otimus-library 0.4.91 → 0.4.93

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.
@@ -1,5 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, Injectable, Input, Directive, input, inject, ElementRef, model, output, HostListener, EventEmitter, Output, ContentChildren, forwardRef, ChangeDetectionStrategy, effect, ContentChild, ViewChildren, ViewChild, ViewEncapsulation, HostBinding, PLATFORM_ID, RendererFactory2, signal, ViewContainerRef, computed, viewChild, booleanAttribute } from '@angular/core';
2
+ import { Component, Injectable, Input, Directive, input, inject, ElementRef, model, output, HostListener, EventEmitter, Output, ContentChildren, forwardRef, ChangeDetectionStrategy, effect, ContentChild, ViewChildren, ViewChild, ViewEncapsulation, HostBinding, PLATFORM_ID, RendererFactory2, signal, ViewContainerRef, computed, viewChild, booleanAttribute, DestroyRef } from '@angular/core';
3
+ import { Subject, filter } from 'rxjs';
3
4
  import * as i2$1 from '@angular/cdk/menu';
4
5
  import { CdkMenuModule } from '@angular/cdk/menu';
5
6
  import * as i1 from '@angular/common';
@@ -12,10 +13,10 @@ import * as i3 from '@angular/cdk/overlay';
12
13
  import { Overlay, OverlayPositionBuilder } from '@angular/cdk/overlay';
13
14
  import * as i1$2 from '@angular/router';
14
15
  import { RouterModule } from '@angular/router';
15
- import { filter } from 'rxjs';
16
16
  import * as i2$2 from '@angular/platform-browser';
17
17
  import * as i2$3 from '@angular/cdk/table';
18
18
  import { CdkTableModule } from '@angular/cdk/table';
19
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
19
20
 
20
21
  class OtimusLibraryComponent {
21
22
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: OtimusLibraryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
@@ -48,73 +49,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
48
49
 
49
50
  class OcToastService {
50
51
  constructor() {
51
- this.toastList = [];
52
- this.isRunning = false;
52
+ this.nextId = 1;
53
+ /** Emits each toast opened via `openToast`. Rendered by `OcToastComponent`. */
54
+ this.opened = new Subject();
55
+ this.opened$ = this.opened.asObservable();
53
56
  this.openToast = (toastStatus, toastMessage, toastCounter, promiseKey) => {
54
57
  const toast = {
55
- id: this.toastList.length === 0 ? 1 : this.toastList[this.toastList.length - 1].id + 1,
58
+ id: this.nextId++,
56
59
  counter: toastCounter || 5,
57
60
  status: toastStatus,
58
61
  message: toastMessage,
59
62
  promiseKey,
60
63
  hasAnimation: true,
61
64
  };
62
- const toastExists = this.toastList.some((to) => {
63
- return to.status === toastStatus && to.message === toastMessage;
64
- });
65
- if (toastExists) {
66
- return;
67
- }
68
- const keyExists = this.toastList.find((to) => to.promiseKey === toast.promiseKey);
69
- if (keyExists) {
70
- this.toastList = this.toastList.map((to) => {
71
- if (to.promiseKey === promiseKey) {
72
- return { ...toast, hasAnimation: false };
73
- }
74
- return to;
75
- });
76
- }
77
- this.toastList.push(toast);
78
- if (!this.isRunning) {
79
- this.renderToasts();
80
- }
65
+ this.opened.next(toast);
81
66
  };
82
67
  }
83
- closeToast(id) {
84
- this.toastList = this.toastList.map((to) => {
85
- if (to.id === id) {
86
- return { ...to, counter: 0 };
87
- }
88
- return to;
89
- });
90
- this.currentToast = this.toastList[0];
91
- }
92
- renderToasts() {
93
- if (this.toastList.length === 0) {
94
- this.isRunning = false;
95
- return;
96
- }
97
- this.isRunning = true;
98
- this.currentToast = this.toastList[0];
99
- const toastInterval = setInterval(() => {
100
- if (this.toastList.length === 0) {
101
- clearInterval(toastInterval);
102
- this.isRunning = false;
103
- return;
104
- }
105
- this.currentToast = this.toastList[0];
106
- if (this.currentToast.status !== 'carregando') {
107
- this.currentToast.counter--;
108
- }
109
- if (this.currentToast.counter <= 0) {
110
- this.toastList = this.toastList.filter((to) => {
111
- return to.status !== this.currentToast.status && to.message !== this.currentToast.message;
112
- });
113
- clearInterval(toastInterval);
114
- this.renderToasts();
115
- }
116
- }, 1000);
117
- }
118
68
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: OcToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
119
69
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: OcToastService, providedIn: 'root' }); }
120
70
  }
@@ -1259,8 +1209,6 @@ class OcAutocompleteComponent {
1259
1209
  this.ocOptionNotFound = new EventEmitter();
1260
1210
  this.ocClick = new EventEmitter();
1261
1211
  this.ocHiddenChipsCountChange = new EventEmitter();
1262
- this.hasSuffix = false;
1263
- this.hasPrefix = false;
1264
1212
  this.selectedValues = [];
1265
1213
  this.hiddenChipsCount = 0;
1266
1214
  this._autoVisibleChipCount = null;
@@ -1303,6 +1251,12 @@ class OcAutocompleteComponent {
1303
1251
  get ocStyle() {
1304
1252
  return this._ocStyle || this.styleThemeService.getStyleTheme() || 'otimus';
1305
1253
  }
1254
+ get hasPrefix() {
1255
+ return !!this.ocPrefix;
1256
+ }
1257
+ get hasSuffix() {
1258
+ return !!this.ocSuffix || !!this.ocHasDeleteButton;
1259
+ }
1306
1260
  static { this.MIN_TYPING_SPACE_PX = 100; }
1307
1261
  static { this.MORE_CHIP_RESERVE_PX = 50; }
1308
1262
  static { this.CONTAINER_HORIZONTAL_PADDING_PX = 28; }
@@ -1370,12 +1324,6 @@ class OcAutocompleteComponent {
1370
1324
  return this.ocMaxWidth || '100%';
1371
1325
  }
1372
1326
  ngOnChanges(changes) {
1373
- if (this.ocPrefix) {
1374
- this.hasPrefix = true;
1375
- }
1376
- if (this.ocSuffix) {
1377
- this.hasSuffix = true;
1378
- }
1379
1327
  this.formatOcValueType();
1380
1328
  this.loadOptions();
1381
1329
  // Sync ocLoading to dropdown portal when it changes
@@ -1394,15 +1342,6 @@ class OcAutocompleteComponent {
1394
1342
  this.ocValue = null;
1395
1343
  }
1396
1344
  }
1397
- ngAfterContentInit() {
1398
- // Set prefix/suffix flags after content has been initialized
1399
- if (this.ocPrefix) {
1400
- this.hasPrefix = true;
1401
- }
1402
- if (this.ocSuffix) {
1403
- this.hasSuffix = true;
1404
- }
1405
- }
1406
1345
  ngAfterViewInit() {
1407
1346
  this.formatOcValueType();
1408
1347
  this.loadOptions();
@@ -4606,17 +4545,137 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
4606
4545
  args: [{ selector: 'oc-notification', standalone: true, imports: [CommonModule], template: "<div\n #card\n class=\"oc-notif\"\n [ngClass]=\"{\n closing: closing(),\n 'swiped-out': swipedOut(),\n dragging: drag().active,\n clickable: ocClickable()\n }\"\n [ngStyle]=\"styleVars()\"\n (click)=\"onClick()\"\n (pointerdown)=\"onPointerDown($event)\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerup)=\"onPointerUp($event)\"\n (pointercancel)=\"onPointerUp($event)\"\n>\n <div class=\"oc-notif-avatar-slot\">\n <ng-content select=\"[ocNotificationAvatar]\"></ng-content>\n </div>\n\n <div class=\"oc-notif-body\">\n <div class=\"oc-notif-kind\">\n <ng-content select=\"[ocNotificationKind]\"></ng-content>\n </div>\n <div class=\"oc-notif-row1\">\n <span class=\"oc-notif-name\">\n <ng-content select=\"[ocNotificationTitle]\"></ng-content>\n </span>\n </div>\n <div class=\"oc-notif-msg\">\n <ng-content></ng-content>\n </div>\n <div class=\"oc-notif-badge-slot\">\n <ng-content select=\"[ocNotificationBadge]\"></ng-content>\n </div>\n </div>\n\n <div class=\"oc-notif-actions\">\n <span class=\"oc-notif-meta\">\n <ng-content select=\"[ocNotificationTime]\"></ng-content>\n </span>\n @if (ocClosable()) {\n <button\n class=\"oc-notif-close\"\n type=\"button\"\n [attr.aria-label]=\"ocCloseLabel()\"\n [title]=\"ocCloseLabel()\"\n (click)=\"onCloseClick($event)\"\n >\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n }\n </div>\n</div>\n", styles: [":host{display:block}.oc-notif{position:relative;display:flex;align-items:flex-start;gap:10px;background:#f8f9ff;border:1px solid rgba(85,5,162,.25);border-radius:var(--notif-radius, 14px);padding:10px 72px 10px 10px;box-shadow:0 1px 3px #1e08320a,0 1px 1px #1e083205;-webkit-user-select:none;user-select:none;transition:transform .2s cubic-bezier(.2,.9,.2,1.05),box-shadow .2s ease,background .2s ease;touch-action:pan-y}.oc-notif.clickable{cursor:pointer}.oc-notif:hover{transform:translateY(-1px);background:#f8f9ff;box-shadow:0 3px 8px -2px #1e08320f,0 1px 2px #1e083208}.oc-notif.closing{animation:ocnSlideOut .28s cubic-bezier(.4,0,1,1) forwards;pointer-events:none}.oc-notif.dragging{transition:none}.oc-notif.swiped-out{animation:ocnSwipeOut .24s cubic-bezier(.4,0,1,1) forwards;pointer-events:none}@keyframes ocnSlideOut{to{opacity:0;transform:translate(60px) scale(.94)}}@keyframes ocnSwipeOut{to{opacity:0;transform:translate(var(--swipe-out-x, -120%)) scale(.9)}}.oc-notif-avatar-slot{flex:0 0 auto;display:flex;align-items:center;justify-content:center}.oc-notif-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px}.oc-notif-kind{font-size:10px;font-weight:400;color:#8f9596;letter-spacing:.1px;line-height:1.2;margin-bottom:1px}.oc-notif-kind:empty{display:none}.oc-notif-row1{display:flex;align-items:baseline;gap:6px;min-width:0}.oc-notif-name{font-size:12.5px;font-weight:700;color:#1e0832;line-height:1.25;letter-spacing:-.1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1 1 auto;min-width:0}.oc-notif-meta{font-size:10.5px;font-weight:500;color:#8f9596;white-space:nowrap;line-height:1}.oc-notif-meta:empty{display:none}.oc-notif-msg{font-size:12px;color:#353535;line-height:1.4;margin-top:3px;word-break:break-word;display:-webkit-box;-webkit-line-clamp:var(--notif-line-clamp, 2);line-clamp:var(--notif-line-clamp, 2);-webkit-box-orient:vertical;overflow:hidden}.oc-notif-msg:empty{display:none}.oc-notif-badge-slot:empty{display:none}.oc-notif-actions{position:absolute;top:8px;right:8px;display:flex;align-items:center;gap:6px;z-index:2}.oc-notif-close{width:20px;height:20px;border-radius:6px;border:0;background:transparent;color:#8f9596;cursor:pointer;display:grid;place-items:center;transition:background .15s ease,color .15s ease}.oc-notif-close:hover{background:#f7f7f7;color:#353535}.oc-notif-close .material-symbols-outlined{font-size:13px}\n"] }]
4607
4546
  }], propDecorators: { ocClosable: [{ type: i0.Input, args: [{ isSignal: true, alias: "ocClosable", required: false }] }], ocClickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "ocClickable", required: false }] }], ocSwipeable: [{ type: i0.Input, args: [{ isSignal: true, alias: "ocSwipeable", required: false }] }], ocSwipeDirection: [{ type: i0.Input, args: [{ isSignal: true, alias: "ocSwipeDirection", required: false }] }], ocBorderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "ocBorderRadius", required: false }] }], ocLineClamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "ocLineClamp", required: false }] }], ocCloseLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ocCloseLabel", required: false }] }], ocClose: [{ type: i0.Output, args: ["ocClose"] }], ocClick: [{ type: i0.Output, args: ["ocClick"] }], card: [{ type: i0.ViewChild, args: ['card', { isSignal: true }] }] } });
4608
4547
 
4548
+ const STATUS_CONF = {
4549
+ sucesso: { cssKey: 'sucesso', icon: 'check_circle' },
4550
+ success: { cssKey: 'sucesso', icon: 'check_circle' },
4551
+ éxito: { cssKey: 'sucesso', icon: 'check_circle' },
4552
+ erro: { cssKey: 'erro', icon: 'error' },
4553
+ error: { cssKey: 'erro', icon: 'error' },
4554
+ informação: { cssKey: 'info', icon: 'info' },
4555
+ informacao: { cssKey: 'info', icon: 'info' },
4556
+ información: { cssKey: 'info', icon: 'info' },
4557
+ information: { cssKey: 'info', icon: 'info' },
4558
+ carregando: { cssKey: 'loading', icon: 'progress_activity' },
4559
+ cargando: { cssKey: 'loading', icon: 'progress_activity' },
4560
+ loading: { cssKey: 'loading', icon: 'progress_activity' },
4561
+ };
4562
+ const DEFAULT_CONF = { cssKey: 'info', icon: 'info' };
4563
+ const MAX_VISIBLE = 3;
4564
+ /** Must match the `oc-toast-out` animation duration in the scss. */
4565
+ const LEAVE_MS = 240;
4566
+ /**
4567
+ * Center-bottom toast stack, drawer-safe (renders above the `oc-drawer` scrim
4568
+ * at `z-index: 1100`). Mount a single instance at the application root, e.g.
4569
+ * `<oc-toast />`.
4570
+ *
4571
+ * Toasts are triggered through `OcToastService.openToast(...)`. Renders a pill
4572
+ * with the status-tint palette, stacks up to 3 (oldest on top), auto-dismisses
4573
+ * after the per-toast countdown (loading persists), pauses the countdown while
4574
+ * hovered, replaces a `promiseKey` toast in place (loading → result) and
4575
+ * de-dupes identical status+message toasts by renewing their timer.
4576
+ */
4609
4577
  class OcToastComponent {
4610
- constructor(toast) {
4611
- this.toast = toast;
4578
+ constructor() {
4579
+ this.toastService = inject(OcToastService);
4580
+ this.destroyRef = inject(DestroyRef);
4581
+ /** Visible + leaving toasts, ordered oldest → newest. */
4582
+ this.toasts = signal([], ...(ngDevMode ? [{ debugName: "toasts" }] : []));
4583
+ /** True while the pointer hovers the stack — freezes every countdown. */
4584
+ this.paused = signal(false, ...(ngDevMode ? [{ debugName: "paused" }] : []));
4585
+ /** Removal timers for toasts playing their leave animation. */
4586
+ this.leaveTimers = new Map();
4587
+ /** Single 1s tick drives every countdown so hover-pause is trivial. */
4588
+ this.tick = setInterval(() => this.onTick(), 1000);
4589
+ this.toastService.opened$
4590
+ .pipe(takeUntilDestroyed(this.destroyRef))
4591
+ .subscribe((toast) => this.onOpened(toast));
4592
+ }
4593
+ ngOnDestroy() {
4594
+ clearInterval(this.tick);
4595
+ this.leaveTimers.forEach((timer) => clearTimeout(timer));
4596
+ this.leaveTimers.clear();
4597
+ }
4598
+ /** Maps any status alias to its icon + css key (defaults to info). */
4599
+ resolve(status) {
4600
+ return STATUS_CONF[(status ?? '').toLowerCase()] ?? DEFAULT_CONF;
4601
+ }
4602
+ isLoading(status) {
4603
+ return this.resolve(status).cssKey === 'loading';
4604
+ }
4605
+ /** Older toasts dim slightly; clamps the css `data-stack-pos` to 0..2. */
4606
+ stackPos(index) {
4607
+ return Math.min(this.toasts().length - 1 - index, 2);
4612
4608
  }
4613
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: OcToastComponent, deps: [{ token: OcToastService }], target: i0.ɵɵFactoryTarget.Component }); }
4614
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.9", type: OcToastComponent, isStandalone: true, selector: "oc-toast", ngImport: i0, template: "<div\n class=\"toast\"\n [ngClass]=\"{\n 'close-toast': toast.currentToast.counter === 1,\n error: ['erro', 'error'].includes(toast.currentToast.status.toLowerCase()),\n success: ['sucesso', 'success', '\u00E9xito'].includes(toast.currentToast.status.toLowerCase()),\n loading: ['carregando', 'cargando', 'loading'].includes(toast.currentToast.status.toLowerCase()),\n animation: toast.currentToast.hasAnimation\n }\"\n *ngIf=\"toast.currentToast && toast.currentToast.counter > 0\"\n>\n <header>\n <ng-container [ngTemplateOutlet]=\"iconTemplate\"></ng-container>\n <h4 class=\"status\">\n {{ toast.currentToast.status[0].toUpperCase() + toast.currentToast.status.slice(1) }}\n </h4>\n <button (click)=\"toast.closeToast(toast.currentToast.id)\">\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </header>\n <p>{{ toast.currentToast.message }}</p>\n</div>\n\n<ng-template #iconTemplate>\n <span\n class=\"material-symbols-outlined\"\n *ngIf=\"['erro', 'error'].includes(toast.currentToast.status.toLowerCase())\"\n >error</span\n >\n\n <span\n class=\"material-symbols-outlined\"\n *ngIf=\"['sucesso', 'success', '\u00E9xito'].includes(toast.currentToast.status.toLowerCase())\"\n >check_circle</span\n >\n\n <span\n class=\"material-symbols-outlined\"\n *ngIf=\"['information', 'informa\u00E7\u00E3o', 'informaci\u00F3n'].includes(toast.currentToast.status.toLowerCase())\"\n >info</span\n >\n\n <svg *ngIf=\"['carregando', 'cargando', 'loading'].includes(toast.currentToast.status.toLowerCase())\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><style>rect{fill:#00DDA3}.spinner_zWVm{animation:spinner_5QiW 1.2s linear infinite,spinner_PnZo 1.2s linear infinite}.spinner_gfyD{animation:spinner_5QiW 1.2s linear infinite,spinner_4j7o 1.2s linear infinite;animation-delay:.1s}.spinner_T5JJ{animation:spinner_5QiW 1.2s linear infinite,spinner_fLK4 1.2s linear infinite;animation-delay:.1s}.spinner_E3Wz{animation:spinner_5QiW 1.2s linear infinite,spinner_tDji 1.2s linear infinite;animation-delay:.2s}.spinner_g2vs{animation:spinner_5QiW 1.2s linear infinite,spinner_CMiT 1.2s linear infinite;animation-delay:.2s}.spinner_ctYB{animation:spinner_5QiW 1.2s linear infinite,spinner_cHKR 1.2s linear infinite;animation-delay:.2s}.spinner_BDNj{animation:spinner_5QiW 1.2s linear infinite,spinner_Re6e 1.2s linear infinite;animation-delay:.3s}.spinner_rCw3{animation:spinner_5QiW 1.2s linear infinite,spinner_EJmJ 1.2s linear infinite;animation-delay:.3s}.spinner_Rszm{animation:spinner_5QiW 1.2s linear infinite,spinner_YJOP 1.2s linear infinite;animation-delay:.4s}@keyframes spinner_5QiW{0%,50%{width:7.33px;height:7.33px}25%{width:1.33px;height:1.33px}}@keyframes spinner_PnZo{0%,50%{x:1px;y:1px}25%{x:4px;y:4px}}@keyframes spinner_4j7o{0%,50%{x:8.33px;y:1px}25%{x:11.33px;y:4px}}@keyframes spinner_fLK4{0%,50%{x:1px;y:8.33px}25%{x:4px;y:11.33px}}@keyframes spinner_tDji{0%,50%{x:15.66px;y:1px}25%{x:18.66px;y:4px}}@keyframes spinner_CMiT{0%,50%{x:8.33px;y:8.33px}25%{x:11.33px;y:11.33px}}@keyframes spinner_cHKR{0%,50%{x:1px;y:15.66px}25%{x:4px;y:18.66px}}@keyframes spinner_Re6e{0%,50%{x:15.66px;y:8.33px}25%{x:18.66px;y:11.33px}}@keyframes spinner_EJmJ{0%,50%{x:8.33px;y:15.66px}25%{x:11.33px;y:18.66px}}@keyframes spinner_YJOP{0%,50%{x:15.66px;y:15.66px}25%{x:18.66px;y:18.66px}}</style><rect class=\"spinner_zWVm\" x=\"1\" y=\"1\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_gfyD\" x=\"8.33\" y=\"1\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_T5JJ\" x=\"1\" y=\"8.33\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_E3Wz\" x=\"15.66\" y=\"1\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_g2vs\" x=\"8.33\" y=\"8.33\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_ctYB\" x=\"1\" y=\"15.66\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_BDNj\" x=\"15.66\" y=\"8.33\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_rCw3\" x=\"8.33\" y=\"15.66\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_Rszm\" x=\"15.66\" y=\"15.66\" width=\"7.33\" height=\"7.33\"/></svg>\n \n\n</ng-template>\n", styles: [".toast{position:fixed;bottom:30px;right:30px;width:370px!important;min-height:116px!important;display:flex;flex-direction:column;justify-content:space-between;border-radius:17px;padding:1rem 1rem 1.5rem;box-shadow:8px 16px 32px #0000004d;background-color:#fff;z-index:50}.toast p{color:#625270;font-size:13px}.toast>header{color:#5505a2;display:flex;align-items:center;gap:.5rem}.toast>header>button{position:absolute;right:20px;border:none;background-color:transparent;color:#d1d5db;padding:10px 0 10px 10px;cursor:pointer;transition:.3s ease}.toast>header>button:hover{color:#ed3a3a}.toast>header>.icon{border:4px solid #5505a2;border-radius:50%;width:30px;height:30px}.toast>header h4{margin:0;padding:0;font-size:20px}.animation{animation:show-up .5s ease}.error>header{color:#ed3a3a}.error>header h4{color:#ed3a3a}.success>header{color:#4ab858}.success>header h4{color:#4ab858}.loading>header h4{color:#786b84}.loading>header>img,.loading>header svg{transform:rotate(45deg)}.close-toast{animation:close 1.1s ease}@keyframes show-up{0%{opacity:0;transform:translateY(100vw)}to{opacity:1;transform:translate(0)}}@keyframes close{0%{opacity:1;transform:translate(0)}to{opacity:0;transform:translate(100vw)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.Default }); }
4609
+ /** Plays the leave animation, then drops the toast from the stack. */
4610
+ dismiss(id) {
4611
+ this.toasts.update((list) => list.map((toast) => (toast.id === id ? { ...toast, leaving: true } : toast)));
4612
+ if (this.leaveTimers.has(id)) {
4613
+ return;
4614
+ }
4615
+ const timer = setTimeout(() => {
4616
+ this.toasts.update((list) => list.filter((toast) => toast.id !== id));
4617
+ this.leaveTimers.delete(id);
4618
+ }, LEAVE_MS);
4619
+ this.leaveTimers.set(id, timer);
4620
+ }
4621
+ onOpened(toast) {
4622
+ // A loading toast carrying a promiseKey is later replaced in place by its
4623
+ // result (e.g. carregando → sucesso) — keep its slot rather than stacking.
4624
+ if (toast.promiseKey) {
4625
+ const existing = this.toasts().find((item) => item.promiseKey === toast.promiseKey && !item.leaving);
4626
+ if (existing) {
4627
+ this.toasts.update((list) => list.map((item) => item.id === existing.id
4628
+ ? { ...item, status: toast.status, message: toast.message, counter: toast.counter }
4629
+ : item));
4630
+ return;
4631
+ }
4632
+ }
4633
+ // De-dupe: an identical (status + message) toast already visible just has
4634
+ // its countdown renewed instead of stacking a copy.
4635
+ const duplicate = this.toasts().find((item) => item.status === toast.status && item.message === toast.message && !item.leaving);
4636
+ if (duplicate) {
4637
+ this.toasts.update((list) => list.map((item) => (item.id === duplicate.id ? { ...item, counter: toast.counter } : item)));
4638
+ return;
4639
+ }
4640
+ // Evict the oldest visible toast once the stack is at capacity.
4641
+ const visible = this.toasts().filter((item) => !item.leaving);
4642
+ if (visible.length >= MAX_VISIBLE) {
4643
+ this.dismiss(visible[0].id);
4644
+ }
4645
+ const item = {
4646
+ id: toast.id,
4647
+ status: toast.status,
4648
+ message: toast.message,
4649
+ counter: toast.counter,
4650
+ promiseKey: toast.promiseKey,
4651
+ leaving: false,
4652
+ };
4653
+ this.toasts.update((list) => [...list, item]);
4654
+ }
4655
+ onTick() {
4656
+ if (this.paused()) {
4657
+ return;
4658
+ }
4659
+ const expired = [];
4660
+ this.toasts.update((list) => list.map((toast) => {
4661
+ if (toast.leaving || this.isLoading(toast.status)) {
4662
+ return toast;
4663
+ }
4664
+ const counter = toast.counter - 1;
4665
+ if (counter <= 0) {
4666
+ expired.push(toast.id);
4667
+ }
4668
+ return { ...toast, counter };
4669
+ }));
4670
+ expired.forEach((id) => this.dismiss(id));
4671
+ }
4672
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: OcToastComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4673
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: OcToastComponent, isStandalone: true, selector: "oc-toast", ngImport: i0, template: "<div\n class=\"oc-toast-stack\"\n (mouseenter)=\"paused.set(true)\"\n (mouseleave)=\"paused.set(false)\"\n>\n @for (toast of toasts(); track toast.id; let i = $index) {\n <div\n class=\"oc-toast status-{{ resolve(toast.status).cssKey }}\"\n [class.is-leaving]=\"toast.leaving\"\n [attr.data-stack-pos]=\"stackPos(i)\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <span class=\"oc-toast-icon\">\n @if (isLoading(toast.status)) {\n <span\n class=\"oc-toast-spinner\"\n aria-hidden=\"true\"\n ></span>\n } @else {\n <span class=\"material-symbols-outlined\">{{ resolve(toast.status).icon }}</span>\n }\n </span>\n\n <span class=\"oc-toast-msg\">{{ toast.message }}</span>\n\n <button\n class=\"oc-toast-close\"\n type=\"button\"\n aria-label=\"Fechar\"\n (click)=\"dismiss(toast.id)\"\n >\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.oc-toast-stack{position:fixed;left:50%;bottom:24px;transform:translate(-50%);display:flex;flex-direction:column;align-items:center;gap:10px;z-index:1100;pointer-events:none;width:max-content;max-width:calc(100% - 48px)}.oc-toast-stack>*{pointer-events:auto}@keyframes oc-toast-in{0%{opacity:0;transform:translateY(28px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes oc-toast-out{0%{opacity:1;transform:translateY(0) scale(1);max-height:200px;margin-top:0}to{opacity:0;transform:translateY(16px) scale(.96);max-height:0;margin-top:-10px}}.oc-toast{display:flex;align-items:center;gap:10px;min-width:280px;max-width:520px;padding:10px 6px 10px 14px;border:1px solid;border-radius:999px;box-shadow:0 12px 28px #1e08321a,0 3px 8px #1e08320d;font-family:Ubuntu,sans-serif;-webkit-user-select:none;user-select:none;animation:oc-toast-in .32s cubic-bezier(.2,.9,.2,1)}.oc-toast.is-leaving{animation:oc-toast-out .24s ease forwards;pointer-events:none}.oc-toast[data-stack-pos=\"1\"]{opacity:.94}.oc-toast[data-stack-pos=\"2\"]{opacity:.84}.oc-toast.status-sucesso{background:#e6fbf4;border-color:#b7efdb;color:#08643d}.oc-toast.status-erro{background:#fde9e9;border-color:#f5bfbf;color:#7a1717}.oc-toast.status-info,.oc-toast.status-loading{background:#f2eaf9;border-color:#dcc8ee;color:#3d0676}.oc-toast-icon{flex-shrink:0;display:grid;place-items:center}.oc-toast-icon .material-symbols-outlined{font-size:20px}.oc-toast-msg{flex:1;min-width:0;font-size:14px;line-height:1.4;font-weight:400;text-wrap:pretty;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.oc-toast-close{flex-shrink:0;display:grid;place-items:center;width:28px;height:28px;border:0;border-radius:50%;background:transparent;color:inherit;opacity:.55;cursor:pointer;transition:opacity .15s ease,background .15s ease}.oc-toast-close:hover{opacity:1;background:#0000000f}.oc-toast-close .material-symbols-outlined{font-size:18px}.oc-toast-spinner{width:20px;height:20px;border:2.5px solid currentColor;border-right-color:transparent;border-radius:50%;opacity:.9;animation:oc-toast-spin .85s linear infinite}@keyframes oc-toast-spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.oc-toast,.oc-toast.is-leaving{animation:none}.oc-toast-spinner{animation-duration:1.6s}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4615
4674
  }
4616
4675
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: OcToastComponent, decorators: [{
4617
4676
  type: Component,
4618
- args: [{ selector: 'oc-toast', imports: [CommonModule], changeDetection: ChangeDetectionStrategy.Default, template: "<div\n class=\"toast\"\n [ngClass]=\"{\n 'close-toast': toast.currentToast.counter === 1,\n error: ['erro', 'error'].includes(toast.currentToast.status.toLowerCase()),\n success: ['sucesso', 'success', '\u00E9xito'].includes(toast.currentToast.status.toLowerCase()),\n loading: ['carregando', 'cargando', 'loading'].includes(toast.currentToast.status.toLowerCase()),\n animation: toast.currentToast.hasAnimation\n }\"\n *ngIf=\"toast.currentToast && toast.currentToast.counter > 0\"\n>\n <header>\n <ng-container [ngTemplateOutlet]=\"iconTemplate\"></ng-container>\n <h4 class=\"status\">\n {{ toast.currentToast.status[0].toUpperCase() + toast.currentToast.status.slice(1) }}\n </h4>\n <button (click)=\"toast.closeToast(toast.currentToast.id)\">\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </header>\n <p>{{ toast.currentToast.message }}</p>\n</div>\n\n<ng-template #iconTemplate>\n <span\n class=\"material-symbols-outlined\"\n *ngIf=\"['erro', 'error'].includes(toast.currentToast.status.toLowerCase())\"\n >error</span\n >\n\n <span\n class=\"material-symbols-outlined\"\n *ngIf=\"['sucesso', 'success', '\u00E9xito'].includes(toast.currentToast.status.toLowerCase())\"\n >check_circle</span\n >\n\n <span\n class=\"material-symbols-outlined\"\n *ngIf=\"['information', 'informa\u00E7\u00E3o', 'informaci\u00F3n'].includes(toast.currentToast.status.toLowerCase())\"\n >info</span\n >\n\n <svg *ngIf=\"['carregando', 'cargando', 'loading'].includes(toast.currentToast.status.toLowerCase())\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><style>rect{fill:#00DDA3}.spinner_zWVm{animation:spinner_5QiW 1.2s linear infinite,spinner_PnZo 1.2s linear infinite}.spinner_gfyD{animation:spinner_5QiW 1.2s linear infinite,spinner_4j7o 1.2s linear infinite;animation-delay:.1s}.spinner_T5JJ{animation:spinner_5QiW 1.2s linear infinite,spinner_fLK4 1.2s linear infinite;animation-delay:.1s}.spinner_E3Wz{animation:spinner_5QiW 1.2s linear infinite,spinner_tDji 1.2s linear infinite;animation-delay:.2s}.spinner_g2vs{animation:spinner_5QiW 1.2s linear infinite,spinner_CMiT 1.2s linear infinite;animation-delay:.2s}.spinner_ctYB{animation:spinner_5QiW 1.2s linear infinite,spinner_cHKR 1.2s linear infinite;animation-delay:.2s}.spinner_BDNj{animation:spinner_5QiW 1.2s linear infinite,spinner_Re6e 1.2s linear infinite;animation-delay:.3s}.spinner_rCw3{animation:spinner_5QiW 1.2s linear infinite,spinner_EJmJ 1.2s linear infinite;animation-delay:.3s}.spinner_Rszm{animation:spinner_5QiW 1.2s linear infinite,spinner_YJOP 1.2s linear infinite;animation-delay:.4s}@keyframes spinner_5QiW{0%,50%{width:7.33px;height:7.33px}25%{width:1.33px;height:1.33px}}@keyframes spinner_PnZo{0%,50%{x:1px;y:1px}25%{x:4px;y:4px}}@keyframes spinner_4j7o{0%,50%{x:8.33px;y:1px}25%{x:11.33px;y:4px}}@keyframes spinner_fLK4{0%,50%{x:1px;y:8.33px}25%{x:4px;y:11.33px}}@keyframes spinner_tDji{0%,50%{x:15.66px;y:1px}25%{x:18.66px;y:4px}}@keyframes spinner_CMiT{0%,50%{x:8.33px;y:8.33px}25%{x:11.33px;y:11.33px}}@keyframes spinner_cHKR{0%,50%{x:1px;y:15.66px}25%{x:4px;y:18.66px}}@keyframes spinner_Re6e{0%,50%{x:15.66px;y:8.33px}25%{x:18.66px;y:11.33px}}@keyframes spinner_EJmJ{0%,50%{x:8.33px;y:15.66px}25%{x:11.33px;y:18.66px}}@keyframes spinner_YJOP{0%,50%{x:15.66px;y:15.66px}25%{x:18.66px;y:18.66px}}</style><rect class=\"spinner_zWVm\" x=\"1\" y=\"1\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_gfyD\" x=\"8.33\" y=\"1\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_T5JJ\" x=\"1\" y=\"8.33\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_E3Wz\" x=\"15.66\" y=\"1\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_g2vs\" x=\"8.33\" y=\"8.33\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_ctYB\" x=\"1\" y=\"15.66\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_BDNj\" x=\"15.66\" y=\"8.33\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_rCw3\" x=\"8.33\" y=\"15.66\" width=\"7.33\" height=\"7.33\"/><rect class=\"spinner_Rszm\" x=\"15.66\" y=\"15.66\" width=\"7.33\" height=\"7.33\"/></svg>\n \n\n</ng-template>\n", styles: [".toast{position:fixed;bottom:30px;right:30px;width:370px!important;min-height:116px!important;display:flex;flex-direction:column;justify-content:space-between;border-radius:17px;padding:1rem 1rem 1.5rem;box-shadow:8px 16px 32px #0000004d;background-color:#fff;z-index:50}.toast p{color:#625270;font-size:13px}.toast>header{color:#5505a2;display:flex;align-items:center;gap:.5rem}.toast>header>button{position:absolute;right:20px;border:none;background-color:transparent;color:#d1d5db;padding:10px 0 10px 10px;cursor:pointer;transition:.3s ease}.toast>header>button:hover{color:#ed3a3a}.toast>header>.icon{border:4px solid #5505a2;border-radius:50%;width:30px;height:30px}.toast>header h4{margin:0;padding:0;font-size:20px}.animation{animation:show-up .5s ease}.error>header{color:#ed3a3a}.error>header h4{color:#ed3a3a}.success>header{color:#4ab858}.success>header h4{color:#4ab858}.loading>header h4{color:#786b84}.loading>header>img,.loading>header svg{transform:rotate(45deg)}.close-toast{animation:close 1.1s ease}@keyframes show-up{0%{opacity:0;transform:translateY(100vw)}to{opacity:1;transform:translate(0)}}@keyframes close{0%{opacity:1;transform:translate(0)}to{opacity:0;transform:translate(100vw)}}\n"] }]
4619
- }], ctorParameters: () => [{ type: OcToastService }] });
4677
+ args: [{ selector: 'oc-toast', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"oc-toast-stack\"\n (mouseenter)=\"paused.set(true)\"\n (mouseleave)=\"paused.set(false)\"\n>\n @for (toast of toasts(); track toast.id; let i = $index) {\n <div\n class=\"oc-toast status-{{ resolve(toast.status).cssKey }}\"\n [class.is-leaving]=\"toast.leaving\"\n [attr.data-stack-pos]=\"stackPos(i)\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <span class=\"oc-toast-icon\">\n @if (isLoading(toast.status)) {\n <span\n class=\"oc-toast-spinner\"\n aria-hidden=\"true\"\n ></span>\n } @else {\n <span class=\"material-symbols-outlined\">{{ resolve(toast.status).icon }}</span>\n }\n </span>\n\n <span class=\"oc-toast-msg\">{{ toast.message }}</span>\n\n <button\n class=\"oc-toast-close\"\n type=\"button\"\n aria-label=\"Fechar\"\n (click)=\"dismiss(toast.id)\"\n >\n <span class=\"material-symbols-outlined\">close</span>\n </button>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.oc-toast-stack{position:fixed;left:50%;bottom:24px;transform:translate(-50%);display:flex;flex-direction:column;align-items:center;gap:10px;z-index:1100;pointer-events:none;width:max-content;max-width:calc(100% - 48px)}.oc-toast-stack>*{pointer-events:auto}@keyframes oc-toast-in{0%{opacity:0;transform:translateY(28px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes oc-toast-out{0%{opacity:1;transform:translateY(0) scale(1);max-height:200px;margin-top:0}to{opacity:0;transform:translateY(16px) scale(.96);max-height:0;margin-top:-10px}}.oc-toast{display:flex;align-items:center;gap:10px;min-width:280px;max-width:520px;padding:10px 6px 10px 14px;border:1px solid;border-radius:999px;box-shadow:0 12px 28px #1e08321a,0 3px 8px #1e08320d;font-family:Ubuntu,sans-serif;-webkit-user-select:none;user-select:none;animation:oc-toast-in .32s cubic-bezier(.2,.9,.2,1)}.oc-toast.is-leaving{animation:oc-toast-out .24s ease forwards;pointer-events:none}.oc-toast[data-stack-pos=\"1\"]{opacity:.94}.oc-toast[data-stack-pos=\"2\"]{opacity:.84}.oc-toast.status-sucesso{background:#e6fbf4;border-color:#b7efdb;color:#08643d}.oc-toast.status-erro{background:#fde9e9;border-color:#f5bfbf;color:#7a1717}.oc-toast.status-info,.oc-toast.status-loading{background:#f2eaf9;border-color:#dcc8ee;color:#3d0676}.oc-toast-icon{flex-shrink:0;display:grid;place-items:center}.oc-toast-icon .material-symbols-outlined{font-size:20px}.oc-toast-msg{flex:1;min-width:0;font-size:14px;line-height:1.4;font-weight:400;text-wrap:pretty;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.oc-toast-close{flex-shrink:0;display:grid;place-items:center;width:28px;height:28px;border:0;border-radius:50%;background:transparent;color:inherit;opacity:.55;cursor:pointer;transition:opacity .15s ease,background .15s ease}.oc-toast-close:hover{opacity:1;background:#0000000f}.oc-toast-close .material-symbols-outlined{font-size:18px}.oc-toast-spinner{width:20px;height:20px;border:2.5px solid currentColor;border-right-color:transparent;border-radius:50%;opacity:.9;animation:oc-toast-spin .85s linear infinite}@keyframes oc-toast-spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.oc-toast,.oc-toast.is-leaving{animation:none}.oc-toast-spinner{animation-duration:1.6s}}\n"] }]
4678
+ }], ctorParameters: () => [] });
4620
4679
 
4621
4680
  class OcToggleComponent {
4622
4681
  constructor() {