ngx-opalbytes-components 1.16.0 → 1.17.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.
@@ -1,7 +1,7 @@
1
1
  import * as i1 from '@angular/common';
2
- import { CommonModule, NgOptimizedImage, isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
2
+ import { CommonModule, isPlatformBrowser, NgTemplateOutlet, NgOptimizedImage } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
- import { EventEmitter, Input, Output, Component, ViewChild, inject, ElementRef, forwardRef, ChangeDetectionStrategy, ViewEncapsulation, NgModule, Injectable, ContentChildren, Directive, TemplateRef, ContentChild, signal, PLATFORM_ID, ViewChildren, HostBinding } from '@angular/core';
4
+ import { EventEmitter, Input, Output, Component, ViewChild, inject, ElementRef, forwardRef, ChangeDetectionStrategy, ViewEncapsulation, NgModule, ContentChildren, Directive, TemplateRef, ContentChild, signal, PLATFORM_ID, ViewChildren, HostBinding, Injectable } from '@angular/core';
5
5
  import * as i3 from '@angular/material/tooltip';
6
6
  import { MatTooltipModule } from '@angular/material/tooltip';
7
7
  import { LucideDynamicIcon } from '@lucide/angular';
@@ -16,7 +16,7 @@ import * as i4 from '@angular/material/input';
16
16
  import { MatInputModule } from '@angular/material/input';
17
17
  import * as i5 from '@angular/material/autocomplete';
18
18
  import { MatAutocompleteModule, MatAutocompleteTrigger } from '@angular/material/autocomplete';
19
- import { BehaviorSubject, combineLatest, startWith, map, Subject, Subscription } from 'rxjs';
19
+ import { BehaviorSubject, combineLatest, startWith, map, Subscription, Subject } from 'rxjs';
20
20
  import * as i4$1 from '@angular/material/icon';
21
21
  import { MatIconModule } from '@angular/material/icon';
22
22
  import { Router, ActivatedRoute } from '@angular/router';
@@ -1233,696 +1233,559 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
1233
1233
  type: Output
1234
1234
  }] } });
1235
1235
 
1236
- class BaseModalService {
1237
- constructor() { }
1238
- toggleModalEvent = new EventEmitter();
1239
- closeAllModalsEvent = new EventEmitter();
1240
- openModal = new EventEmitter();
1241
- modalResultSubject = new Subject();
1242
- emitModalResult(result) {
1243
- this.modalResultSubject.next(result);
1244
- }
1245
- onModalResult() {
1246
- return this.modalResultSubject.asObservable();
1247
- }
1248
- toggleModal(modalInfo) {
1249
- this.toggleModalEvent.emit(modalInfo);
1250
- }
1251
- closeAllModals() {
1252
- this.closeAllModalsEvent.emit(true);
1253
- }
1254
- showModal(_selectedModal, data) {
1255
- this.closeAllModals();
1256
- const modalInfo = {
1257
- type: _selectedModal,
1258
- data: data,
1259
- status: true,
1260
- };
1261
- this.openModal.emit(modalInfo);
1262
- }
1263
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseModalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1264
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseModalService, providedIn: "root" });
1265
- }
1266
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseModalService, decorators: [{
1267
- type: Injectable,
1268
- args: [{
1269
- providedIn: "root",
1270
- }]
1271
- }], ctorParameters: () => [], propDecorators: { toggleModalEvent: [{
1272
- type: Output
1273
- }], closeAllModalsEvent: [{
1274
- type: Output
1275
- }], openModal: [{
1276
- type: Output
1277
- }] } });
1278
-
1279
- class BaseModal {
1280
- showModal = false;
1236
+ class StepComponent {
1281
1237
  title = "";
1282
- data;
1283
- modalTypeClass = "default";
1284
- modalClass = "modal-default";
1285
- modalSize = "w-70";
1286
- closeOnOverlayClick = false;
1287
- modalService = inject(BaseModalService);
1288
- closeModals() { }
1289
- closeModalsWithoutDialog() {
1290
- this.modalService.closeAllModals();
1291
- }
1292
- onOverlayClick() {
1293
- if (this.closeOnOverlayClick) {
1294
- this.closeModals();
1295
- }
1296
- }
1297
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
1298
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: BaseModal, isStandalone: true, selector: "cao-modal", inputs: { showModal: "showModal", title: "title", data: "data", modalTypeClass: "modalTypeClass", modalClass: "modalClass", modalSize: "modalSize", closeOnOverlayClick: "closeOnOverlayClick" }, ngImport: i0, template: "<div aria-hidden=\"true\" class=\"modal\" tabIndex=\"0\" [class.show]=\"showModal\" (keydown)=\"onOverlayClick()\"\n (click)=\"onOverlayClick()\">\n <div aria-hidden=\"true\" class=\"modal-dialog\" tabIndex=\"1\" [ngClass]=\"[modalSize, modalClass]\"\n (keydown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n</div>", styles: [".modal{width:100vw;height:100vh;align-items:center;justify-content:center;position:fixed;transition:.5s;top:-100vh;left:0}.modal .modal-dialog{padding:24px 34px;border-radius:20px;position:relative;max-width:1444px;height:auto;top:-100vh;transition:.5s;background-color:var(--bg-card);left:0}.modal .modal-dialog.custom{padding:0}.modal .modal-dialog.w-100{width:100%}.modal .modal-dialog.w-90{width:90%}.modal .modal-dialog.w-80{width:80%}.modal .modal-dialog.w-75{width:75%}.modal .modal-dialog.w-70{width:70%}.modal .modal-dialog.w-60{width:60%}.modal .modal-dialog.w-50{width:50%}.modal .modal-dialog.w-40{width:40%}.modal .modal-dialog.w-30{width:30%}.modal .modal-dialog.w-20{width:20%}.modal .modal-dialog.w-10{width:10%}.modal.show{z-index:1000;display:flex;top:0;background-color:#00000080}.modal.show .modal-dialog{top:0}@media(max-width:768px){.modal-dialog{width:90%;max-width:90vw;margin-left:0}}@media(min-width:769px){.modal-dialog{width:75%;margin-left:250px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
1238
+ isActive = false;
1239
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: StepComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1240
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: StepComponent, isStandalone: true, selector: "cao-step", inputs: { title: "title", isActive: "isActive" }, ngImport: i0, template: "<div class=\"step d-flex aic jcc\" [ngClass]=\"{'active': isActive}\"> {{ title }} </div>\n", styles: [".step{width:44px;height:44px;border-radius:100%;font-size:18px;font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
1299
1241
  }
1300
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseModal, decorators: [{
1242
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: StepComponent, decorators: [{
1301
1243
  type: Component,
1302
- args: [{ selector: 'cao-modal', imports: [CommonModule], template: "<div aria-hidden=\"true\" class=\"modal\" tabIndex=\"0\" [class.show]=\"showModal\" (keydown)=\"onOverlayClick()\"\n (click)=\"onOverlayClick()\">\n <div aria-hidden=\"true\" class=\"modal-dialog\" tabIndex=\"1\" [ngClass]=\"[modalSize, modalClass]\"\n (keydown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n</div>", styles: [".modal{width:100vw;height:100vh;align-items:center;justify-content:center;position:fixed;transition:.5s;top:-100vh;left:0}.modal .modal-dialog{padding:24px 34px;border-radius:20px;position:relative;max-width:1444px;height:auto;top:-100vh;transition:.5s;background-color:var(--bg-card);left:0}.modal .modal-dialog.custom{padding:0}.modal .modal-dialog.w-100{width:100%}.modal .modal-dialog.w-90{width:90%}.modal .modal-dialog.w-80{width:80%}.modal .modal-dialog.w-75{width:75%}.modal .modal-dialog.w-70{width:70%}.modal .modal-dialog.w-60{width:60%}.modal .modal-dialog.w-50{width:50%}.modal .modal-dialog.w-40{width:40%}.modal .modal-dialog.w-30{width:30%}.modal .modal-dialog.w-20{width:20%}.modal .modal-dialog.w-10{width:10%}.modal.show{z-index:1000;display:flex;top:0;background-color:#00000080}.modal.show .modal-dialog{top:0}@media(max-width:768px){.modal-dialog{width:90%;max-width:90vw;margin-left:0}}@media(min-width:769px){.modal-dialog{width:75%;margin-left:250px}}\n"] }]
1303
- }], propDecorators: { showModal: [{
1304
- type: Input
1305
- }], title: [{
1306
- type: Input
1307
- }], data: [{
1308
- type: Input
1309
- }], modalTypeClass: [{
1310
- type: Input
1311
- }], modalClass: [{
1312
- type: Input
1313
- }], modalSize: [{
1244
+ args: [{ selector: "cao-step", standalone: true, imports: [CommonModule], template: "<div class=\"step d-flex aic jcc\" [ngClass]=\"{'active': isActive}\"> {{ title }} </div>\n", styles: [".step{width:44px;height:44px;border-radius:100%;font-size:18px;font-weight:700}\n"] }]
1245
+ }], propDecorators: { title: [{
1314
1246
  type: Input
1315
- }], closeOnOverlayClick: [{
1247
+ }], isActive: [{
1316
1248
  type: Input
1317
1249
  }] } });
1318
1250
 
1319
- class BaseDialog {
1320
- config;
1321
- closeDialog = this.noop;
1322
- iconPaths = {
1323
- success: "https://placehold.co/600x400",
1324
- error: "https://placehold.co/600x400",
1325
- info: "https://placehold.co/600x400",
1326
- warning: "https://placehold.co/600x400",
1327
- };
1328
- noop() {
1329
- return;
1251
+ class StepperComponent {
1252
+ constructor() { }
1253
+ steps;
1254
+ title;
1255
+ activeStepIndex = 0;
1256
+ lengthStep = 0;
1257
+ showLine = true;
1258
+ maxReachedEvent = new EventEmitter();
1259
+ ngAfterContentInit() {
1260
+ if (this.steps.length > 0) {
1261
+ this.steps.toArray()[0].isActive = true;
1262
+ this.lengthStep = this.steps.length;
1263
+ }
1330
1264
  }
1331
- getIconPath() {
1332
- return this.iconPaths[this.config.type];
1265
+ nextStep() {
1266
+ if (this.steps.length > 0) {
1267
+ if (this.activeStepIndex < this.steps.length - 1) {
1268
+ this.activeStepIndex++;
1269
+ this.steps.toArray()[this.activeStepIndex].isActive = true;
1270
+ }
1271
+ else {
1272
+ this.maxReachedEvent.emit(null);
1273
+ }
1274
+ }
1333
1275
  }
1334
- handleConfirm() {
1335
- this.config.onConfirm?.();
1336
- this.closeDialog();
1276
+ prevStep() {
1277
+ if (this.steps.length > 0) {
1278
+ if (this.activeStepIndex > 0) {
1279
+ this.steps.toArray()[this.activeStepIndex].isActive = false;
1280
+ this.activeStepIndex--;
1281
+ this.steps.toArray()[this.activeStepIndex].isActive = true;
1282
+ }
1283
+ }
1337
1284
  }
1338
- handleCancel() {
1339
- this.config.onCancel?.();
1340
- this.closeDialog();
1285
+ resetStepper() {
1286
+ this.activeStepIndex = 0;
1287
+ this.steps.forEach((step) => (step.isActive = false));
1288
+ if (this.steps.length > 0) {
1289
+ this.steps.toArray()[0].isActive = true;
1290
+ }
1341
1291
  }
1342
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
1343
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: BaseDialog, isStandalone: true, selector: "cao-dialog", inputs: { config: "config" }, ngImport: i0, template: "\n<div class=\"dialog-container\">\n <div class=\"dialog-content\">\n <img alt=\"Logo\" class=\"logo\" [fill]=\"true\" [ngSrc]=\"config.logoIcon ?? ''\" />\n <div class=\"alert-wrapper\">\n <div class=\"text-content\" [ngClass]=\"config.type\">\n <div class=\"title\">{{ config.title }}</div>\n <div class=\"message\">{{ config.message }}</div>\n <div class=\"button-container\">\n @if (config.cancelButtonText) {\n <button\n type=\"button\"\n class=\"cancel-button\"\n [attr.data-cy]=\"config.cancelButtonText\"\n (keydown)=\"handleCancel()\"\n (click)=\"handleCancel()\">\n {{ config.cancelButtonText }}\n </button>\n } @if (config.confirmButtonText) {\n <button\n type=\"button\"\n class=\"confirm-button\"\n [ngClass]=\"config.type\"\n [attr.data-cy]=\"config.confirmButtonText\"\n (click)=\"handleConfirm()\"\n (keydown)=\"handleConfirm()\"\n >\n {{ config.confirmButtonText }}\n </button>\n }\n </div>\n </div>\n <div class=\"icon-container\">\n <img alt=\"Dialog Icon\" class=\"alert-icon\" [fill]=\"true\" [ngSrc]=\"getIconPath()\" />\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{position:fixed;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;z-index:1000;background:#0009}.dialog-container{width:600px;border-radius:30px;overflow:hidden;box-shadow:0 4px 6px #0000001a;background-color:var(--white);max-width:90%;margin-left:250px}.dialog-content{padding:20px 30px;box-sizing:border-box}.logo{width:150px;height:24px;margin-bottom:15px}.alert-wrapper{display:flex;align-items:center;justify-content:space-between}.button-container{display:flex;gap:10px}.confirm-button,.cancel-button{padding:10px 20px;border:none;border-radius:20px;cursor:pointer;font-weight:600;transition:all .3s ease}.confirm-button{color:var(--white);background-color:var(--primary)}.cancel-button{background-color:var(--disabled-button);color:var(--white)}.confirm-button:hover,.cancel-button:hover{opacity:.9}.text-content{flex-grow:1;padding-right:20px}.text-content .title{font-weight:700;font-size:20px;color:var(--primary);margin-bottom:10px}.text-content.success .title{color:var(--primary)}.text-content.error .title{color:var(--error-color)}.text-content.error .confirm-button{background-color:var(--error-color)}.text-content.warning .title{color:var(--support-orange)}.text-content.info .title{color:var(--primary)}.text-content.info .confirm-button{background-color:var(--primary)}.message{font-weight:400;font-size:16px;color:var(--message-color);margin-bottom:15px}.icon-container{width:150px;height:150px;flex-shrink:0}.alert-icon{width:100%;height:100%;object-fit:contain}@media(max-width:768px){.dialog-container{width:400px;max-width:90%;margin-left:0}.alert-wrapper{flex-direction:column;text-align:center}.text-content{padding-right:0;margin-bottom:10px}.icon-container{width:100px;height:100px}.button-container{flex-direction:column;width:100%}.confirm-button,.cancel-button{width:100%;margin-bottom:10px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }] });
1292
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: StepperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1293
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: StepperComponent, isStandalone: true, selector: "cao-stepper", inputs: { title: "title" }, outputs: { maxReachedEvent: "maxReachedEvent" }, queries: [{ propertyName: "steps", predicate: StepComponent }], ngImport: i0, template: "@if(title){\n<h3 class=\"stepper-title\">{{ title }}</h3>\n}\n<div class=\"d-flex step-container aic jcsb\">\n @if (showLine) {\n <div class=\"line\"></div>\n }\n <div class=\"steps d-flex aic jcsb\">\n <ng-content />\n </div>\n</div>\n", styles: [".step-container{position:relative}.steps{z-index:2;gap:24px}.line{width:100%;position:absolute;top:50%;height:1.5px;background-color:var(--return-color);z-index:1}\n"] });
1344
1294
  }
1345
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseDialog, decorators: [{
1295
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: StepperComponent, decorators: [{
1346
1296
  type: Component,
1347
- args: [{ selector: 'cao-dialog', imports: [CommonModule, NgOptimizedImage], template: "\n<div class=\"dialog-container\">\n <div class=\"dialog-content\">\n <img alt=\"Logo\" class=\"logo\" [fill]=\"true\" [ngSrc]=\"config.logoIcon ?? ''\" />\n <div class=\"alert-wrapper\">\n <div class=\"text-content\" [ngClass]=\"config.type\">\n <div class=\"title\">{{ config.title }}</div>\n <div class=\"message\">{{ config.message }}</div>\n <div class=\"button-container\">\n @if (config.cancelButtonText) {\n <button\n type=\"button\"\n class=\"cancel-button\"\n [attr.data-cy]=\"config.cancelButtonText\"\n (keydown)=\"handleCancel()\"\n (click)=\"handleCancel()\">\n {{ config.cancelButtonText }}\n </button>\n } @if (config.confirmButtonText) {\n <button\n type=\"button\"\n class=\"confirm-button\"\n [ngClass]=\"config.type\"\n [attr.data-cy]=\"config.confirmButtonText\"\n (click)=\"handleConfirm()\"\n (keydown)=\"handleConfirm()\"\n >\n {{ config.confirmButtonText }}\n </button>\n }\n </div>\n </div>\n <div class=\"icon-container\">\n <img alt=\"Dialog Icon\" class=\"alert-icon\" [fill]=\"true\" [ngSrc]=\"getIconPath()\" />\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{position:fixed;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;z-index:1000;background:#0009}.dialog-container{width:600px;border-radius:30px;overflow:hidden;box-shadow:0 4px 6px #0000001a;background-color:var(--white);max-width:90%;margin-left:250px}.dialog-content{padding:20px 30px;box-sizing:border-box}.logo{width:150px;height:24px;margin-bottom:15px}.alert-wrapper{display:flex;align-items:center;justify-content:space-between}.button-container{display:flex;gap:10px}.confirm-button,.cancel-button{padding:10px 20px;border:none;border-radius:20px;cursor:pointer;font-weight:600;transition:all .3s ease}.confirm-button{color:var(--white);background-color:var(--primary)}.cancel-button{background-color:var(--disabled-button);color:var(--white)}.confirm-button:hover,.cancel-button:hover{opacity:.9}.text-content{flex-grow:1;padding-right:20px}.text-content .title{font-weight:700;font-size:20px;color:var(--primary);margin-bottom:10px}.text-content.success .title{color:var(--primary)}.text-content.error .title{color:var(--error-color)}.text-content.error .confirm-button{background-color:var(--error-color)}.text-content.warning .title{color:var(--support-orange)}.text-content.info .title{color:var(--primary)}.text-content.info .confirm-button{background-color:var(--primary)}.message{font-weight:400;font-size:16px;color:var(--message-color);margin-bottom:15px}.icon-container{width:150px;height:150px;flex-shrink:0}.alert-icon{width:100%;height:100%;object-fit:contain}@media(max-width:768px){.dialog-container{width:400px;max-width:90%;margin-left:0}.alert-wrapper{flex-direction:column;text-align:center}.text-content{padding-right:0;margin-bottom:10px}.icon-container{width:100px;height:100px}.button-container{flex-direction:column;width:100%}.confirm-button,.cancel-button{width:100%;margin-bottom:10px}}\n"] }]
1348
- }], propDecorators: { config: [{
1297
+ args: [{ selector: "cao-stepper", standalone: true, template: "@if(title){\n<h3 class=\"stepper-title\">{{ title }}</h3>\n}\n<div class=\"d-flex step-container aic jcsb\">\n @if (showLine) {\n <div class=\"line\"></div>\n }\n <div class=\"steps d-flex aic jcsb\">\n <ng-content />\n </div>\n</div>\n", styles: [".step-container{position:relative}.steps{z-index:2;gap:24px}.line{width:100%;position:absolute;top:50%;height:1.5px;background-color:var(--return-color);z-index:1}\n"] }]
1298
+ }], ctorParameters: () => [], propDecorators: { steps: [{
1299
+ type: ContentChildren,
1300
+ args: [StepComponent]
1301
+ }], title: [{
1349
1302
  type: Input
1303
+ }], maxReachedEvent: [{
1304
+ type: Output
1350
1305
  }] } });
1351
1306
 
1352
- class BaseDialogService {
1353
- overlay;
1354
- constructor(overlay) {
1355
- this.overlay = overlay;
1356
- }
1357
- open(config) {
1358
- const overlayRef = this.overlay.create({
1359
- hasBackdrop: true,
1360
- positionStrategy: this.overlay.position().global().centerHorizontally().centerVertically(),
1361
- scrollStrategy: this.overlay.scrollStrategies.block(),
1362
- backdropClass: "dialog-backdrop",
1363
- });
1364
- const dialogPortal = new ComponentPortal(this.generateComponentPortal());
1365
- const componentRef = overlayRef.attach(dialogPortal);
1366
- componentRef.instance.config = config;
1367
- componentRef.instance.closeDialog = () => {
1368
- overlayRef.dispose();
1369
- };
1370
- return overlayRef;
1371
- }
1372
- generateComponentPortal() {
1373
- return BaseDialog;
1374
- }
1375
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseDialogService, deps: [{ token: i1$4.Overlay }], target: i0.ɵɵFactoryTarget.Injectable });
1376
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseDialogService, providedIn: "root" });
1307
+ class CaoTabContentDirective {
1308
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1309
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: CaoTabContentDirective, isStandalone: true, selector: "[caoTabContent]", ngImport: i0 });
1377
1310
  }
1378
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseDialogService, decorators: [{
1379
- type: Injectable,
1311
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabContentDirective, decorators: [{
1312
+ type: Directive,
1380
1313
  args: [{
1381
- providedIn: "root",
1314
+ selector: '[caoTabContent]',
1315
+ standalone: true,
1382
1316
  }]
1383
- }], ctorParameters: () => [{ type: i1$4.Overlay }] });
1317
+ }] });
1384
1318
 
1385
- class BaseFilterTableService {
1386
- filterSubject = new Subject();
1387
- filter$ = this.filterSubject.asObservable();
1388
- updateFilter(filterValue) {
1389
- this.filterSubject.next(filterValue);
1390
- }
1391
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTableService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1392
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTableService, providedIn: "root" });
1319
+ class CaoTabLabelDirective {
1320
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabLabelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1321
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: CaoTabLabelDirective, isStandalone: true, selector: "[caoTabLabel]", ngImport: i0 });
1393
1322
  }
1394
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTableService, decorators: [{
1395
- type: Injectable,
1323
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabLabelDirective, decorators: [{
1324
+ type: Directive,
1396
1325
  args: [{
1397
- providedIn: "root",
1326
+ selector: '[caoTabLabel]',
1327
+ standalone: true,
1398
1328
  }]
1399
1329
  }] });
1400
1330
 
1401
- class BaseTableService {
1402
- tableConfigSubject = new BehaviorSubject(null);
1403
- dataSubject = new BehaviorSubject([]);
1404
- columnsSubject = new BehaviorSubject([]);
1405
- tableConfig$ = this.tableConfigSubject.asObservable();
1406
- columns$ = this.columnsSubject.asObservable();
1407
- data$ = this.dataSubject.asObservable();
1408
- visibleColumns$ = this.columns$.pipe(map((columns) => columns.filter((col) => col.visible).map((col) => col.key || col.element || "")));
1409
- createTable(data, columns, customConfig) {
1410
- const tableConfig = {
1411
- columns: columns ? columns.map((col) => col.key || col.element || "") : [],
1412
- data,
1413
- columnData: {},
1414
- result: {
1415
- noData: "Não há dados para o filtro selecionado.",
1416
- defaultMessage: "Nenhum resultado encontrado.",
1417
- },
1418
- ...customConfig,
1419
- };
1420
- if (data.length > 0 && columns) {
1421
- const columnData = {};
1422
- columns.forEach((col) => {
1423
- columnData[col.key || col.element || ""] = {
1424
- ...col,
1425
- type: col.type || this.inferColumnType(data[0][col.key || col.element || ""]),
1426
- visible: col.visible !== undefined ? col.visible : true,
1427
- };
1428
- });
1429
- tableConfig.columnData = columnData;
1430
- }
1431
- else if (data.length === 0 && columns) {
1432
- const columnData = {};
1433
- columns.forEach((col) => {
1434
- columnData[col.key || col.element || ""] = {
1435
- ...col,
1436
- type: col.type || "STRING",
1437
- visible: col.visible !== undefined ? col.visible : true,
1438
- };
1439
- });
1440
- tableConfig.columnData = columnData;
1441
- }
1442
- this.tableConfigSubject.next(tableConfig);
1443
- this.columnsSubject.next(columns || []);
1444
- this.dataSubject.next(data);
1445
- }
1446
- inferColumnType(value) {
1447
- if (value === null || value === undefined) {
1448
- return "STRING";
1449
- }
1450
- switch (typeof value) {
1451
- case "boolean":
1452
- return "BOOLEAN";
1453
- case "number":
1454
- return "NUMBER";
1455
- case "string":
1456
- return this.isValidDate(value) ? "DATE" : "STRING";
1457
- default:
1458
- return "STRING";
1459
- }
1460
- }
1461
- isValidDate(value) {
1462
- return !isNaN(Date.parse(value));
1463
- }
1464
- toggleColumnVisibility(columnKey) {
1465
- const currentColumns = this.columnsSubject.value;
1466
- const updatedColumns = currentColumns.map((col) => col.key === columnKey || col.element === columnKey ? { ...col, visible: !col.visible } : col);
1467
- const currentConfig = this.tableConfigSubject.value;
1468
- if (currentConfig) {
1469
- const updatedColumnData = { ...currentConfig.columnData };
1470
- const columnToUpdate = Object.keys(updatedColumnData).find((key) => key === columnKey);
1471
- if (columnToUpdate) {
1472
- updatedColumnData[columnToUpdate].visible = !updatedColumnData[columnToUpdate].visible;
1473
- this.tableConfigSubject.next({
1474
- ...currentConfig,
1475
- columnData: updatedColumnData,
1476
- });
1477
- }
1478
- }
1479
- this.columnsSubject.next(updatedColumns);
1480
- }
1481
- getVisibleColumns() {
1482
- return this.columnsSubject.value.filter((col) => col.visible);
1483
- }
1484
- setColumns(columns) {
1485
- const currentConfig = this.tableConfigSubject.value;
1486
- if (currentConfig) {
1487
- const columnData = {};
1488
- columns.forEach((col) => {
1489
- columnData[col.key || col.element || ""] = col;
1490
- });
1491
- this.tableConfigSubject.next({
1492
- ...currentConfig,
1493
- columns: columns.map((col) => col.key || col.element || ""),
1494
- columnData,
1495
- });
1496
- }
1497
- this.columnsSubject.next(columns);
1498
- }
1499
- setData(data) {
1500
- this.dataSubject.next(data);
1501
- const currentConfig = this.tableConfigSubject.value;
1502
- if (currentConfig) {
1503
- this.tableConfigSubject.next({
1504
- ...currentConfig,
1505
- data,
1506
- });
1507
- }
1508
- }
1509
- updateTableData(data) {
1510
- this.setData(data);
1511
- }
1512
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTableService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1513
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTableService, providedIn: "root" });
1331
+ class CaoTabPanel {
1332
+ label = '';
1333
+ isLucideIcon = true;
1334
+ trailingIcon = null;
1335
+ leadingIcon = null;
1336
+ isDisabled = false;
1337
+ labelTemplate;
1338
+ lazyContent;
1339
+ content;
1340
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
1341
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: CaoTabPanel, isStandalone: true, selector: "cao-tab-panel", inputs: { label: "label", isLucideIcon: "isLucideIcon", trailingIcon: "trailingIcon", leadingIcon: "leadingIcon", isDisabled: "isDisabled" }, queries: [{ propertyName: "labelTemplate", first: true, predicate: CaoTabLabelDirective, descendants: true, read: TemplateRef }, { propertyName: "lazyContent", first: true, predicate: CaoTabContentDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "content", first: true, predicate: ["implicitContent"], descendants: true, static: true }], ngImport: i0, template: `
1342
+ <ng-template #implicitContent>
1343
+ <ng-content />
1344
+ </ng-template>
1345
+ `, isInline: true, styles: [""] });
1514
1346
  }
1515
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTableService, decorators: [{
1516
- type: Injectable,
1517
- args: [{
1518
- providedIn: "root",
1519
- }]
1520
- }] });
1347
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabPanel, decorators: [{
1348
+ type: Component,
1349
+ args: [{ selector: "cao-tab-panel", imports: [], template: `
1350
+ <ng-template #implicitContent>
1351
+ <ng-content />
1352
+ </ng-template>
1353
+ ` }]
1354
+ }], propDecorators: { label: [{
1355
+ type: Input
1356
+ }], isLucideIcon: [{
1357
+ type: Input
1358
+ }], trailingIcon: [{
1359
+ type: Input
1360
+ }], leadingIcon: [{
1361
+ type: Input
1362
+ }], isDisabled: [{
1363
+ type: Input
1364
+ }], labelTemplate: [{
1365
+ type: ContentChild,
1366
+ args: [CaoTabLabelDirective, { read: TemplateRef }]
1367
+ }], lazyContent: [{
1368
+ type: ContentChild,
1369
+ args: [CaoTabContentDirective, { read: TemplateRef }]
1370
+ }], content: [{
1371
+ type: ViewChild,
1372
+ args: ['implicitContent', { static: true }]
1373
+ }] } });
1521
1374
 
1522
- function getPtBrPaginatorIntlBaseTable() {
1523
- const paginatorIntl = new MatPaginatorIntl();
1524
- paginatorIntl.itemsPerPageLabel = "Itens por página:";
1525
- paginatorIntl.nextPageLabel = "Próxima página";
1526
- paginatorIntl.previousPageLabel = "Página anterior";
1527
- paginatorIntl.firstPageLabel = "Primeira página";
1528
- paginatorIntl.lastPageLabel = "Última página";
1529
- paginatorIntl.getRangeLabel = (page, pageSize, length) => {
1530
- if (length === 0 || pageSize === 0) {
1531
- return `0 de ${length}`;
1532
- }
1533
- const startIndex = page * pageSize;
1534
- const endIndex = Math.min(startIndex + pageSize, length);
1535
- return `${startIndex + 1} – ${endIndex} de ${length}`;
1536
- };
1537
- return paginatorIntl;
1538
- }
1539
- class BaseTable {
1540
- customClass = "";
1541
- pageSizeOptions = [5, 10, 20, 50];
1542
- showFirstLastButtons = true;
1543
- isPaginatedByServer = false;
1544
- pageChanged = new EventEmitter();
1545
- pageSizeChanged = new EventEmitter();
1546
- firstPageClicked = new EventEmitter();
1547
- lastPageClicked = new EventEmitter();
1548
- selectionChanged = new EventEmitter();
1549
- pageEvent = new EventEmitter();
1550
- dataSource = new MatTableDataSource([]);
1551
- selection = new SelectionModel(true, []);
1552
- allColumns = [];
1553
- displayedColumns = [];
1554
- filterValue = "";
1555
- configSubscription = null;
1556
- visibleColumnsSubscription = null;
1557
- dataSubscription = null;
1558
- filterSubscription = null;
1559
- tableConfig = null;
1560
- sort;
1561
- paginator;
1562
- totalItems = 0;
1563
- pageSize = 10;
1564
- currentPage = 1;
1565
- previousPage = 1;
1566
- getAllColumns() {
1567
- return ["select", ...this.displayedColumns];
1375
+ class CaoTabGroup {
1376
+ get _hostStyles() {
1377
+ return {
1378
+ '--cao-tab-label-height': this.labelHeight,
1379
+ '--cao-tab-label-px': this.labelPaddingX,
1380
+ '--cao-tab-label-gap': this.labelGap,
1381
+ '--cao-tab-color-text': this.colorText,
1382
+ '--cao-tab-color-active': this.colorActive,
1383
+ '--cao-tab-color-hover-bg': this.colorHoverBg,
1384
+ '--cao-tab-color-disabled': this.colorDisabled,
1385
+ '--cao-tab-color-ink-bar': this.colorInkBar,
1386
+ '--cao-tab-color-header-border': this.colorHeaderBorder,
1387
+ '--cao-tab-ink-bar-height': this.inkBarHeight,
1388
+ '--cao-tab-content-pt': this.contentPaddingTop,
1389
+ '--cao-tab-radius': this.labelRadius,
1390
+ };
1568
1391
  }
1569
- tableService = inject(BaseTableService);
1570
- liveAnnouncer = inject(LiveAnnouncer);
1571
- filterTableService = inject(BaseFilterTableService);
1572
- constructor() {
1573
- this.initializeSortingAccessor();
1574
- this.initializeFilterPredicate();
1392
+ set selectedIndex(val) {
1393
+ this.selectIndex(val, false);
1575
1394
  }
1576
- ngOnInit() {
1577
- this.configSubscription = this.tableService.tableConfig$.subscribe((config) => {
1578
- if (config) {
1579
- this.tableConfig = config;
1580
- this.allColumns = config.columns;
1581
- }
1582
- });
1583
- this.visibleColumnsSubscription = this.tableService.visibleColumns$.subscribe((visibleColumns) => {
1584
- this.displayedColumns = visibleColumns.filter((col) => col !== "select");
1585
- });
1586
- this.dataSubscription = this.tableService.data$.subscribe((data) => {
1587
- this.dataSource.data = data;
1588
- this.updateTotalItems();
1589
- });
1590
- this.filterSubscription = this.filterTableService.filter$.subscribe((filterValue) => {
1591
- this.filterValue = filterValue;
1592
- this.applyFilter();
1593
- });
1395
+ get selectedIndex() {
1396
+ return this.activeIndex();
1594
1397
  }
1595
- ngAfterViewInit() {
1596
- this.dataSource.sort = this.sort;
1597
- // Connect paginator if available
1598
- setTimeout(() => {
1599
- if (this.paginator) {
1600
- this.dataSource.paginator = this.paginator;
1601
- this.paginator.pageIndex = this.currentPage - 1;
1602
- this.paginator.pageSize = this.pageSize;
1603
- this.paginator.showFirstLastButtons = this.showFirstLastButtons;
1604
- }
1605
- });
1606
- this.selection.changed.subscribe(() => {
1607
- this.selectionChanged.emit(this.selection.selected);
1608
- });
1398
+ labelHeight = '48px';
1399
+ labelPaddingX = '16px';
1400
+ labelGap = '6px';
1401
+ colorText = '#6b7280';
1402
+ colorActive = '#4f46e5';
1403
+ colorHoverBg = '#f3f4f6';
1404
+ colorDisabled = '#d1d5db';
1405
+ colorInkBar = '#4f46e5';
1406
+ colorHeaderBorder = '#e5e7eb';
1407
+ inkBarHeight = '2px';
1408
+ contentPaddingTop = '20px';
1409
+ labelRadius = '4px';
1410
+ animationDuration = '300ms';
1411
+ dynamicHeight = false;
1412
+ labelAlign = 'start';
1413
+ iconColorActive = '';
1414
+ iconColorInactive = '';
1415
+ strokeWidthIcon = 1;
1416
+ selectedTabChange = new EventEmitter();
1417
+ focusChange = new EventEmitter();
1418
+ tabs;
1419
+ tabBtns;
1420
+ inkBar;
1421
+ activeIndex = signal(0, ...(ngDevMode ? [{ debugName: "activeIndex" }] : []));
1422
+ activatedSet = new Set();
1423
+ tabList = [];
1424
+ subs = new Subscription();
1425
+ isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
1426
+ ngAfterContentInit() {
1427
+ this.tabList = this.tabs.toArray();
1428
+ this.activatedSet.add(this.activeIndex());
1429
+ this.subs.add(this.tabs.changes.subscribe(() => {
1430
+ this.tabList = this.tabs.toArray();
1431
+ const safe = Math.min(this.activeIndex(), this.tabList.length - 1);
1432
+ this.activeIndex.set(Math.max(0, safe));
1433
+ this.scheduleInkBar();
1434
+ }));
1435
+ this.scheduleInkBar();
1609
1436
  }
1610
1437
  ngOnDestroy() {
1611
- this.configSubscription?.unsubscribe();
1612
- this.visibleColumnsSubscription?.unsubscribe();
1613
- this.dataSubscription?.unsubscribe();
1614
- this.filterSubscription?.unsubscribe();
1438
+ this.subs.unsubscribe();
1615
1439
  }
1616
- initializeSortingAccessor() {
1617
- this.dataSource.sortingDataAccessor = (item, property) => {
1618
- const value = item[property];
1619
- if (typeof value === "string") {
1620
- return value.toLowerCase();
1621
- }
1622
- else if (typeof value === "number") {
1623
- return value;
1624
- }
1625
- else if (typeof value === "boolean") {
1626
- return value ? 1 : 0;
1627
- }
1628
- else if (value instanceof Date) {
1629
- return value.valueOf();
1630
- }
1631
- else if (value === null) {
1632
- return "";
1633
- }
1634
- else if (value === undefined) {
1635
- return undefined;
1636
- }
1637
- else if (typeof value === "object") {
1638
- return value.toString();
1639
- }
1640
- return value;
1641
- };
1440
+ selectTab(index) {
1441
+ this.selectIndex(index, true);
1642
1442
  }
1643
- initializeFilterPredicate() {
1644
- this.dataSource.filterPredicate = (data, filter) => {
1645
- const searchTerms = filter.trim().toLowerCase();
1646
- if (!searchTerms) {
1647
- return true;
1648
- }
1649
- const dataStr = Object.keys(data).reduce((currentTerm, key) => {
1650
- const value = data[key];
1651
- return (currentTerm +
1652
- (value !== null && value !== undefined ? value.toString().toLowerCase() : ""));
1653
- }, "");
1654
- return dataStr.indexOf(searchTerms) !== -1;
1655
- };
1443
+ get activeTab() {
1444
+ return this.tabList[this.activeIndex()] ?? null;
1656
1445
  }
1657
- applyFilter() {
1658
- const normalizedFilter = this.filterValue.trim().toLowerCase();
1659
- this.dataSource.filter = normalizedFilter;
1446
+ isActive(index) {
1447
+ return this.activeIndex() === index;
1660
1448
  }
1661
- toggleColumnVisibility(columnKey) {
1662
- this.tableService.toggleColumnVisibility(columnKey);
1449
+ wasActivated(index) {
1450
+ return this.activatedSet.has(index);
1663
1451
  }
1664
- isColumnVisible(column) {
1665
- if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
1666
- return true;
1452
+ onTabClick(index) {
1453
+ if (this.tabList[index]?.isDisabled) {
1454
+ return;
1667
1455
  }
1668
- return this.tableConfig.columnData[column].visible !== false;
1456
+ this.selectIndex(index, true);
1669
1457
  }
1670
- getColumnHeader(column) {
1671
- if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
1672
- return column;
1458
+ onKeydown(event, currentIndex) {
1459
+ let next = currentIndex;
1460
+ switch (event.key) {
1461
+ case 'ArrowRight':
1462
+ next = this.nextEnabled(currentIndex, 1);
1463
+ break;
1464
+ case 'ArrowLeft':
1465
+ next = this.nextEnabled(currentIndex, -1);
1466
+ break;
1467
+ case 'Home':
1468
+ next = this.nextEnabled(-1, 1);
1469
+ break;
1470
+ case 'End':
1471
+ next = this.nextEnabled(this.tabList.length, -1);
1472
+ break;
1473
+ default: return;
1673
1474
  }
1674
- return this.tableConfig.columnData[column].header || column;
1475
+ event.preventDefault();
1476
+ this.selectIndex(next, true);
1477
+ this.focusTab(next);
1675
1478
  }
1676
- getColumnType(column) {
1677
- if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
1678
- return "STRING";
1679
- }
1680
- return this.tableConfig.columnData[column].type || "STRING";
1479
+ onFocus(index) {
1480
+ this.focusChange.emit(index);
1681
1481
  }
1682
- getColumnElement(column) {
1683
- if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
1684
- return column;
1482
+ nextEnabled(from, dir) {
1483
+ const tabs = this.tabList;
1484
+ let idx = from + dir;
1485
+ while (idx >= 0 && idx < tabs.length) {
1486
+ if (!tabs[idx].isDisabled) {
1487
+ return idx;
1488
+ }
1489
+ idx += dir;
1685
1490
  }
1686
- return this.tableConfig.columnData[column].element || column;
1491
+ return from;
1687
1492
  }
1688
- getColumnButtons(column) {
1689
- if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
1690
- return [];
1493
+ selectIndex(index, emit) {
1494
+ if (!this.tabList) {
1495
+ this.activeIndex.set(Math.max(0, index));
1496
+ return;
1691
1497
  }
1692
- return this.tableConfig.columnData[column].buttons || [];
1693
- }
1694
- isAllSelected() {
1695
- if (!this.paginator ||
1696
- !this.dataSource.filteredData ||
1697
- this.dataSource.filteredData.length === 0) {
1698
- return false;
1498
+ const clamped = Math.max(0, Math.min(index, this.tabList.length - 1));
1499
+ const previous = this.activeIndex();
1500
+ if (clamped === previous && emit) {
1501
+ return;
1699
1502
  }
1700
- const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
1701
- const endIndex = Math.min(startIndex + this.paginator.pageSize, this.dataSource.filteredData.length);
1702
- const currentPageData = this.dataSource.filteredData.slice(startIndex, endIndex);
1703
- if (currentPageData.length === 0) {
1704
- return false;
1503
+ this.activeIndex.set(clamped);
1504
+ this.activatedSet.add(clamped);
1505
+ if (emit) {
1506
+ this.selectedTabChange.emit({
1507
+ previousIndex: previous,
1508
+ index: clamped,
1509
+ tab: this.tabList[clamped],
1510
+ });
1705
1511
  }
1706
- return currentPageData.every((row) => this.selection.isSelected(row));
1512
+ this.scheduleInkBar();
1707
1513
  }
1708
- toggleAllRows() {
1709
- if (!this.paginator || !this.dataSource.filteredData) {
1514
+ focusTab(index) {
1515
+ this.tabBtns?.toArray()[index]?.nativeElement?.focus();
1516
+ }
1517
+ scheduleInkBar() {
1518
+ if (!this.isBrowser) {
1710
1519
  return;
1711
1520
  }
1712
- if (this.isAllSelected()) {
1713
- this.selection.clear();
1714
- }
1715
- else {
1716
- const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
1717
- const endIndex = Math.min(startIndex + this.paginator.pageSize, this.dataSource.filteredData.length);
1718
- const currentPageData = this.dataSource.filteredData.slice(startIndex, endIndex);
1719
- currentPageData.forEach((row) => this.selection.select(row));
1720
- }
1521
+ requestAnimationFrame(() => this.updateInkBar());
1721
1522
  }
1722
- announceSortChange(sortState) {
1723
- if (sortState.direction) {
1724
- this.liveAnnouncer.announce(`Ordenado ${sortState.direction === "asc" ? "ascendente" : "descendente"}`);
1523
+ updateInkBar() {
1524
+ const btns = this.tabBtns?.toArray();
1525
+ const bar = this.inkBar?.nativeElement;
1526
+ if (!btns || !bar) {
1527
+ return;
1725
1528
  }
1726
- else {
1727
- this.liveAnnouncer.announce("Ordenação removida");
1529
+ const btn = btns[this.activeIndex()]?.nativeElement;
1530
+ if (!btn) {
1531
+ return;
1728
1532
  }
1533
+ bar.style.width = `${btn.offsetWidth}px`;
1534
+ bar.style.transform = `translateX(${btn.offsetLeft}px)`;
1535
+ bar.style.transitionDuration = this.animationDuration;
1729
1536
  }
1730
- trackByFn(index, item) {
1731
- return item;
1537
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
1538
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CaoTabGroup, isStandalone: true, selector: "cao-tab-group", inputs: { selectedIndex: "selectedIndex", labelHeight: "labelHeight", labelPaddingX: "labelPaddingX", labelGap: "labelGap", colorText: "colorText", colorActive: "colorActive", colorHoverBg: "colorHoverBg", colorDisabled: "colorDisabled", colorInkBar: "colorInkBar", colorHeaderBorder: "colorHeaderBorder", inkBarHeight: "inkBarHeight", contentPaddingTop: "contentPaddingTop", labelRadius: "labelRadius", animationDuration: "animationDuration", dynamicHeight: "dynamicHeight", labelAlign: "labelAlign", iconColorActive: "iconColorActive", iconColorInactive: "iconColorInactive", strokeWidthIcon: "strokeWidthIcon" }, outputs: { selectedTabChange: "selectedTabChange", focusChange: "focusChange" }, host: { properties: { "style": "this._hostStyles" }, classAttribute: "cao-tab-group" }, queries: [{ propertyName: "tabs", predicate: CaoTabPanel }], viewQueries: [{ propertyName: "inkBar", first: true, predicate: ["inkBar"], descendants: true }, { propertyName: "tabBtns", predicate: ["tabBtn"], descendants: true }], ngImport: i0, template: "<div\n #header\n [class]=\"'cao-tab-header cao-tab-header--align-' + labelAlign\"\n>\n <div class=\"cao-tab-label-list\" role=\"tablist\">\n @for (tab of tabList; track $index; let i = $index) {\n <button\n #tabBtn\n role=\"tab\"\n type=\"button\"\n class=\"cao-tab-label\"\n [class.cao-tab-label--active]=\"isActive(i)\"\n [class.cao-tab-label--disabled]=\"tab.isDisabled\"\n [attr.aria-selected]=\"isActive(i)\"\n [attr.aria-disabled]=\"tab.isDisabled || null\"\n [attr.tabindex]=\"isActive(i) ? 0 : -1\"\n [attr.id]=\"'cao-tab-label-' + i\"\n [attr.aria-controls]=\"'cao-tab-content-' + i\"\n (click)=\"onTabClick(i)\"\n (keydown)=\"onKeydown($event, i)\"\n (focus)=\"onFocus(i)\"\n >\n @if (tab.leadingIcon) {\n <span class=\"leading-icon\">\n @if (tab.isLucideIcon) {\n <svg [lucideIcon]=\"tab.leadingIcon\" [style.color]=\"isActive(i) ? iconColorActive : iconColorInactive\" [strokeWidth]=\"strokeWidthIcon\"></svg>\n } @else {\n <img alt=\"icon\" [src]=\"tab.leadingIcon\" />\n }\n </span>\n }\n\n @if (tab.labelTemplate) {\n <ng-container [ngTemplateOutlet]=\"tab.labelTemplate\" />\n } @else {\n <span class=\"cao-tab-labeltext\">{{ tab.label }}</span>\n }\n\n @if (tab.trailingIcon) {\n <span class=\"trailing-icon\">\n @if (tab.isLucideIcon) {\n <svg [lucideIcon]=\"tab.trailingIcon\" [style.color]=\"isActive(i) ? iconColorActive : iconColorInactive\" [strokeWidth]=\"strokeWidthIcon\"></svg>\n } @else {\n <img alt=\"icon\" [src]=\"tab.trailingIcon\" />\n }\n </span>\n }\n </button>\n }\n </div>\n\n <!-- Ink bar animado -->\n <div class=\"cao-tab-ink-bar-track\">\n <div #inkBar class=\"cao-tab-ink-bar\"></div>\n </div>\n</div>\n\n<!-- \u2550\u2550\u2550 Tab Bodies \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<div\n class=\"cao-tab-body-wrapper\"\n [class.cao-tab-body-wrapper--dynamic]=\"dynamicHeight\"\n>\n @for (tab of tabList; track $index; let i = $index) {\n <div\n role=\"tabpanel\"\n class=\"cao-tab-body\"\n [class.cao-tab-body--active]=\"isActive(i)\"\n [attr.id]=\"'cao-tab-content-' + i\"\n [attr.aria-labelledby]=\"'cao-tab-label-' + i\"\n [attr.aria-hidden]=\"!isActive(i)\"\n [style.--cao-tab-anim-duration]=\"animationDuration\"\n >\n <div class=\"cao-tab-bodycontent\">\n @if (tab.lazyContent) {\n @if (isActive(i) || wasActivated(i)) {\n <ng-container [ngTemplateOutlet]=\"tab.lazyContent\" />\n }\n } @else {\n <ng-container [ngTemplateOutlet]=\"tab.content\" />\n }\n </div>\n </div>\n }\n</div>", styles: [":host{--cao-tab-font-family: inherit;--cao-tab-font-size: .875rem;--cao-tab-font-weight: 500;--cao-tab-label-height: 48px;--cao-tab-Label-px: 16px;--cao-tab-Label-gap: 6px;--cao-tab-color-text: #6b7280;--cao-tab-color-active: #4f46e5;--cao-tab-color-hover-bg: #f3f4f6;--cao-tab-color-disabled: #d1d5db;--cao-tab-color-ink-bar: #4f46e5;--cao-tab-color-header-border: #e5e7eb;--cao-tab-ink-bar-height: 2px;--cao-tab-content-pt: 20px;--cao-tab-radius: 4px;display:flex;flex-direction:column;width:100%}.cao-tab-header{position:relative;border-bottom:1px solid var(--cao-tab-color-header-border);overflow-x:auto;scrollbar-width:none}.cao-tab-header::-webkit-scrollbar{display:none}.cao-tab-label-list{display:flex;align-items:center;min-width:max-content}.cao-tab-header--align-center .cao-tab-label-list{justify-content:center}.cao-tab-header--align-end .cao-tab-label-list{justify-content:flex-end}.cao-tab-header--align-start .cao-tab-label-list{justify-content:flex-start}.cao-tab-label{width:100%;display:inline-flex;justify-content:center;align-items:center;gap:var(--cao-tab-label-gap);height:var(--cao-tab-label-height);padding:0 var(--cao-tab-label-px);font-family:var(--cao-tab-font-family);font-size:var(--cao-tab-font-size);font-weight:var(--cao-tab-font-weight);color:var(--cao-tab-color-text);white-space:nowrap;background:transparent;border:none;border-radius:var(--cao-tab-radius) var(--cao-tab-radius) 0 0;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .18s ease,background-color .18s ease;outline:none}.cao-tab-label:focus-visible{outline:2px solid var(--cao-tab-color-active);outline-offset:-2px}.cao-tab-label:hover:not(.cao-tab-label--disabled){background-color:var(--cao-tab-color-hover-bg);color:var(--cao-tab-color-active)}.cao-tab-label--active{color:var(--cao-tab-color-active)}.cao-tab-label--disabled{color:var(--cao-tab-color-disabled);cursor:not-allowed;pointer-events:none}.cao-tab-label__icon{flex-shrink:0;color:inherit;transition:color .18s ease}.cao-tab-ink-bar-track{position:absolute;bottom:0;left:0;right:0;height:var(--cao-tab-ink-bar-height);pointer-events:none}.cao-tab-ink-bar{position:absolute;bottom:0;left:0;height:100%;background-color:var(--cao-tab-color-ink-bar);border-radius:2px 2px 0 0;transition-property:transform,width;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}.cao-tab-body-wrapper{position:relative;overflow:hidden}.cao-tab-body-wrapper--dynamic{height:auto}.cao-tab-body{position:absolute;top:0;left:0;width:100%;visibility:hidden;opacity:0;pointer-events:none;transform:translate(24px);transition:opacity var(--cao-tab-anim-duration, .3s) cubic-bezier(.4,0,.2,1),transform var(--cao-tab-anim-duration, .3s) cubic-bezier(.4,0,.2,1)}.cao-tab-body--active{position:relative;visibility:visible;opacity:1;pointer-events:auto;transform:translate(0)}.cao-tab-body__content{padding-top:var(--cao-tab-content-pt)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }] });
1539
+ }
1540
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabGroup, decorators: [{
1541
+ type: Component,
1542
+ args: [{ selector: 'cao-tab-group', standalone: true, imports: [NgTemplateOutlet, LucideDynamicIcon], host: { class: 'cao-tab-group' }, template: "<div\n #header\n [class]=\"'cao-tab-header cao-tab-header--align-' + labelAlign\"\n>\n <div class=\"cao-tab-label-list\" role=\"tablist\">\n @for (tab of tabList; track $index; let i = $index) {\n <button\n #tabBtn\n role=\"tab\"\n type=\"button\"\n class=\"cao-tab-label\"\n [class.cao-tab-label--active]=\"isActive(i)\"\n [class.cao-tab-label--disabled]=\"tab.isDisabled\"\n [attr.aria-selected]=\"isActive(i)\"\n [attr.aria-disabled]=\"tab.isDisabled || null\"\n [attr.tabindex]=\"isActive(i) ? 0 : -1\"\n [attr.id]=\"'cao-tab-label-' + i\"\n [attr.aria-controls]=\"'cao-tab-content-' + i\"\n (click)=\"onTabClick(i)\"\n (keydown)=\"onKeydown($event, i)\"\n (focus)=\"onFocus(i)\"\n >\n @if (tab.leadingIcon) {\n <span class=\"leading-icon\">\n @if (tab.isLucideIcon) {\n <svg [lucideIcon]=\"tab.leadingIcon\" [style.color]=\"isActive(i) ? iconColorActive : iconColorInactive\" [strokeWidth]=\"strokeWidthIcon\"></svg>\n } @else {\n <img alt=\"icon\" [src]=\"tab.leadingIcon\" />\n }\n </span>\n }\n\n @if (tab.labelTemplate) {\n <ng-container [ngTemplateOutlet]=\"tab.labelTemplate\" />\n } @else {\n <span class=\"cao-tab-labeltext\">{{ tab.label }}</span>\n }\n\n @if (tab.trailingIcon) {\n <span class=\"trailing-icon\">\n @if (tab.isLucideIcon) {\n <svg [lucideIcon]=\"tab.trailingIcon\" [style.color]=\"isActive(i) ? iconColorActive : iconColorInactive\" [strokeWidth]=\"strokeWidthIcon\"></svg>\n } @else {\n <img alt=\"icon\" [src]=\"tab.trailingIcon\" />\n }\n </span>\n }\n </button>\n }\n </div>\n\n <!-- Ink bar animado -->\n <div class=\"cao-tab-ink-bar-track\">\n <div #inkBar class=\"cao-tab-ink-bar\"></div>\n </div>\n</div>\n\n<!-- \u2550\u2550\u2550 Tab Bodies \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<div\n class=\"cao-tab-body-wrapper\"\n [class.cao-tab-body-wrapper--dynamic]=\"dynamicHeight\"\n>\n @for (tab of tabList; track $index; let i = $index) {\n <div\n role=\"tabpanel\"\n class=\"cao-tab-body\"\n [class.cao-tab-body--active]=\"isActive(i)\"\n [attr.id]=\"'cao-tab-content-' + i\"\n [attr.aria-labelledby]=\"'cao-tab-label-' + i\"\n [attr.aria-hidden]=\"!isActive(i)\"\n [style.--cao-tab-anim-duration]=\"animationDuration\"\n >\n <div class=\"cao-tab-bodycontent\">\n @if (tab.lazyContent) {\n @if (isActive(i) || wasActivated(i)) {\n <ng-container [ngTemplateOutlet]=\"tab.lazyContent\" />\n }\n } @else {\n <ng-container [ngTemplateOutlet]=\"tab.content\" />\n }\n </div>\n </div>\n }\n</div>", styles: [":host{--cao-tab-font-family: inherit;--cao-tab-font-size: .875rem;--cao-tab-font-weight: 500;--cao-tab-label-height: 48px;--cao-tab-Label-px: 16px;--cao-tab-Label-gap: 6px;--cao-tab-color-text: #6b7280;--cao-tab-color-active: #4f46e5;--cao-tab-color-hover-bg: #f3f4f6;--cao-tab-color-disabled: #d1d5db;--cao-tab-color-ink-bar: #4f46e5;--cao-tab-color-header-border: #e5e7eb;--cao-tab-ink-bar-height: 2px;--cao-tab-content-pt: 20px;--cao-tab-radius: 4px;display:flex;flex-direction:column;width:100%}.cao-tab-header{position:relative;border-bottom:1px solid var(--cao-tab-color-header-border);overflow-x:auto;scrollbar-width:none}.cao-tab-header::-webkit-scrollbar{display:none}.cao-tab-label-list{display:flex;align-items:center;min-width:max-content}.cao-tab-header--align-center .cao-tab-label-list{justify-content:center}.cao-tab-header--align-end .cao-tab-label-list{justify-content:flex-end}.cao-tab-header--align-start .cao-tab-label-list{justify-content:flex-start}.cao-tab-label{width:100%;display:inline-flex;justify-content:center;align-items:center;gap:var(--cao-tab-label-gap);height:var(--cao-tab-label-height);padding:0 var(--cao-tab-label-px);font-family:var(--cao-tab-font-family);font-size:var(--cao-tab-font-size);font-weight:var(--cao-tab-font-weight);color:var(--cao-tab-color-text);white-space:nowrap;background:transparent;border:none;border-radius:var(--cao-tab-radius) var(--cao-tab-radius) 0 0;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .18s ease,background-color .18s ease;outline:none}.cao-tab-label:focus-visible{outline:2px solid var(--cao-tab-color-active);outline-offset:-2px}.cao-tab-label:hover:not(.cao-tab-label--disabled){background-color:var(--cao-tab-color-hover-bg);color:var(--cao-tab-color-active)}.cao-tab-label--active{color:var(--cao-tab-color-active)}.cao-tab-label--disabled{color:var(--cao-tab-color-disabled);cursor:not-allowed;pointer-events:none}.cao-tab-label__icon{flex-shrink:0;color:inherit;transition:color .18s ease}.cao-tab-ink-bar-track{position:absolute;bottom:0;left:0;right:0;height:var(--cao-tab-ink-bar-height);pointer-events:none}.cao-tab-ink-bar{position:absolute;bottom:0;left:0;height:100%;background-color:var(--cao-tab-color-ink-bar);border-radius:2px 2px 0 0;transition-property:transform,width;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}.cao-tab-body-wrapper{position:relative;overflow:hidden}.cao-tab-body-wrapper--dynamic{height:auto}.cao-tab-body{position:absolute;top:0;left:0;width:100%;visibility:hidden;opacity:0;pointer-events:none;transform:translate(24px);transition:opacity var(--cao-tab-anim-duration, .3s) cubic-bezier(.4,0,.2,1),transform var(--cao-tab-anim-duration, .3s) cubic-bezier(.4,0,.2,1)}.cao-tab-body--active{position:relative;visibility:visible;opacity:1;pointer-events:auto;transform:translate(0)}.cao-tab-body__content{padding-top:var(--cao-tab-content-pt)}\n"] }]
1543
+ }], propDecorators: { _hostStyles: [{
1544
+ type: HostBinding,
1545
+ args: ['style']
1546
+ }], selectedIndex: [{
1547
+ type: Input
1548
+ }], labelHeight: [{
1549
+ type: Input
1550
+ }], labelPaddingX: [{
1551
+ type: Input
1552
+ }], labelGap: [{
1553
+ type: Input
1554
+ }], colorText: [{
1555
+ type: Input
1556
+ }], colorActive: [{
1557
+ type: Input
1558
+ }], colorHoverBg: [{
1559
+ type: Input
1560
+ }], colorDisabled: [{
1561
+ type: Input
1562
+ }], colorInkBar: [{
1563
+ type: Input
1564
+ }], colorHeaderBorder: [{
1565
+ type: Input
1566
+ }], inkBarHeight: [{
1567
+ type: Input
1568
+ }], contentPaddingTop: [{
1569
+ type: Input
1570
+ }], labelRadius: [{
1571
+ type: Input
1572
+ }], animationDuration: [{
1573
+ type: Input
1574
+ }], dynamicHeight: [{
1575
+ type: Input
1576
+ }], labelAlign: [{
1577
+ type: Input
1578
+ }], iconColorActive: [{
1579
+ type: Input
1580
+ }], iconColorInactive: [{
1581
+ type: Input
1582
+ }], strokeWidthIcon: [{
1583
+ type: Input
1584
+ }], selectedTabChange: [{
1585
+ type: Output
1586
+ }], focusChange: [{
1587
+ type: Output
1588
+ }], tabs: [{
1589
+ type: ContentChildren,
1590
+ args: [CaoTabPanel]
1591
+ }], tabBtns: [{
1592
+ type: ViewChildren,
1593
+ args: ['tabBtn']
1594
+ }], inkBar: [{
1595
+ type: ViewChild,
1596
+ args: ['inkBar']
1597
+ }] } });
1598
+
1599
+ class CaoBaseIcon {
1600
+ imgSource = "";
1601
+ isLucideIcon = true;
1602
+ strokeWidthIcon = 1;
1603
+ iconColor = "";
1604
+ size = 32;
1605
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoBaseIcon, deps: [], target: i0.ɵɵFactoryTarget.Component });
1606
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CaoBaseIcon, isStandalone: true, selector: "cao-base-icon", inputs: { imgSource: "imgSource", isLucideIcon: "isLucideIcon", strokeWidthIcon: "strokeWidthIcon", iconColor: "iconColor", size: "size" }, ngImport: i0, template: "@if (imgSource) {\n @if (isLucideIcon) {\n <div class=\"icon\">\n <svg [lucideIcon]=\"imgSource\" [style.color]=\"iconColor\" [strokeWidth]=\"strokeWidthIcon\" [size]=\"size\"></svg>\n </div>\n } @else {\n <div class=\"icon\">\n <img alt=\"\u00EDcone de in\u00EDcio\" [src]=\"imgSource\" />\n </div>\n }\n}", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }] });
1607
+ }
1608
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoBaseIcon, decorators: [{
1609
+ type: Component,
1610
+ args: [{ selector: 'cao-base-icon', imports: [CommonModule, LucideDynamicIcon], template: "@if (imgSource) {\n @if (isLucideIcon) {\n <div class=\"icon\">\n <svg [lucideIcon]=\"imgSource\" [style.color]=\"iconColor\" [strokeWidth]=\"strokeWidthIcon\" [size]=\"size\"></svg>\n </div>\n } @else {\n <div class=\"icon\">\n <img alt=\"\u00EDcone de in\u00EDcio\" [src]=\"imgSource\" />\n </div>\n }\n}" }]
1611
+ }], propDecorators: { imgSource: [{
1612
+ type: Input
1613
+ }], isLucideIcon: [{
1614
+ type: Input
1615
+ }], strokeWidthIcon: [{
1616
+ type: Input
1617
+ }], iconColor: [{
1618
+ type: Input
1619
+ }], size: [{
1620
+ type: Input
1621
+ }] } });
1622
+
1623
+ class BaseModalService {
1624
+ constructor() { }
1625
+ toggleModalEvent = new EventEmitter();
1626
+ closeAllModalsEvent = new EventEmitter();
1627
+ openModal = new EventEmitter();
1628
+ modalResultSubject = new Subject();
1629
+ emitModalResult(result) {
1630
+ this.modalResultSubject.next(result);
1732
1631
  }
1733
- onPageChanged(page) {
1734
- this.currentPage = page;
1735
- this.pageChanged.emit(page);
1736
- if (this.paginator && this.paginator.pageIndex !== page - 1) {
1737
- this.paginator.pageIndex = page - 1;
1738
- }
1632
+ onModalResult() {
1633
+ return this.modalResultSubject.asObservable();
1739
1634
  }
1740
- onPageSizeChanged(pageSize) {
1741
- this.pageSize = pageSize;
1742
- this.pageSizeChanged.emit(pageSize);
1743
- if (this.paginator && this.paginator.pageSize !== pageSize) {
1744
- this.paginator.pageSize = pageSize;
1745
- }
1635
+ toggleModal(modalInfo) {
1636
+ this.toggleModalEvent.emit(modalInfo);
1746
1637
  }
1747
- /**
1748
- * Handle pagination events from Mat Paginator
1749
- */
1750
- onPageEvent(event) {
1751
- const newPage = event.pageIndex + 1;
1752
- const isFirstPage = newPage === 1 && this.previousPage !== 1;
1753
- const isLastPage = newPage === Math.ceil(this.totalItems / event.pageSize) && newPage !== this.previousPage;
1754
- // Handle page size changes
1755
- if (event.pageSize !== this.pageSize) {
1756
- this.onPageSizeChanged(event.pageSize);
1757
- }
1758
- // Handle page changes
1759
- if (newPage !== this.currentPage) {
1760
- this.previousPage = this.currentPage; // Store previous page for first/last detection
1761
- this.onPageChanged(newPage);
1762
- // Emit specific events for first/last page navigation
1763
- if (isFirstPage) {
1764
- this.firstPageClicked.emit();
1765
- this.liveAnnouncer.announce("Primeira página");
1766
- }
1767
- else if (isLastPage) {
1768
- this.lastPageClicked.emit();
1769
- this.liveAnnouncer.announce("Última página");
1770
- }
1771
- }
1772
- this.pageEvent.emit(event);
1638
+ closeAllModals() {
1639
+ this.closeAllModalsEvent.emit(true);
1773
1640
  }
1774
- /**
1775
- * Navigate to first page programmatically
1776
- */
1777
- goToFirstPage() {
1778
- if (this.currentPage !== 1) {
1779
- this.onPageChanged(1);
1780
- this.firstPageClicked.emit();
1781
- this.liveAnnouncer.announce("Primeira página");
1782
- }
1641
+ showModal(_selectedModal, data) {
1642
+ this.closeAllModals();
1643
+ const modalInfo = {
1644
+ type: _selectedModal,
1645
+ data: data,
1646
+ status: true,
1647
+ };
1648
+ this.openModal.emit(modalInfo);
1783
1649
  }
1784
- /**
1785
- * Navigate to last page programmatically
1786
- */
1787
- goToLastPage() {
1788
- const lastPage = Math.max(1, Math.ceil(this.totalItems / this.pageSize));
1789
- if (this.currentPage !== lastPage) {
1790
- this.onPageChanged(lastPage);
1791
- this.lastPageClicked.emit();
1792
- this.liveAnnouncer.announce("Última página");
1793
- }
1650
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseModalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1651
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseModalService, providedIn: "root" });
1652
+ }
1653
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseModalService, decorators: [{
1654
+ type: Injectable,
1655
+ args: [{
1656
+ providedIn: "root",
1657
+ }]
1658
+ }], ctorParameters: () => [], propDecorators: { toggleModalEvent: [{
1659
+ type: Output
1660
+ }], closeAllModalsEvent: [{
1661
+ type: Output
1662
+ }], openModal: [{
1663
+ type: Output
1664
+ }] } });
1665
+
1666
+ class BaseModal {
1667
+ showModal = false;
1668
+ title = "";
1669
+ data;
1670
+ modalTypeClass = "default";
1671
+ modalClass = "modal-default";
1672
+ modalSize = "w-70";
1673
+ closeOnOverlayClick = false;
1674
+ modalService = inject(BaseModalService);
1675
+ closeModals() { }
1676
+ closeModalsWithoutDialog() {
1677
+ this.modalService.closeAllModals();
1794
1678
  }
1795
- /**
1796
- * Update total items when data changes
1797
- */
1798
- updateTotalItems() {
1799
- if (this.isPaginatedByServer) {
1800
- return;
1679
+ onOverlayClick() {
1680
+ if (this.closeOnOverlayClick) {
1681
+ this.closeModals();
1801
1682
  }
1802
- this.totalItems = this.dataSource.data.length;
1803
1683
  }
1804
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
1805
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: BaseTable, isStandalone: true, selector: "cao-table", inputs: { customClass: "customClass", pageSizeOptions: "pageSizeOptions", showFirstLastButtons: "showFirstLastButtons", isPaginatedByServer: "isPaginatedByServer" }, outputs: { pageChanged: "pageChanged", pageSizeChanged: "pageSizeChanged", firstPageClicked: "firstPageClicked", lastPageClicked: "lastPageClicked", selectionChanged: "selectionChanged", pageEvent: "pageEvent" }, providers: [{ provide: MatPaginatorIntl, useValue: getPtBrPaginatorIntlBaseTable() }], viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }], ngImport: i0, template: "<div class=\"table-container\" [ngClass]=\"customClass\">\n @if (tableConfig) {\n <div class=\"table-controls\">\n <mat-menu #menuColunas=\"matMenu\">\n @for (column of allColumns; track column) {\n <button\n mat-menu-item\n [type]=\"'button'\" (click)=\"toggleColumnVisibility(column)\">\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-toggle-column-' + column\"\n [checked]=\"isColumnVisible(column)\">\n {{ getColumnHeader(column) }}\n </mat-checkbox>\n </button>\n }\n </mat-menu>\n </div>\n\n <table\n mat-table\n matSort\n class=\"mat-elevation-z8\"\n [dataSource]=\"dataSource\"\n (matSortChange)=\"announceSortChange($event)\">\n <ng-container matColumnDef=\"select\">\n <th *matHeaderCellDef mat-header-cell>\n <mat-checkbox\n data-cy=\"checkbox-select-all\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n (change)=\"$event ? toggleAllRows() : null\" />\n </th>\n <td *matCellDef=\"let row\" mat-cell>\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-select-row-' + row.id\"\n [checked]=\"selection.isSelected(row)\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(row) : null\" />\n </td>\n </ng-container>\n\n @for (column of displayedColumns; track column) {\n <ng-container [matColumnDef]=\"column\">\n <th *matHeaderCellDef mat-header-cell [mat-sort-header]=\"column\">\n <span>{{ getColumnHeader(column) }}</span>\n <img\n alt=\"icone\"\n [ngSrc]=\"'.src/assets/svg/arrow-left-double.svg'\"\n [fill]=\"true\"\n [matMenuTriggerFor]=\"menuColunas\" />\n <mat-menu #menuColunas=\"matMenu\">\n @for (column of allColumns; track column) {\n <button\n mat-menu-item\n [type]=\"'button'\" (click)=\"toggleColumnVisibility(column)\">\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-toggle-column-' + column\"\n [checked]=\"isColumnVisible(column)\">\n {{ getColumnHeader(column) }}\n </mat-checkbox>\n </button>\n }\n </mat-menu>\n </th>\n <td *matCellDef=\"let element\" mat-cell>\n @switch (getColumnType(column)) { @case ('STRING') {\n <span>{{ element[getColumnElement(column)] }}</span>\n } @case ('BOOLEAN') {\n <mat-checkbox\n disabled\n [attr.data-cy]=\"'checkbox-value-' + column + '-' + element.id\"\n [checked]=\"element[getColumnElement(column)]\" />\n } @case ('DATE') {\n <span>{{ element[getColumnElement(column)] | date:'mediumDate' }}</span>\n } @case ('NUMBER') {\n <span>{{ element[getColumnElement(column)] | number:'1.2-2' }}</span>\n } @case ('SINGLE_BUTTON') {\n <div>\n @for (btn of getColumnButtons(column); track btn) {\n <button\n mat-icon-button\n [type]=\"'button'\" [matTooltip]=\"btn.tooltip\" (click)=\"btn.onClick(element)\">\n <mat-icon>{{ btn.icon }}</mat-icon>\n </button>\n }\n </div>\n } @default {\n <span>{{ element[getColumnElement(column)] }}</span>\n } }\n </td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"footer\">\n <td *matFooterCellDef mat-footer-cell [attr.colspan]=\"displayedColumns.length + 1\">\n Total de Registros: {{ dataSource.data.length }}\n </td>\n </ng-container>\n\n <tr *matHeaderRowDef=\"getAllColumns()\" mat-header-row></tr>\n <tr\n *matRowDef=\"let row; columns: getAllColumns();\"\n mat-row\n (click)=\"selection.toggle(row)\"></tr>\n <tr *matFooterRowDef=\"['footer']\" mat-footer-row></tr>\n </table>\n }\n</div>\n\n<mat-paginator\n #paginator\n aria-label=\"Select page\"\n [length]=\"totalItems\"\n [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\"\n [pageIndex]=\"currentPage - 1\"\n [hidePageSize]=\"false\"\n [showFirstLastButtons]=\"showFirstLastButtons\"\n (page)=\"onPageEvent($event)\" />\n\n@if (!tableConfig || tableConfig.data.length === 0) {\n<div class=\"no-data-container\">\n <h2 class=\"no-data-title\">{{ tableConfig?.result?.noData || 'N\u00E3o h\u00E1 dados dispon\u00EDveis' }}</h2>\n <p class=\"no-data-message\"\n >{{ tableConfig?.result?.defaultMessage || 'Adicione alguns dados' }}</p\n >\n</div>\n}\n", styles: [".table-container{border-radius:8px;box-shadow:0 4px 6px #0000001a;max-width:100%;overflow:auto hidden}.table-container .table-controls{display:flex;align-items:center;padding:20px}.table-container .table-controls .filter-field{display:flex;align-items:center;justify-content:space-between;padding:10px;flex-direction:row;border:none;border-radius:10px;background-color:var(--input-disabled-bg);width:50%;height:55px}.table-container .table-controls .filter-field input:focus{outline:none!important;box-shadow:none!important;border-color:transparent!important}.table-container .table-controls .filter-field .input-filter{width:100%;box-sizing:border-box;background-color:transparent;border:none;transition:none}.table-container .table-controls .filter-field i{color:var(--icon-collor);margin-left:8px}.table-container .mat-mdc-table{width:max-content;min-width:100%;background-color:var(--table-body-color)}.table-container .mat-mdc-table .mat-mdc-header-cell:first-child,.table-container .mat-mdc-table .mat-mdc-cell:first-child{border-right:none!important}.table-container .mat-mdc-table .mat-mdc-header-cell:not(:first-child),.table-container .mat-mdc-table .mat-mdc-cell:not(:first-child){border-right:1px solid var(--primary)}.table-container .mat-mdc-table .mat-mdc-header-cell:first-child,.table-container .mat-mdc-table .mat-mdc-cell:first-child{width:60px;max-width:60px;min-width:60px;border-right:none}.table-container .mat-mdc-table .mat-mdc-header-row{background-color:var(--table-header)}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell{border-right:1px solid var(--white);font-weight:600;color:var(--white);border-bottom:1px solid var(--input-background);text-transform:uppercase;font-size:.875rem}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row{transition:background-color .2s ease}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--primary);color:var(--gray-dark);border-bottom:1px solid var(--input-background)}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row:hover{background-color:#0000000a}.table-container .mat-mdc-table .mat-mdc-row.selected{background-color:#3f51b51a}.table-container .mat-mdc-table .mat-mdc-checkbox{margin-right:12px}.table-container .mat-mdc-table .mat-mdc-checkbox .mdc-checkbox{--mdc-checkbox-unselected-icon-color: var(--gray-dark);--mdc-checkbox-selected-icon-color: var(--info)}.table-container .mat-mdc-table .mat-mdc-footer-row{background-color:var(--table-background);font-weight:600;color:var(--input-disabled-bg)}.table-container .mat-mdc-table .mat-mdc-footer-row .mat-mdc-footer-cell{padding:12px;text-align:left;color:var(--gray-dark)}.table-container span,.table-container img{margin-right:10px}.table-container[_ngcontent-ng-c1530403114] .mat-mdc-table[_ngcontent-ng-c1530403114] .mat-mdc-footer-row[_ngcontent-ng-c1530403114]{display:none}.no-data-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:15px;font-size:1.1rem}.no-data-container .no-data-title{color:var(--table-header);margin-bottom:12px}.no-data-container .no-data-message{color:var(--table-header)}@media(max-width:768px){.table-container .table-controls{flex-direction:column;align-items:stretch}.table-container .table-controls .filter-field{margin-right:0;margin-bottom:12px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i2$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i1$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "directive", type: i7.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i7.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i8.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i8.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i8.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i8.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i8.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i8.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i8.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }, { kind: "pipe", type: i1.DatePipe, name: "date" }] });
1684
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
1685
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: BaseModal, isStandalone: true, selector: "cao-modal", inputs: { showModal: "showModal", title: "title", data: "data", modalTypeClass: "modalTypeClass", modalClass: "modalClass", modalSize: "modalSize", closeOnOverlayClick: "closeOnOverlayClick" }, ngImport: i0, template: "<div aria-hidden=\"true\" class=\"modal\" tabIndex=\"0\" [class.show]=\"showModal\" (keydown)=\"onOverlayClick()\"\n (click)=\"onOverlayClick()\">\n <div aria-hidden=\"true\" class=\"modal-dialog\" tabIndex=\"1\" [ngClass]=\"[modalSize, modalClass]\"\n (keydown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n</div>", styles: [".modal{width:100vw;height:100vh;align-items:center;justify-content:center;position:fixed;transition:.5s;top:-100vh;left:0}.modal .modal-dialog{padding:24px 34px;border-radius:20px;position:relative;max-width:1444px;height:auto;top:-100vh;transition:.5s;background-color:var(--bg-card);left:0}.modal .modal-dialog.custom{padding:0}.modal .modal-dialog.w-100{width:100%}.modal .modal-dialog.w-90{width:90%}.modal .modal-dialog.w-80{width:80%}.modal .modal-dialog.w-75{width:75%}.modal .modal-dialog.w-70{width:70%}.modal .modal-dialog.w-60{width:60%}.modal .modal-dialog.w-50{width:50%}.modal .modal-dialog.w-40{width:40%}.modal .modal-dialog.w-30{width:30%}.modal .modal-dialog.w-20{width:20%}.modal .modal-dialog.w-10{width:10%}.modal.show{z-index:1000;display:flex;top:0;background-color:#00000080}.modal.show .modal-dialog{top:0}@media(max-width:768px){.modal-dialog{width:90%;max-width:90vw;margin-left:0}}@media(min-width:769px){.modal-dialog{width:75%;margin-left:250px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
1806
1686
  }
1807
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTable, decorators: [{
1687
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseModal, decorators: [{
1808
1688
  type: Component,
1809
- args: [{ selector: "cao-table", imports: [CommonModule, MaterialModule, NgOptimizedImage], providers: [{ provide: MatPaginatorIntl, useValue: getPtBrPaginatorIntlBaseTable() }], template: "<div class=\"table-container\" [ngClass]=\"customClass\">\n @if (tableConfig) {\n <div class=\"table-controls\">\n <mat-menu #menuColunas=\"matMenu\">\n @for (column of allColumns; track column) {\n <button\n mat-menu-item\n [type]=\"'button'\" (click)=\"toggleColumnVisibility(column)\">\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-toggle-column-' + column\"\n [checked]=\"isColumnVisible(column)\">\n {{ getColumnHeader(column) }}\n </mat-checkbox>\n </button>\n }\n </mat-menu>\n </div>\n\n <table\n mat-table\n matSort\n class=\"mat-elevation-z8\"\n [dataSource]=\"dataSource\"\n (matSortChange)=\"announceSortChange($event)\">\n <ng-container matColumnDef=\"select\">\n <th *matHeaderCellDef mat-header-cell>\n <mat-checkbox\n data-cy=\"checkbox-select-all\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n (change)=\"$event ? toggleAllRows() : null\" />\n </th>\n <td *matCellDef=\"let row\" mat-cell>\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-select-row-' + row.id\"\n [checked]=\"selection.isSelected(row)\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(row) : null\" />\n </td>\n </ng-container>\n\n @for (column of displayedColumns; track column) {\n <ng-container [matColumnDef]=\"column\">\n <th *matHeaderCellDef mat-header-cell [mat-sort-header]=\"column\">\n <span>{{ getColumnHeader(column) }}</span>\n <img\n alt=\"icone\"\n [ngSrc]=\"'.src/assets/svg/arrow-left-double.svg'\"\n [fill]=\"true\"\n [matMenuTriggerFor]=\"menuColunas\" />\n <mat-menu #menuColunas=\"matMenu\">\n @for (column of allColumns; track column) {\n <button\n mat-menu-item\n [type]=\"'button'\" (click)=\"toggleColumnVisibility(column)\">\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-toggle-column-' + column\"\n [checked]=\"isColumnVisible(column)\">\n {{ getColumnHeader(column) }}\n </mat-checkbox>\n </button>\n }\n </mat-menu>\n </th>\n <td *matCellDef=\"let element\" mat-cell>\n @switch (getColumnType(column)) { @case ('STRING') {\n <span>{{ element[getColumnElement(column)] }}</span>\n } @case ('BOOLEAN') {\n <mat-checkbox\n disabled\n [attr.data-cy]=\"'checkbox-value-' + column + '-' + element.id\"\n [checked]=\"element[getColumnElement(column)]\" />\n } @case ('DATE') {\n <span>{{ element[getColumnElement(column)] | date:'mediumDate' }}</span>\n } @case ('NUMBER') {\n <span>{{ element[getColumnElement(column)] | number:'1.2-2' }}</span>\n } @case ('SINGLE_BUTTON') {\n <div>\n @for (btn of getColumnButtons(column); track btn) {\n <button\n mat-icon-button\n [type]=\"'button'\" [matTooltip]=\"btn.tooltip\" (click)=\"btn.onClick(element)\">\n <mat-icon>{{ btn.icon }}</mat-icon>\n </button>\n }\n </div>\n } @default {\n <span>{{ element[getColumnElement(column)] }}</span>\n } }\n </td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"footer\">\n <td *matFooterCellDef mat-footer-cell [attr.colspan]=\"displayedColumns.length + 1\">\n Total de Registros: {{ dataSource.data.length }}\n </td>\n </ng-container>\n\n <tr *matHeaderRowDef=\"getAllColumns()\" mat-header-row></tr>\n <tr\n *matRowDef=\"let row; columns: getAllColumns();\"\n mat-row\n (click)=\"selection.toggle(row)\"></tr>\n <tr *matFooterRowDef=\"['footer']\" mat-footer-row></tr>\n </table>\n }\n</div>\n\n<mat-paginator\n #paginator\n aria-label=\"Select page\"\n [length]=\"totalItems\"\n [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\"\n [pageIndex]=\"currentPage - 1\"\n [hidePageSize]=\"false\"\n [showFirstLastButtons]=\"showFirstLastButtons\"\n (page)=\"onPageEvent($event)\" />\n\n@if (!tableConfig || tableConfig.data.length === 0) {\n<div class=\"no-data-container\">\n <h2 class=\"no-data-title\">{{ tableConfig?.result?.noData || 'N\u00E3o h\u00E1 dados dispon\u00EDveis' }}</h2>\n <p class=\"no-data-message\"\n >{{ tableConfig?.result?.defaultMessage || 'Adicione alguns dados' }}</p\n >\n</div>\n}\n", styles: [".table-container{border-radius:8px;box-shadow:0 4px 6px #0000001a;max-width:100%;overflow:auto hidden}.table-container .table-controls{display:flex;align-items:center;padding:20px}.table-container .table-controls .filter-field{display:flex;align-items:center;justify-content:space-between;padding:10px;flex-direction:row;border:none;border-radius:10px;background-color:var(--input-disabled-bg);width:50%;height:55px}.table-container .table-controls .filter-field input:focus{outline:none!important;box-shadow:none!important;border-color:transparent!important}.table-container .table-controls .filter-field .input-filter{width:100%;box-sizing:border-box;background-color:transparent;border:none;transition:none}.table-container .table-controls .filter-field i{color:var(--icon-collor);margin-left:8px}.table-container .mat-mdc-table{width:max-content;min-width:100%;background-color:var(--table-body-color)}.table-container .mat-mdc-table .mat-mdc-header-cell:first-child,.table-container .mat-mdc-table .mat-mdc-cell:first-child{border-right:none!important}.table-container .mat-mdc-table .mat-mdc-header-cell:not(:first-child),.table-container .mat-mdc-table .mat-mdc-cell:not(:first-child){border-right:1px solid var(--primary)}.table-container .mat-mdc-table .mat-mdc-header-cell:first-child,.table-container .mat-mdc-table .mat-mdc-cell:first-child{width:60px;max-width:60px;min-width:60px;border-right:none}.table-container .mat-mdc-table .mat-mdc-header-row{background-color:var(--table-header)}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell{border-right:1px solid var(--white);font-weight:600;color:var(--white);border-bottom:1px solid var(--input-background);text-transform:uppercase;font-size:.875rem}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row{transition:background-color .2s ease}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--primary);color:var(--gray-dark);border-bottom:1px solid var(--input-background)}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row:hover{background-color:#0000000a}.table-container .mat-mdc-table .mat-mdc-row.selected{background-color:#3f51b51a}.table-container .mat-mdc-table .mat-mdc-checkbox{margin-right:12px}.table-container .mat-mdc-table .mat-mdc-checkbox .mdc-checkbox{--mdc-checkbox-unselected-icon-color: var(--gray-dark);--mdc-checkbox-selected-icon-color: var(--info)}.table-container .mat-mdc-table .mat-mdc-footer-row{background-color:var(--table-background);font-weight:600;color:var(--input-disabled-bg)}.table-container .mat-mdc-table .mat-mdc-footer-row .mat-mdc-footer-cell{padding:12px;text-align:left;color:var(--gray-dark)}.table-container span,.table-container img{margin-right:10px}.table-container[_ngcontent-ng-c1530403114] .mat-mdc-table[_ngcontent-ng-c1530403114] .mat-mdc-footer-row[_ngcontent-ng-c1530403114]{display:none}.no-data-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:15px;font-size:1.1rem}.no-data-container .no-data-title{color:var(--table-header);margin-bottom:12px}.no-data-container .no-data-message{color:var(--table-header)}@media(max-width:768px){.table-container .table-controls{flex-direction:column;align-items:stretch}.table-container .table-controls .filter-field{margin-right:0;margin-bottom:12px}}\n"] }]
1810
- }], ctorParameters: () => [], propDecorators: { customClass: [{
1689
+ args: [{ selector: 'cao-modal', imports: [CommonModule], template: "<div aria-hidden=\"true\" class=\"modal\" tabIndex=\"0\" [class.show]=\"showModal\" (keydown)=\"onOverlayClick()\"\n (click)=\"onOverlayClick()\">\n <div aria-hidden=\"true\" class=\"modal-dialog\" tabIndex=\"1\" [ngClass]=\"[modalSize, modalClass]\"\n (keydown)=\"$event.stopPropagation()\" (click)=\"$event.stopPropagation()\">\n <ng-content />\n </div>\n</div>", styles: [".modal{width:100vw;height:100vh;align-items:center;justify-content:center;position:fixed;transition:.5s;top:-100vh;left:0}.modal .modal-dialog{padding:24px 34px;border-radius:20px;position:relative;max-width:1444px;height:auto;top:-100vh;transition:.5s;background-color:var(--bg-card);left:0}.modal .modal-dialog.custom{padding:0}.modal .modal-dialog.w-100{width:100%}.modal .modal-dialog.w-90{width:90%}.modal .modal-dialog.w-80{width:80%}.modal .modal-dialog.w-75{width:75%}.modal .modal-dialog.w-70{width:70%}.modal .modal-dialog.w-60{width:60%}.modal .modal-dialog.w-50{width:50%}.modal .modal-dialog.w-40{width:40%}.modal .modal-dialog.w-30{width:30%}.modal .modal-dialog.w-20{width:20%}.modal .modal-dialog.w-10{width:10%}.modal.show{z-index:1000;display:flex;top:0;background-color:#00000080}.modal.show .modal-dialog{top:0}@media(max-width:768px){.modal-dialog{width:90%;max-width:90vw;margin-left:0}}@media(min-width:769px){.modal-dialog{width:75%;margin-left:250px}}\n"] }]
1690
+ }], propDecorators: { showModal: [{
1811
1691
  type: Input
1812
- }], pageSizeOptions: [{
1692
+ }], title: [{
1813
1693
  type: Input
1814
- }], showFirstLastButtons: [{
1694
+ }], data: [{
1815
1695
  type: Input
1816
- }], isPaginatedByServer: [{
1696
+ }], modalTypeClass: [{
1697
+ type: Input
1698
+ }], modalClass: [{
1699
+ type: Input
1700
+ }], modalSize: [{
1701
+ type: Input
1702
+ }], closeOnOverlayClick: [{
1817
1703
  type: Input
1818
- }], pageChanged: [{
1819
- type: Output
1820
- }], pageSizeChanged: [{
1821
- type: Output
1822
- }], firstPageClicked: [{
1823
- type: Output
1824
- }], lastPageClicked: [{
1825
- type: Output
1826
- }], selectionChanged: [{
1827
- type: Output
1828
- }], pageEvent: [{
1829
- type: Output
1830
- }], sort: [{
1831
- type: ViewChild,
1832
- args: [MatSort]
1833
- }], paginator: [{
1834
- type: ViewChild,
1835
- args: [MatPaginator]
1836
1704
  }] } });
1837
1705
 
1838
- class BaseFilterTablePaginatedService {
1839
- filterSubject = new Subject();
1840
- filter$ = this.filterSubject.asObservable();
1841
- updateFilter(filterValue) {
1842
- this.filterSubject.next(filterValue);
1706
+ class BaseDialog {
1707
+ config;
1708
+ closeDialog = this.noop;
1709
+ iconPaths = {
1710
+ success: "https://placehold.co/600x400",
1711
+ error: "https://placehold.co/600x400",
1712
+ info: "https://placehold.co/600x400",
1713
+ warning: "https://placehold.co/600x400",
1714
+ };
1715
+ noop() {
1716
+ return;
1843
1717
  }
1844
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTablePaginatedService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1845
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTablePaginatedService, providedIn: "root" });
1846
- }
1847
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTablePaginatedService, decorators: [{
1848
- type: Injectable,
1849
- args: [{
1850
- providedIn: "root",
1851
- }]
1852
- }] });
1853
-
1854
- class BasePaginationService {
1855
- pageSubject = new BehaviorSubject(1);
1856
- pageSizeSubject = new BehaviorSubject(10);
1857
- totalItemsSubject = new BehaviorSubject(0);
1858
- currentPage$ = this.pageSubject.asObservable();
1859
- pageSize$ = this.pageSizeSubject.asObservable();
1860
- totalItems$ = this.totalItemsSubject.asObservable();
1861
- constructor() { }
1862
- /**
1863
- * Sets the current page number
1864
- * @param page The page number to set
1865
- */
1866
- setPage(page) {
1867
- if (page !== this.pageSubject.value) {
1868
- this.pageSubject.next(page);
1869
- }
1718
+ getIconPath() {
1719
+ return this.iconPaths[this.config.type];
1870
1720
  }
1871
- /**
1872
- * Sets the page size
1873
- * @param size The page size to set
1874
- */
1875
- setPageSize(size) {
1876
- if (size !== this.pageSizeSubject.value) {
1877
- this.pageSizeSubject.next(size);
1878
- }
1721
+ handleConfirm() {
1722
+ this.config.onConfirm?.();
1723
+ this.closeDialog();
1879
1724
  }
1880
- /**
1881
- * Sets the total number of items
1882
- * @param total The total number of items
1883
- */
1884
- setTotalItems(total) {
1885
- if (total !== this.totalItemsSubject.value) {
1886
- this.totalItemsSubject.next(total);
1887
- }
1725
+ handleCancel() {
1726
+ this.config.onCancel?.();
1727
+ this.closeDialog();
1888
1728
  }
1889
- /**
1890
- * Gets the current page
1891
- */
1892
- getCurrentPage() {
1893
- return this.pageSubject.value;
1729
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
1730
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: BaseDialog, isStandalone: true, selector: "cao-dialog", inputs: { config: "config" }, ngImport: i0, template: "\n<div class=\"dialog-container\">\n <div class=\"dialog-content\">\n <img alt=\"Logo\" class=\"logo\" [fill]=\"true\" [ngSrc]=\"config.logoIcon ?? ''\" />\n <div class=\"alert-wrapper\">\n <div class=\"text-content\" [ngClass]=\"config.type\">\n <div class=\"title\">{{ config.title }}</div>\n <div class=\"message\">{{ config.message }}</div>\n <div class=\"button-container\">\n @if (config.cancelButtonText) {\n <button\n type=\"button\"\n class=\"cancel-button\"\n [attr.data-cy]=\"config.cancelButtonText\"\n (keydown)=\"handleCancel()\"\n (click)=\"handleCancel()\">\n {{ config.cancelButtonText }}\n </button>\n } @if (config.confirmButtonText) {\n <button\n type=\"button\"\n class=\"confirm-button\"\n [ngClass]=\"config.type\"\n [attr.data-cy]=\"config.confirmButtonText\"\n (click)=\"handleConfirm()\"\n (keydown)=\"handleConfirm()\"\n >\n {{ config.confirmButtonText }}\n </button>\n }\n </div>\n </div>\n <div class=\"icon-container\">\n <img alt=\"Dialog Icon\" class=\"alert-icon\" [fill]=\"true\" [ngSrc]=\"getIconPath()\" />\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{position:fixed;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;z-index:1000;background:#0009}.dialog-container{width:600px;border-radius:30px;overflow:hidden;box-shadow:0 4px 6px #0000001a;background-color:var(--white);max-width:90%;margin-left:250px}.dialog-content{padding:20px 30px;box-sizing:border-box}.logo{width:150px;height:24px;margin-bottom:15px}.alert-wrapper{display:flex;align-items:center;justify-content:space-between}.button-container{display:flex;gap:10px}.confirm-button,.cancel-button{padding:10px 20px;border:none;border-radius:20px;cursor:pointer;font-weight:600;transition:all .3s ease}.confirm-button{color:var(--white);background-color:var(--primary)}.cancel-button{background-color:var(--disabled-button);color:var(--white)}.confirm-button:hover,.cancel-button:hover{opacity:.9}.text-content{flex-grow:1;padding-right:20px}.text-content .title{font-weight:700;font-size:20px;color:var(--primary);margin-bottom:10px}.text-content.success .title{color:var(--primary)}.text-content.error .title{color:var(--error-color)}.text-content.error .confirm-button{background-color:var(--error-color)}.text-content.warning .title{color:var(--support-orange)}.text-content.info .title{color:var(--primary)}.text-content.info .confirm-button{background-color:var(--primary)}.message{font-weight:400;font-size:16px;color:var(--message-color);margin-bottom:15px}.icon-container{width:150px;height:150px;flex-shrink:0}.alert-icon{width:100%;height:100%;object-fit:contain}@media(max-width:768px){.dialog-container{width:400px;max-width:90%;margin-left:0}.alert-wrapper{flex-direction:column;text-align:center}.text-content{padding-right:0;margin-bottom:10px}.icon-container{width:100px;height:100px}.button-container{flex-direction:column;width:100%}.confirm-button,.cancel-button{width:100%;margin-bottom:10px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }] });
1731
+ }
1732
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseDialog, decorators: [{
1733
+ type: Component,
1734
+ args: [{ selector: 'cao-dialog', imports: [CommonModule, NgOptimizedImage], template: "\n<div class=\"dialog-container\">\n <div class=\"dialog-content\">\n <img alt=\"Logo\" class=\"logo\" [fill]=\"true\" [ngSrc]=\"config.logoIcon ?? ''\" />\n <div class=\"alert-wrapper\">\n <div class=\"text-content\" [ngClass]=\"config.type\">\n <div class=\"title\">{{ config.title }}</div>\n <div class=\"message\">{{ config.message }}</div>\n <div class=\"button-container\">\n @if (config.cancelButtonText) {\n <button\n type=\"button\"\n class=\"cancel-button\"\n [attr.data-cy]=\"config.cancelButtonText\"\n (keydown)=\"handleCancel()\"\n (click)=\"handleCancel()\">\n {{ config.cancelButtonText }}\n </button>\n } @if (config.confirmButtonText) {\n <button\n type=\"button\"\n class=\"confirm-button\"\n [ngClass]=\"config.type\"\n [attr.data-cy]=\"config.confirmButtonText\"\n (click)=\"handleConfirm()\"\n (keydown)=\"handleConfirm()\"\n >\n {{ config.confirmButtonText }}\n </button>\n }\n </div>\n </div>\n <div class=\"icon-container\">\n <img alt=\"Dialog Icon\" class=\"alert-icon\" [fill]=\"true\" [ngSrc]=\"getIconPath()\" />\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{position:fixed;top:0;left:0;width:100%;height:100%;display:flex;align-items:center;justify-content:center;z-index:1000;background:#0009}.dialog-container{width:600px;border-radius:30px;overflow:hidden;box-shadow:0 4px 6px #0000001a;background-color:var(--white);max-width:90%;margin-left:250px}.dialog-content{padding:20px 30px;box-sizing:border-box}.logo{width:150px;height:24px;margin-bottom:15px}.alert-wrapper{display:flex;align-items:center;justify-content:space-between}.button-container{display:flex;gap:10px}.confirm-button,.cancel-button{padding:10px 20px;border:none;border-radius:20px;cursor:pointer;font-weight:600;transition:all .3s ease}.confirm-button{color:var(--white);background-color:var(--primary)}.cancel-button{background-color:var(--disabled-button);color:var(--white)}.confirm-button:hover,.cancel-button:hover{opacity:.9}.text-content{flex-grow:1;padding-right:20px}.text-content .title{font-weight:700;font-size:20px;color:var(--primary);margin-bottom:10px}.text-content.success .title{color:var(--primary)}.text-content.error .title{color:var(--error-color)}.text-content.error .confirm-button{background-color:var(--error-color)}.text-content.warning .title{color:var(--support-orange)}.text-content.info .title{color:var(--primary)}.text-content.info .confirm-button{background-color:var(--primary)}.message{font-weight:400;font-size:16px;color:var(--message-color);margin-bottom:15px}.icon-container{width:150px;height:150px;flex-shrink:0}.alert-icon{width:100%;height:100%;object-fit:contain}@media(max-width:768px){.dialog-container{width:400px;max-width:90%;margin-left:0}.alert-wrapper{flex-direction:column;text-align:center}.text-content{padding-right:0;margin-bottom:10px}.icon-container{width:100px;height:100px}.button-container{flex-direction:column;width:100%}.confirm-button,.cancel-button{width:100%;margin-bottom:10px}}\n"] }]
1735
+ }], propDecorators: { config: [{
1736
+ type: Input
1737
+ }] } });
1738
+
1739
+ class BaseDialogService {
1740
+ overlay;
1741
+ constructor(overlay) {
1742
+ this.overlay = overlay;
1894
1743
  }
1895
- /**
1896
- * Gets the current page size
1897
- */
1898
- getPageSize() {
1899
- return this.pageSizeSubject.value;
1744
+ open(config) {
1745
+ const overlayRef = this.overlay.create({
1746
+ hasBackdrop: true,
1747
+ positionStrategy: this.overlay.position().global().centerHorizontally().centerVertically(),
1748
+ scrollStrategy: this.overlay.scrollStrategies.block(),
1749
+ backdropClass: "dialog-backdrop",
1750
+ });
1751
+ const dialogPortal = new ComponentPortal(this.generateComponentPortal());
1752
+ const componentRef = overlayRef.attach(dialogPortal);
1753
+ componentRef.instance.config = config;
1754
+ componentRef.instance.closeDialog = () => {
1755
+ overlayRef.dispose();
1756
+ };
1757
+ return overlayRef;
1900
1758
  }
1901
- /**
1902
- * Gets the total number of items
1903
- */
1904
- getTotalItems() {
1905
- return this.totalItemsSubject.value;
1759
+ generateComponentPortal() {
1760
+ return BaseDialog;
1906
1761
  }
1907
- /**
1908
- * Resets pagination to default values
1909
- */
1910
- reset() {
1911
- this.pageSubject.next(1);
1912
- this.pageSizeSubject.next(10);
1913
- this.totalItemsSubject.next(0);
1762
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseDialogService, deps: [{ token: i1$4.Overlay }], target: i0.ɵɵFactoryTarget.Injectable });
1763
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseDialogService, providedIn: "root" });
1764
+ }
1765
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseDialogService, decorators: [{
1766
+ type: Injectable,
1767
+ args: [{
1768
+ providedIn: "root",
1769
+ }]
1770
+ }], ctorParameters: () => [{ type: i1$4.Overlay }] });
1771
+
1772
+ class BaseFilterTableService {
1773
+ filterSubject = new Subject();
1774
+ filter$ = this.filterSubject.asObservable();
1775
+ updateFilter(filterValue) {
1776
+ this.filterSubject.next(filterValue);
1914
1777
  }
1915
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BasePaginationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1916
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BasePaginationService, providedIn: "root" });
1778
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTableService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1779
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTableService, providedIn: "root" });
1917
1780
  }
1918
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BasePaginationService, decorators: [{
1781
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTableService, decorators: [{
1919
1782
  type: Injectable,
1920
1783
  args: [{
1921
1784
  providedIn: "root",
1922
1785
  }]
1923
- }], ctorParameters: () => [] });
1786
+ }] });
1924
1787
 
1925
- class TablePaginatedService {
1788
+ class BaseTableService {
1926
1789
  tableConfigSubject = new BehaviorSubject(null);
1927
1790
  dataSubject = new BehaviorSubject([]);
1928
1791
  columnsSubject = new BehaviorSubject([]);
@@ -2033,17 +1896,17 @@ class TablePaginatedService {
2033
1896
  updateTableData(data) {
2034
1897
  this.setData(data);
2035
1898
  }
2036
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TablePaginatedService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2037
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TablePaginatedService, providedIn: "root" });
1899
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTableService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1900
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTableService, providedIn: "root" });
2038
1901
  }
2039
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TablePaginatedService, decorators: [{
1902
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTableService, decorators: [{
2040
1903
  type: Injectable,
2041
1904
  args: [{
2042
1905
  providedIn: "root",
2043
1906
  }]
2044
1907
  }] });
2045
1908
 
2046
- function getPtBrPaginatorIntlBasePaginated() {
1909
+ function getPtBrPaginatorIntlBaseTable() {
2047
1910
  const paginatorIntl = new MatPaginatorIntl();
2048
1911
  paginatorIntl.itemsPerPageLabel = "Itens por página:";
2049
1912
  paginatorIntl.nextPageLabel = "Próxima página";
@@ -2060,19 +1923,17 @@ function getPtBrPaginatorIntlBasePaginated() {
2060
1923
  };
2061
1924
  return paginatorIntl;
2062
1925
  }
2063
- class BaseTablePaginated {
2064
- paginationSubscriptions = [];
2065
- getColumnCssClass;
1926
+ class BaseTable {
2066
1927
  customClass = "";
2067
1928
  pageSizeOptions = [5, 10, 20, 50];
2068
1929
  showFirstLastButtons = true;
1930
+ isPaginatedByServer = false;
2069
1931
  pageChanged = new EventEmitter();
2070
1932
  pageSizeChanged = new EventEmitter();
2071
1933
  firstPageClicked = new EventEmitter();
2072
1934
  lastPageClicked = new EventEmitter();
2073
1935
  selectionChanged = new EventEmitter();
2074
1936
  pageEvent = new EventEmitter();
2075
- rowClicked = new EventEmitter();
2076
1937
  dataSource = new MatTableDataSource([]);
2077
1938
  selection = new SelectionModel(true, []);
2078
1939
  allColumns = [];
@@ -2089,21 +1950,16 @@ class BaseTablePaginated {
2089
1950
  pageSize = 10;
2090
1951
  currentPage = 1;
2091
1952
  previousPage = 1;
2092
- paginationService = inject(BasePaginationService);
2093
- tableService = inject(TablePaginatedService);
1953
+ getAllColumns() {
1954
+ return ["select", ...this.displayedColumns];
1955
+ }
1956
+ tableService = inject(BaseTableService);
2094
1957
  liveAnnouncer = inject(LiveAnnouncer);
2095
- filterTableService = inject(BaseFilterTablePaginatedService);
1958
+ filterTableService = inject(BaseFilterTableService);
2096
1959
  constructor() {
2097
1960
  this.initializeSortingAccessor();
2098
1961
  this.initializeFilterPredicate();
2099
1962
  }
2100
- onPageChanged(page) {
2101
- this.currentPage = page;
2102
- this.pageChanged.emit(page);
2103
- if (this.paginator && this.paginator.pageIndex !== page - 1) {
2104
- this.paginator.pageIndex = page - 1;
2105
- }
2106
- }
2107
1963
  ngOnInit() {
2108
1964
  this.configSubscription = this.tableService.tableConfig$.subscribe((config) => {
2109
1965
  if (config) {
@@ -2118,77 +1974,31 @@ class BaseTablePaginated {
2118
1974
  this.dataSource.data = data;
2119
1975
  this.updateTotalItems();
2120
1976
  });
2121
- this.filterSubscription = this.filterTableService.filter$.subscribe((filterValue) => {
2122
- this.filterValue = filterValue;
2123
- this.applyFilter();
1977
+ this.filterSubscription = this.filterTableService.filter$.subscribe((filterValue) => {
1978
+ this.filterValue = filterValue;
1979
+ this.applyFilter();
1980
+ });
1981
+ }
1982
+ ngAfterViewInit() {
1983
+ this.dataSource.sort = this.sort;
1984
+ // Connect paginator if available
1985
+ setTimeout(() => {
1986
+ if (this.paginator) {
1987
+ this.dataSource.paginator = this.paginator;
1988
+ this.paginator.pageIndex = this.currentPage - 1;
1989
+ this.paginator.pageSize = this.pageSize;
1990
+ this.paginator.showFirstLastButtons = this.showFirstLastButtons;
1991
+ }
1992
+ });
1993
+ this.selection.changed.subscribe(() => {
1994
+ this.selectionChanged.emit(this.selection.selected);
2124
1995
  });
2125
- this.paginationSubscriptions.push(this.paginationService.currentPage$.subscribe((page) => {
2126
- if (this.currentPage !== page) {
2127
- this.onPageChanged(page);
2128
- }
2129
- }), this.paginationService.pageSize$.subscribe((size) => {
2130
- if (this.pageSize !== size) {
2131
- this.onPageSizeChanged(size);
2132
- }
2133
- }));
2134
1996
  }
2135
1997
  ngOnDestroy() {
2136
1998
  this.configSubscription?.unsubscribe();
2137
1999
  this.visibleColumnsSubscription?.unsubscribe();
2138
2000
  this.dataSubscription?.unsubscribe();
2139
2001
  this.filterSubscription?.unsubscribe();
2140
- this.paginationSubscriptions.forEach((sub) => sub.unsubscribe());
2141
- }
2142
- updateTotalItems(newTotalItens) {
2143
- this.totalItems = newTotalItens ?? this.totalItems;
2144
- this.paginationService.setTotalItems(this.totalItems);
2145
- const lastPage = this.pageSize > 0 ? Math.ceil(this.totalItems / this.pageSize) : 1;
2146
- const lastValidPage = lastPage > 0 ? lastPage : 1;
2147
- if (this.currentPage > lastValidPage) {
2148
- this.paginationService.setPage(1);
2149
- }
2150
- }
2151
- onPageSizeChanged(pageSize) {
2152
- this.pageSize = pageSize;
2153
- this.pageSizeChanged.emit(pageSize);
2154
- if (this.paginator && this.paginator.pageSize !== pageSize) {
2155
- this.paginator.pageSize = pageSize;
2156
- }
2157
- }
2158
- getColumnHeader(column) {
2159
- if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2160
- return column;
2161
- }
2162
- return this.tableConfig.columnData[column].header || column;
2163
- }
2164
- getColumnElement(column) {
2165
- if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2166
- return column;
2167
- }
2168
- return this.tableConfig.columnData[column].element || column;
2169
- }
2170
- getColumnType(column) {
2171
- if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2172
- return "STRING";
2173
- }
2174
- return this.tableConfig.columnData[column].type || "STRING";
2175
- }
2176
- announceSortChange(sortState) {
2177
- if (sortState.direction) {
2178
- this.liveAnnouncer.announce(`Ordenado ${sortState.direction === "asc" ? "ascendente" : "descendente"}`);
2179
- }
2180
- else {
2181
- this.liveAnnouncer.announce("Ordenação removida");
2182
- }
2183
- }
2184
- handlePageChange(event) {
2185
- this.pageSize = event.pageSize;
2186
- this.paginationService.setPageSize(event.pageSize);
2187
- this.pageChanged.emit(event.pageIndex);
2188
- }
2189
- applyFilter() {
2190
- const normalizedFilter = this.filterValue.trim().toLowerCase();
2191
- this.dataSource.filter = normalizedFilter;
2192
2002
  }
2193
2003
  initializeSortingAccessor() {
2194
2004
  this.dataSource.sortingDataAccessor = (item, property) => {
@@ -2231,9 +2041,99 @@ class BaseTablePaginated {
2231
2041
  return dataStr.indexOf(searchTerms) !== -1;
2232
2042
  };
2233
2043
  }
2234
- onRowClick(row) {
2235
- this.rowClicked.emit(row);
2044
+ applyFilter() {
2045
+ const normalizedFilter = this.filterValue.trim().toLowerCase();
2046
+ this.dataSource.filter = normalizedFilter;
2047
+ }
2048
+ toggleColumnVisibility(columnKey) {
2049
+ this.tableService.toggleColumnVisibility(columnKey);
2050
+ }
2051
+ isColumnVisible(column) {
2052
+ if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2053
+ return true;
2054
+ }
2055
+ return this.tableConfig.columnData[column].visible !== false;
2056
+ }
2057
+ getColumnHeader(column) {
2058
+ if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2059
+ return column;
2060
+ }
2061
+ return this.tableConfig.columnData[column].header || column;
2062
+ }
2063
+ getColumnType(column) {
2064
+ if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2065
+ return "STRING";
2066
+ }
2067
+ return this.tableConfig.columnData[column].type || "STRING";
2068
+ }
2069
+ getColumnElement(column) {
2070
+ if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2071
+ return column;
2072
+ }
2073
+ return this.tableConfig.columnData[column].element || column;
2074
+ }
2075
+ getColumnButtons(column) {
2076
+ if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2077
+ return [];
2078
+ }
2079
+ return this.tableConfig.columnData[column].buttons || [];
2080
+ }
2081
+ isAllSelected() {
2082
+ if (!this.paginator ||
2083
+ !this.dataSource.filteredData ||
2084
+ this.dataSource.filteredData.length === 0) {
2085
+ return false;
2086
+ }
2087
+ const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
2088
+ const endIndex = Math.min(startIndex + this.paginator.pageSize, this.dataSource.filteredData.length);
2089
+ const currentPageData = this.dataSource.filteredData.slice(startIndex, endIndex);
2090
+ if (currentPageData.length === 0) {
2091
+ return false;
2092
+ }
2093
+ return currentPageData.every((row) => this.selection.isSelected(row));
2094
+ }
2095
+ toggleAllRows() {
2096
+ if (!this.paginator || !this.dataSource.filteredData) {
2097
+ return;
2098
+ }
2099
+ if (this.isAllSelected()) {
2100
+ this.selection.clear();
2101
+ }
2102
+ else {
2103
+ const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
2104
+ const endIndex = Math.min(startIndex + this.paginator.pageSize, this.dataSource.filteredData.length);
2105
+ const currentPageData = this.dataSource.filteredData.slice(startIndex, endIndex);
2106
+ currentPageData.forEach((row) => this.selection.select(row));
2107
+ }
2108
+ }
2109
+ announceSortChange(sortState) {
2110
+ if (sortState.direction) {
2111
+ this.liveAnnouncer.announce(`Ordenado ${sortState.direction === "asc" ? "ascendente" : "descendente"}`);
2112
+ }
2113
+ else {
2114
+ this.liveAnnouncer.announce("Ordenação removida");
2115
+ }
2116
+ }
2117
+ trackByFn(index, item) {
2118
+ return item;
2119
+ }
2120
+ onPageChanged(page) {
2121
+ this.currentPage = page;
2122
+ this.pageChanged.emit(page);
2123
+ if (this.paginator && this.paginator.pageIndex !== page - 1) {
2124
+ this.paginator.pageIndex = page - 1;
2125
+ }
2126
+ }
2127
+ onPageSizeChanged(pageSize) {
2128
+ this.pageSize = pageSize;
2129
+ this.pageSizeChanged.emit(pageSize);
2130
+ if (this.paginator && this.paginator.pageSize !== pageSize) {
2131
+ this.paginator.pageSize = pageSize;
2132
+ }
2236
2133
  }
2134
+ /**
2135
+ * Handle pagination events from Mat Paginator
2136
+ */
2237
2137
  onPageEvent(event) {
2238
2138
  const newPage = event.pageIndex + 1;
2239
2139
  const isFirstPage = newPage === 1 && this.previousPage !== 1;
@@ -2258,26 +2158,50 @@ class BaseTablePaginated {
2258
2158
  }
2259
2159
  this.pageEvent.emit(event);
2260
2160
  }
2261
- getColumnButtons(column) {
2262
- if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2263
- return [];
2161
+ /**
2162
+ * Navigate to first page programmatically
2163
+ */
2164
+ goToFirstPage() {
2165
+ if (this.currentPage !== 1) {
2166
+ this.onPageChanged(1);
2167
+ this.firstPageClicked.emit();
2168
+ this.liveAnnouncer.announce("Primeira página");
2264
2169
  }
2265
- return this.tableConfig.columnData[column].buttons || [];
2266
2170
  }
2267
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTablePaginated, deps: [], target: i0.ɵɵFactoryTarget.Component });
2268
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: BaseTablePaginated, isStandalone: true, selector: "cao-table-paginated", inputs: { getColumnCssClass: "getColumnCssClass", customClass: "customClass", pageSizeOptions: "pageSizeOptions", showFirstLastButtons: "showFirstLastButtons" }, outputs: { pageChanged: "pageChanged", pageSizeChanged: "pageSizeChanged", firstPageClicked: "firstPageClicked", lastPageClicked: "lastPageClicked", selectionChanged: "selectionChanged", pageEvent: "pageEvent", rowClicked: "rowClicked" }, providers: [{ provide: MatPaginatorIntl, useValue: getPtBrPaginatorIntlBasePaginated() }], viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }], ngImport: i0, template: "<div class=\"table-container\" [ngClass]=\"customClass\">\n @if (tableConfig) {\n <table mat-table matSort [dataSource]=\"dataSource\" (matSortChange)=\"announceSortChange($event)\">\n @for (column of displayedColumns; track column) {\n <ng-container [matColumnDef]=\"column\">\n <th *matHeaderCellDef mat-header-cell mat-sort-header class=\"table-header\">\n {{ getColumnHeader(column) }}\n </th>\n <td *matCellDef=\"let element\" mat-cell class=\"table-cell\">\n @switch (getColumnType(column)) { @case ('STRING') { @if (getColumnCssClass &&\n getColumnCssClass(column, element[getColumnElement(column)])) {\n <span [class]=\"getColumnCssClass(column, element[getColumnElement(column)])\">\n {{ element[getColumnElement(column)] }}\n </span>\n } @else {\n <span>{{ element[getColumnElement(column)] }}</span>\n } } @case ('BOOLEAN') {\n <mat-checkbox disabled [checked]=\"element[getColumnElement(column)]\" />\n } @case ('DATE') {\n <span>{{ element[getColumnElement(column)] | date:'mediumDate' }}</span>\n } @case ('NUMBER') {\n <span>{{ element[getColumnElement(column)] | number:'1.2-2' }}</span>\n } @case ('SINGLE_BUTTON') {\n <div>\n @for (btn of getColumnButtons(column); track btn) {\n <button type=\"button\" mat-icon-button [matTooltip]=\"btn.tooltip\" (click)=\"btn.onClick(element)\">\n <mat-icon>{{ btn.icon }}</mat-icon>\n </button>\n }\n </div>\n } }\n </td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"footer\">\n <td\n *matFooterCellDef\n mat-footer-cell\n class=\"table-cell\"\n [attr.colspan]=\"displayedColumns.length\">\n Total de Registros: {{ totalItems }}\n </td>\n </ng-container>\n\n <tr *matHeaderRowDef=\"displayedColumns\" mat-header-row></tr>\n <tr *matRowDef=\"let row; columns: displayedColumns;\" mat-row (click)=\"onRowClick(row)\"></tr>\n <tr *matFooterRowDef=\"['footer']\" mat-footer-row class=\"mat-row-footer\"></tr>\n </table>\n @if(totalItems > 0){\n\n <mat-paginator\n #paginator\n aria-label=\"Select page\"\n [length]=\"totalItems\"\n [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\"\n [pageIndex]=\"currentPage - 1\"\n [hidePageSize]=\"false\"\n [showFirstLastButtons]=\"showFirstLastButtons\"\n (page)=\"onPageEvent($event)\" />\n } @else {\n <div class=\"no-data-container\">\n <h2>{{ tableConfig?.result?.noData ?? 'N\u00E3o h\u00E1 dados dispon\u00EDveis' }}</h2>\n <p>{{ tableConfig?.result?.defaultMessage ?? 'Adicione alguns dados' }}</p>\n </div>\n } }\n</div>\n", styles: [".table-container{border-radius:8px;box-shadow:0 4px 6px #0000001a;overflow:hidden}.table-container .table-controls{display:flex;align-items:center;padding:20px;justify-content:center}.table-container .table-controls .filter-field{display:flex;align-items:center;justify-content:space-between;padding:10px;flex-direction:row;border:none;border-radius:10px;background-color:var(--input-disabled-bg);width:50%;height:55px;margin:0 auto}.table-container .table-controls .filter-field input:focus{outline:none!important;box-shadow:none!important;border-color:transparent!important}.table-container .table-controls .filter-field .input-filter{width:100%;box-sizing:border-box;background-color:transparent;border:none;transition:none;text-align:center}.table-container .table-controls .filter-field i{color:var(--icon-collor);margin-left:8px}.table-container .mat-mdc-table{width:100%}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell{border-right:1px solid var(--data-bg);font-weight:600;color:var(--message-color);border-bottom:1px solid var(--input-background);text-transform:uppercase;font-size:.875rem;text-align:center;padding:12px;vertical-align:middle}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell .mat-sort-header-container{justify-content:center}.table-container .mat-mdc-table .mat-mdc-row{transition:background-color .2s ease;background-color:transparent}.table-container .mat-mdc-table .mat-mdc-row:nth-child(2n){background-color:transparent}.table-container .mat-mdc-table .mat-mdc-row:nth-child(odd){background-color:var(--input-background)}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--border-table-ligth);color:var(--gray-dark);border-bottom:1px solid var(--input-background);text-align:center;padding:12px;vertical-align:middle}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row:hover{background-color:#0000000a}.table-container .mat-mdc-table .mat-mdc-row.selected{background-color:#3f51b51a}.table-container .mat-mdc-table .mat-mdc-checkbox{margin:0 auto;display:block}.table-container .mat-mdc-table .mat-mdc-checkbox .mdc-checkbox{--mdc-checkbox-unselected-icon-color: var(--gray-dark);--mdc-checkbox-selected-icon-color: var(--info)}.table-container .mat-mdc-table .mat-mdc-footer-row{background-color:var(--table-background);font-weight:600;color:var(--text-color)}.table-container .mat-mdc-table .mat-mdc-footer-row .mat-mdc-footer-cell{padding:12px;text-align:center}.table-container .no-data-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;text-align:center;background-color:var(--table-background)}.table-container .no-data-container h2{color:var(--input-disabled-bg);margin-bottom:12px}.table-container .no-data-container p{color:var(--input-disabled-bg)}@media(width<=768px){.table-container .table-controls{flex-direction:column;align-items:center}.table-container .table-controls .filter-field{width:80%;margin-right:0;margin-bottom:12px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i2$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i1$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "directive", type: i7.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i7.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i8.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i8.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i8.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i8.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i8.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i8.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i8.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }, { kind: "pipe", type: i1.DatePipe, name: "date" }], encapsulation: i0.ViewEncapsulation.None });
2171
+ /**
2172
+ * Navigate to last page programmatically
2173
+ */
2174
+ goToLastPage() {
2175
+ const lastPage = Math.max(1, Math.ceil(this.totalItems / this.pageSize));
2176
+ if (this.currentPage !== lastPage) {
2177
+ this.onPageChanged(lastPage);
2178
+ this.lastPageClicked.emit();
2179
+ this.liveAnnouncer.announce("Última página");
2180
+ }
2181
+ }
2182
+ /**
2183
+ * Update total items when data changes
2184
+ */
2185
+ updateTotalItems() {
2186
+ if (this.isPaginatedByServer) {
2187
+ return;
2188
+ }
2189
+ this.totalItems = this.dataSource.data.length;
2190
+ }
2191
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
2192
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: BaseTable, isStandalone: true, selector: "cao-table", inputs: { customClass: "customClass", pageSizeOptions: "pageSizeOptions", showFirstLastButtons: "showFirstLastButtons", isPaginatedByServer: "isPaginatedByServer" }, outputs: { pageChanged: "pageChanged", pageSizeChanged: "pageSizeChanged", firstPageClicked: "firstPageClicked", lastPageClicked: "lastPageClicked", selectionChanged: "selectionChanged", pageEvent: "pageEvent" }, providers: [{ provide: MatPaginatorIntl, useValue: getPtBrPaginatorIntlBaseTable() }], viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }], ngImport: i0, template: "<div class=\"table-container\" [ngClass]=\"customClass\">\n @if (tableConfig) {\n <div class=\"table-controls\">\n <mat-menu #menuColunas=\"matMenu\">\n @for (column of allColumns; track column) {\n <button\n mat-menu-item\n [type]=\"'button'\" (click)=\"toggleColumnVisibility(column)\">\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-toggle-column-' + column\"\n [checked]=\"isColumnVisible(column)\">\n {{ getColumnHeader(column) }}\n </mat-checkbox>\n </button>\n }\n </mat-menu>\n </div>\n\n <table\n mat-table\n matSort\n class=\"mat-elevation-z8\"\n [dataSource]=\"dataSource\"\n (matSortChange)=\"announceSortChange($event)\">\n <ng-container matColumnDef=\"select\">\n <th *matHeaderCellDef mat-header-cell>\n <mat-checkbox\n data-cy=\"checkbox-select-all\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n (change)=\"$event ? toggleAllRows() : null\" />\n </th>\n <td *matCellDef=\"let row\" mat-cell>\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-select-row-' + row.id\"\n [checked]=\"selection.isSelected(row)\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(row) : null\" />\n </td>\n </ng-container>\n\n @for (column of displayedColumns; track column) {\n <ng-container [matColumnDef]=\"column\">\n <th *matHeaderCellDef mat-header-cell [mat-sort-header]=\"column\">\n <span>{{ getColumnHeader(column) }}</span>\n <img\n alt=\"icone\"\n [ngSrc]=\"'.src/assets/svg/arrow-left-double.svg'\"\n [fill]=\"true\"\n [matMenuTriggerFor]=\"menuColunas\" />\n <mat-menu #menuColunas=\"matMenu\">\n @for (column of allColumns; track column) {\n <button\n mat-menu-item\n [type]=\"'button'\" (click)=\"toggleColumnVisibility(column)\">\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-toggle-column-' + column\"\n [checked]=\"isColumnVisible(column)\">\n {{ getColumnHeader(column) }}\n </mat-checkbox>\n </button>\n }\n </mat-menu>\n </th>\n <td *matCellDef=\"let element\" mat-cell>\n @switch (getColumnType(column)) { @case ('STRING') {\n <span>{{ element[getColumnElement(column)] }}</span>\n } @case ('BOOLEAN') {\n <mat-checkbox\n disabled\n [attr.data-cy]=\"'checkbox-value-' + column + '-' + element.id\"\n [checked]=\"element[getColumnElement(column)]\" />\n } @case ('DATE') {\n <span>{{ element[getColumnElement(column)] | date:'mediumDate' }}</span>\n } @case ('NUMBER') {\n <span>{{ element[getColumnElement(column)] | number:'1.2-2' }}</span>\n } @case ('SINGLE_BUTTON') {\n <div>\n @for (btn of getColumnButtons(column); track btn) {\n <button\n mat-icon-button\n [type]=\"'button'\" [matTooltip]=\"btn.tooltip\" (click)=\"btn.onClick(element)\">\n <mat-icon>{{ btn.icon }}</mat-icon>\n </button>\n }\n </div>\n } @default {\n <span>{{ element[getColumnElement(column)] }}</span>\n } }\n </td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"footer\">\n <td *matFooterCellDef mat-footer-cell [attr.colspan]=\"displayedColumns.length + 1\">\n Total de Registros: {{ dataSource.data.length }}\n </td>\n </ng-container>\n\n <tr *matHeaderRowDef=\"getAllColumns()\" mat-header-row></tr>\n <tr\n *matRowDef=\"let row; columns: getAllColumns();\"\n mat-row\n (click)=\"selection.toggle(row)\"></tr>\n <tr *matFooterRowDef=\"['footer']\" mat-footer-row></tr>\n </table>\n }\n</div>\n\n<mat-paginator\n #paginator\n aria-label=\"Select page\"\n [length]=\"totalItems\"\n [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\"\n [pageIndex]=\"currentPage - 1\"\n [hidePageSize]=\"false\"\n [showFirstLastButtons]=\"showFirstLastButtons\"\n (page)=\"onPageEvent($event)\" />\n\n@if (!tableConfig || tableConfig.data.length === 0) {\n<div class=\"no-data-container\">\n <h2 class=\"no-data-title\">{{ tableConfig?.result?.noData || 'N\u00E3o h\u00E1 dados dispon\u00EDveis' }}</h2>\n <p class=\"no-data-message\"\n >{{ tableConfig?.result?.defaultMessage || 'Adicione alguns dados' }}</p\n >\n</div>\n}\n", styles: [".table-container{border-radius:8px;box-shadow:0 4px 6px #0000001a;max-width:100%;overflow:auto hidden}.table-container .table-controls{display:flex;align-items:center;padding:20px}.table-container .table-controls .filter-field{display:flex;align-items:center;justify-content:space-between;padding:10px;flex-direction:row;border:none;border-radius:10px;background-color:var(--input-disabled-bg);width:50%;height:55px}.table-container .table-controls .filter-field input:focus{outline:none!important;box-shadow:none!important;border-color:transparent!important}.table-container .table-controls .filter-field .input-filter{width:100%;box-sizing:border-box;background-color:transparent;border:none;transition:none}.table-container .table-controls .filter-field i{color:var(--icon-collor);margin-left:8px}.table-container .mat-mdc-table{width:max-content;min-width:100%;background-color:var(--table-body-color)}.table-container .mat-mdc-table .mat-mdc-header-cell:first-child,.table-container .mat-mdc-table .mat-mdc-cell:first-child{border-right:none!important}.table-container .mat-mdc-table .mat-mdc-header-cell:not(:first-child),.table-container .mat-mdc-table .mat-mdc-cell:not(:first-child){border-right:1px solid var(--primary)}.table-container .mat-mdc-table .mat-mdc-header-cell:first-child,.table-container .mat-mdc-table .mat-mdc-cell:first-child{width:60px;max-width:60px;min-width:60px;border-right:none}.table-container .mat-mdc-table .mat-mdc-header-row{background-color:var(--table-header)}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell{border-right:1px solid var(--white);font-weight:600;color:var(--white);border-bottom:1px solid var(--input-background);text-transform:uppercase;font-size:.875rem}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row{transition:background-color .2s ease}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--primary);color:var(--gray-dark);border-bottom:1px solid var(--input-background)}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row:hover{background-color:#0000000a}.table-container .mat-mdc-table .mat-mdc-row.selected{background-color:#3f51b51a}.table-container .mat-mdc-table .mat-mdc-checkbox{margin-right:12px}.table-container .mat-mdc-table .mat-mdc-checkbox .mdc-checkbox{--mdc-checkbox-unselected-icon-color: var(--gray-dark);--mdc-checkbox-selected-icon-color: var(--info)}.table-container .mat-mdc-table .mat-mdc-footer-row{background-color:var(--table-background);font-weight:600;color:var(--input-disabled-bg)}.table-container .mat-mdc-table .mat-mdc-footer-row .mat-mdc-footer-cell{padding:12px;text-align:left;color:var(--gray-dark)}.table-container span,.table-container img{margin-right:10px}.table-container[_ngcontent-ng-c1530403114] .mat-mdc-table[_ngcontent-ng-c1530403114] .mat-mdc-footer-row[_ngcontent-ng-c1530403114]{display:none}.no-data-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:15px;font-size:1.1rem}.no-data-container .no-data-title{color:var(--table-header);margin-bottom:12px}.no-data-container .no-data-message{color:var(--table-header)}@media(max-width:768px){.table-container .table-controls{flex-direction:column;align-items:stretch}.table-container .table-controls .filter-field{margin-right:0;margin-bottom:12px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i2$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5$1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i5$1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i5$1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i1$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "directive", type: i7.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i7.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i8.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i8.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i8.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i8.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i8.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i8.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i8.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }, { kind: "pipe", type: i1.DatePipe, name: "date" }] });
2269
2193
  }
2270
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTablePaginated, decorators: [{
2194
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTable, decorators: [{
2271
2195
  type: Component,
2272
- args: [{ selector: "cao-table-paginated", encapsulation: ViewEncapsulation.None, imports: [CommonModule, MaterialModule], providers: [{ provide: MatPaginatorIntl, useValue: getPtBrPaginatorIntlBasePaginated() }], template: "<div class=\"table-container\" [ngClass]=\"customClass\">\n @if (tableConfig) {\n <table mat-table matSort [dataSource]=\"dataSource\" (matSortChange)=\"announceSortChange($event)\">\n @for (column of displayedColumns; track column) {\n <ng-container [matColumnDef]=\"column\">\n <th *matHeaderCellDef mat-header-cell mat-sort-header class=\"table-header\">\n {{ getColumnHeader(column) }}\n </th>\n <td *matCellDef=\"let element\" mat-cell class=\"table-cell\">\n @switch (getColumnType(column)) { @case ('STRING') { @if (getColumnCssClass &&\n getColumnCssClass(column, element[getColumnElement(column)])) {\n <span [class]=\"getColumnCssClass(column, element[getColumnElement(column)])\">\n {{ element[getColumnElement(column)] }}\n </span>\n } @else {\n <span>{{ element[getColumnElement(column)] }}</span>\n } } @case ('BOOLEAN') {\n <mat-checkbox disabled [checked]=\"element[getColumnElement(column)]\" />\n } @case ('DATE') {\n <span>{{ element[getColumnElement(column)] | date:'mediumDate' }}</span>\n } @case ('NUMBER') {\n <span>{{ element[getColumnElement(column)] | number:'1.2-2' }}</span>\n } @case ('SINGLE_BUTTON') {\n <div>\n @for (btn of getColumnButtons(column); track btn) {\n <button type=\"button\" mat-icon-button [matTooltip]=\"btn.tooltip\" (click)=\"btn.onClick(element)\">\n <mat-icon>{{ btn.icon }}</mat-icon>\n </button>\n }\n </div>\n } }\n </td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"footer\">\n <td\n *matFooterCellDef\n mat-footer-cell\n class=\"table-cell\"\n [attr.colspan]=\"displayedColumns.length\">\n Total de Registros: {{ totalItems }}\n </td>\n </ng-container>\n\n <tr *matHeaderRowDef=\"displayedColumns\" mat-header-row></tr>\n <tr *matRowDef=\"let row; columns: displayedColumns;\" mat-row (click)=\"onRowClick(row)\"></tr>\n <tr *matFooterRowDef=\"['footer']\" mat-footer-row class=\"mat-row-footer\"></tr>\n </table>\n @if(totalItems > 0){\n\n <mat-paginator\n #paginator\n aria-label=\"Select page\"\n [length]=\"totalItems\"\n [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\"\n [pageIndex]=\"currentPage - 1\"\n [hidePageSize]=\"false\"\n [showFirstLastButtons]=\"showFirstLastButtons\"\n (page)=\"onPageEvent($event)\" />\n } @else {\n <div class=\"no-data-container\">\n <h2>{{ tableConfig?.result?.noData ?? 'N\u00E3o h\u00E1 dados dispon\u00EDveis' }}</h2>\n <p>{{ tableConfig?.result?.defaultMessage ?? 'Adicione alguns dados' }}</p>\n </div>\n } }\n</div>\n", styles: [".table-container{border-radius:8px;box-shadow:0 4px 6px #0000001a;overflow:hidden}.table-container .table-controls{display:flex;align-items:center;padding:20px;justify-content:center}.table-container .table-controls .filter-field{display:flex;align-items:center;justify-content:space-between;padding:10px;flex-direction:row;border:none;border-radius:10px;background-color:var(--input-disabled-bg);width:50%;height:55px;margin:0 auto}.table-container .table-controls .filter-field input:focus{outline:none!important;box-shadow:none!important;border-color:transparent!important}.table-container .table-controls .filter-field .input-filter{width:100%;box-sizing:border-box;background-color:transparent;border:none;transition:none;text-align:center}.table-container .table-controls .filter-field i{color:var(--icon-collor);margin-left:8px}.table-container .mat-mdc-table{width:100%}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell{border-right:1px solid var(--data-bg);font-weight:600;color:var(--message-color);border-bottom:1px solid var(--input-background);text-transform:uppercase;font-size:.875rem;text-align:center;padding:12px;vertical-align:middle}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell .mat-sort-header-container{justify-content:center}.table-container .mat-mdc-table .mat-mdc-row{transition:background-color .2s ease;background-color:transparent}.table-container .mat-mdc-table .mat-mdc-row:nth-child(2n){background-color:transparent}.table-container .mat-mdc-table .mat-mdc-row:nth-child(odd){background-color:var(--input-background)}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--border-table-ligth);color:var(--gray-dark);border-bottom:1px solid var(--input-background);text-align:center;padding:12px;vertical-align:middle}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row:hover{background-color:#0000000a}.table-container .mat-mdc-table .mat-mdc-row.selected{background-color:#3f51b51a}.table-container .mat-mdc-table .mat-mdc-checkbox{margin:0 auto;display:block}.table-container .mat-mdc-table .mat-mdc-checkbox .mdc-checkbox{--mdc-checkbox-unselected-icon-color: var(--gray-dark);--mdc-checkbox-selected-icon-color: var(--info)}.table-container .mat-mdc-table .mat-mdc-footer-row{background-color:var(--table-background);font-weight:600;color:var(--text-color)}.table-container .mat-mdc-table .mat-mdc-footer-row .mat-mdc-footer-cell{padding:12px;text-align:center}.table-container .no-data-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;text-align:center;background-color:var(--table-background)}.table-container .no-data-container h2{color:var(--input-disabled-bg);margin-bottom:12px}.table-container .no-data-container p{color:var(--input-disabled-bg)}@media(width<=768px){.table-container .table-controls{flex-direction:column;align-items:center}.table-container .table-controls .filter-field{width:80%;margin-right:0;margin-bottom:12px}}\n"] }]
2273
- }], ctorParameters: () => [], propDecorators: { getColumnCssClass: [{
2274
- type: Input
2275
- }], customClass: [{
2196
+ args: [{ selector: "cao-table", imports: [CommonModule, MaterialModule, NgOptimizedImage], providers: [{ provide: MatPaginatorIntl, useValue: getPtBrPaginatorIntlBaseTable() }], template: "<div class=\"table-container\" [ngClass]=\"customClass\">\n @if (tableConfig) {\n <div class=\"table-controls\">\n <mat-menu #menuColunas=\"matMenu\">\n @for (column of allColumns; track column) {\n <button\n mat-menu-item\n [type]=\"'button'\" (click)=\"toggleColumnVisibility(column)\">\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-toggle-column-' + column\"\n [checked]=\"isColumnVisible(column)\">\n {{ getColumnHeader(column) }}\n </mat-checkbox>\n </button>\n }\n </mat-menu>\n </div>\n\n <table\n mat-table\n matSort\n class=\"mat-elevation-z8\"\n [dataSource]=\"dataSource\"\n (matSortChange)=\"announceSortChange($event)\">\n <ng-container matColumnDef=\"select\">\n <th *matHeaderCellDef mat-header-cell>\n <mat-checkbox\n data-cy=\"checkbox-select-all\"\n [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\"\n (change)=\"$event ? toggleAllRows() : null\" />\n </th>\n <td *matCellDef=\"let row\" mat-cell>\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-select-row-' + row.id\"\n [checked]=\"selection.isSelected(row)\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"$event ? selection.toggle(row) : null\" />\n </td>\n </ng-container>\n\n @for (column of displayedColumns; track column) {\n <ng-container [matColumnDef]=\"column\">\n <th *matHeaderCellDef mat-header-cell [mat-sort-header]=\"column\">\n <span>{{ getColumnHeader(column) }}</span>\n <img\n alt=\"icone\"\n [ngSrc]=\"'.src/assets/svg/arrow-left-double.svg'\"\n [fill]=\"true\"\n [matMenuTriggerFor]=\"menuColunas\" />\n <mat-menu #menuColunas=\"matMenu\">\n @for (column of allColumns; track column) {\n <button\n mat-menu-item\n [type]=\"'button'\" (click)=\"toggleColumnVisibility(column)\">\n <mat-checkbox\n [attr.data-cy]=\"'checkbox-toggle-column-' + column\"\n [checked]=\"isColumnVisible(column)\">\n {{ getColumnHeader(column) }}\n </mat-checkbox>\n </button>\n }\n </mat-menu>\n </th>\n <td *matCellDef=\"let element\" mat-cell>\n @switch (getColumnType(column)) { @case ('STRING') {\n <span>{{ element[getColumnElement(column)] }}</span>\n } @case ('BOOLEAN') {\n <mat-checkbox\n disabled\n [attr.data-cy]=\"'checkbox-value-' + column + '-' + element.id\"\n [checked]=\"element[getColumnElement(column)]\" />\n } @case ('DATE') {\n <span>{{ element[getColumnElement(column)] | date:'mediumDate' }}</span>\n } @case ('NUMBER') {\n <span>{{ element[getColumnElement(column)] | number:'1.2-2' }}</span>\n } @case ('SINGLE_BUTTON') {\n <div>\n @for (btn of getColumnButtons(column); track btn) {\n <button\n mat-icon-button\n [type]=\"'button'\" [matTooltip]=\"btn.tooltip\" (click)=\"btn.onClick(element)\">\n <mat-icon>{{ btn.icon }}</mat-icon>\n </button>\n }\n </div>\n } @default {\n <span>{{ element[getColumnElement(column)] }}</span>\n } }\n </td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"footer\">\n <td *matFooterCellDef mat-footer-cell [attr.colspan]=\"displayedColumns.length + 1\">\n Total de Registros: {{ dataSource.data.length }}\n </td>\n </ng-container>\n\n <tr *matHeaderRowDef=\"getAllColumns()\" mat-header-row></tr>\n <tr\n *matRowDef=\"let row; columns: getAllColumns();\"\n mat-row\n (click)=\"selection.toggle(row)\"></tr>\n <tr *matFooterRowDef=\"['footer']\" mat-footer-row></tr>\n </table>\n }\n</div>\n\n<mat-paginator\n #paginator\n aria-label=\"Select page\"\n [length]=\"totalItems\"\n [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\"\n [pageIndex]=\"currentPage - 1\"\n [hidePageSize]=\"false\"\n [showFirstLastButtons]=\"showFirstLastButtons\"\n (page)=\"onPageEvent($event)\" />\n\n@if (!tableConfig || tableConfig.data.length === 0) {\n<div class=\"no-data-container\">\n <h2 class=\"no-data-title\">{{ tableConfig?.result?.noData || 'N\u00E3o h\u00E1 dados dispon\u00EDveis' }}</h2>\n <p class=\"no-data-message\"\n >{{ tableConfig?.result?.defaultMessage || 'Adicione alguns dados' }}</p\n >\n</div>\n}\n", styles: [".table-container{border-radius:8px;box-shadow:0 4px 6px #0000001a;max-width:100%;overflow:auto hidden}.table-container .table-controls{display:flex;align-items:center;padding:20px}.table-container .table-controls .filter-field{display:flex;align-items:center;justify-content:space-between;padding:10px;flex-direction:row;border:none;border-radius:10px;background-color:var(--input-disabled-bg);width:50%;height:55px}.table-container .table-controls .filter-field input:focus{outline:none!important;box-shadow:none!important;border-color:transparent!important}.table-container .table-controls .filter-field .input-filter{width:100%;box-sizing:border-box;background-color:transparent;border:none;transition:none}.table-container .table-controls .filter-field i{color:var(--icon-collor);margin-left:8px}.table-container .mat-mdc-table{width:max-content;min-width:100%;background-color:var(--table-body-color)}.table-container .mat-mdc-table .mat-mdc-header-cell:first-child,.table-container .mat-mdc-table .mat-mdc-cell:first-child{border-right:none!important}.table-container .mat-mdc-table .mat-mdc-header-cell:not(:first-child),.table-container .mat-mdc-table .mat-mdc-cell:not(:first-child){border-right:1px solid var(--primary)}.table-container .mat-mdc-table .mat-mdc-header-cell:first-child,.table-container .mat-mdc-table .mat-mdc-cell:first-child{width:60px;max-width:60px;min-width:60px;border-right:none}.table-container .mat-mdc-table .mat-mdc-header-row{background-color:var(--table-header)}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell{border-right:1px solid var(--white);font-weight:600;color:var(--white);border-bottom:1px solid var(--input-background);text-transform:uppercase;font-size:.875rem}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row{transition:background-color .2s ease}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--primary);color:var(--gray-dark);border-bottom:1px solid var(--input-background)}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row:hover{background-color:#0000000a}.table-container .mat-mdc-table .mat-mdc-row.selected{background-color:#3f51b51a}.table-container .mat-mdc-table .mat-mdc-checkbox{margin-right:12px}.table-container .mat-mdc-table .mat-mdc-checkbox .mdc-checkbox{--mdc-checkbox-unselected-icon-color: var(--gray-dark);--mdc-checkbox-selected-icon-color: var(--info)}.table-container .mat-mdc-table .mat-mdc-footer-row{background-color:var(--table-background);font-weight:600;color:var(--input-disabled-bg)}.table-container .mat-mdc-table .mat-mdc-footer-row .mat-mdc-footer-cell{padding:12px;text-align:left;color:var(--gray-dark)}.table-container span,.table-container img{margin-right:10px}.table-container[_ngcontent-ng-c1530403114] .mat-mdc-table[_ngcontent-ng-c1530403114] .mat-mdc-footer-row[_ngcontent-ng-c1530403114]{display:none}.no-data-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:15px;font-size:1.1rem}.no-data-container .no-data-title{color:var(--table-header);margin-bottom:12px}.no-data-container .no-data-message{color:var(--table-header)}@media(max-width:768px){.table-container .table-controls{flex-direction:column;align-items:stretch}.table-container .table-controls .filter-field{margin-right:0;margin-bottom:12px}}\n"] }]
2197
+ }], ctorParameters: () => [], propDecorators: { customClass: [{
2276
2198
  type: Input
2277
2199
  }], pageSizeOptions: [{
2278
2200
  type: Input
2279
2201
  }], showFirstLastButtons: [{
2280
2202
  type: Input
2203
+ }], isPaginatedByServer: [{
2204
+ type: Input
2281
2205
  }], pageChanged: [{
2282
2206
  type: Output
2283
2207
  }], pageSizeChanged: [{
@@ -2290,440 +2214,536 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
2290
2214
  type: Output
2291
2215
  }], pageEvent: [{
2292
2216
  type: Output
2293
- }], rowClicked: [{
2294
- type: Output
2295
2217
  }], sort: [{
2296
2218
  type: ViewChild,
2297
2219
  args: [MatSort]
2298
- }], paginator: [{
2299
- type: ViewChild,
2300
- args: [MatPaginator]
2301
- }] } });
2302
-
2303
- class BaseAlert {
2304
- data;
2305
- iconPath;
2306
- titleClass;
2307
- iconPaths = {
2308
- success: "https://placehold.co/600x400",
2309
- error: "https://placehold.co/600x400",
2310
- info: "https://placehold.co/600x400",
2311
- warning: "https://placehold.co/600x400",
2312
- };
2313
- ngOnInit() {
2314
- this.iconPath = this.iconPaths[this.data.type];
2315
- this.titleClass = `title-${this.data.type}`;
2316
- }
2317
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseAlert, deps: [], target: i0.ɵɵFactoryTarget.Component });
2318
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: BaseAlert, isStandalone: true, selector: "cao-alert", ngImport: i0, template: "<div class=\"dialog-container\">\n <div class=\"dialog-content\">\n <img alt=\"Logo\" class=\"logo\" [ngSrc]=\"data.alertIcon ?? ''\" [fill]=\"true\" />\n <div class=\"alert-wrapper\">\n <div class=\"text-content\">\n @if (data.title) {\n <div class=\"title\" [ngClass]=\"titleClass\">{{ data.title }}</div>\n } @if (data.title && data.message) {\n <div class=\"message-spacer\"></div>\n } @if (data.message) {\n <div class=\"message\">{{ data.message }}</div>\n }\n </div>\n <div class=\"icon-container\">\n <img alt=\"Alert Icon\" class=\"alert-icon\" [ngSrc]=\"iconPath\" [fill]=\"true\" />\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{position:fixed;top:10%;left:55%;transform:translate(-50%);z-index:1000;display:block;animation:slide-in .3s ease-out}@keyframes slide-in{0%{opacity:0;transform:translate(-50%,-20px)}to{opacity:1;transform:translate(-50%)}}.dialog-container{width:600px;border-radius:30px;overflow:hidden;box-shadow:0 4px 6px #0000001a;background-color:var(--white)}.dialog-content{padding:20px 30px;box-sizing:border-box}.logo{width:150px;height:24px;margin-bottom:15px}.alert-wrapper{display:flex;align-items:center;justify-content:space-between}.text-content{flex-grow:1;margin:20px;padding-right:20px}.title{font-family:Lato,sans-serif;font-weight:700;font-size:24px;color:var(--primary);margin-bottom:5px}.title.success{color:var(--primary)}.title.error{color:var(--error-color)}.title.warning{color:var(--support-orange)}.title.info,.title.title-success{color:var(--primary)}.title.title-error{color:var(--error)}.title.title-warning{color:var(--support-orange)}.title.title-info{color:var(--primary)}.message-spacer{height:16px}.message{font-family:Lato,sans-serif;font-weight:400;font-size:26px;line-height:100%;color:var(--message-color)}.icon-container{width:150px;height:150px;flex-shrink:0}.alert-icon{width:100%;height:100%;object-fit:contain}@media(max-width:768px){:host{left:55%;max-width:95%}.dialog-container{max-width:90%;width:400px}.alert-wrapper{flex-direction:column;text-align:center}.text-content{padding-right:0;margin-bottom:10px}.icon-container{width:100px;height:100px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2319
- }
2320
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseAlert, decorators: [{
2321
- type: Component,
2322
- args: [{ selector: 'cao-alert', imports: [CommonModule, NgOptimizedImage], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"dialog-container\">\n <div class=\"dialog-content\">\n <img alt=\"Logo\" class=\"logo\" [ngSrc]=\"data.alertIcon ?? ''\" [fill]=\"true\" />\n <div class=\"alert-wrapper\">\n <div class=\"text-content\">\n @if (data.title) {\n <div class=\"title\" [ngClass]=\"titleClass\">{{ data.title }}</div>\n } @if (data.title && data.message) {\n <div class=\"message-spacer\"></div>\n } @if (data.message) {\n <div class=\"message\">{{ data.message }}</div>\n }\n </div>\n <div class=\"icon-container\">\n <img alt=\"Alert Icon\" class=\"alert-icon\" [ngSrc]=\"iconPath\" [fill]=\"true\" />\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{position:fixed;top:10%;left:55%;transform:translate(-50%);z-index:1000;display:block;animation:slide-in .3s ease-out}@keyframes slide-in{0%{opacity:0;transform:translate(-50%,-20px)}to{opacity:1;transform:translate(-50%)}}.dialog-container{width:600px;border-radius:30px;overflow:hidden;box-shadow:0 4px 6px #0000001a;background-color:var(--white)}.dialog-content{padding:20px 30px;box-sizing:border-box}.logo{width:150px;height:24px;margin-bottom:15px}.alert-wrapper{display:flex;align-items:center;justify-content:space-between}.text-content{flex-grow:1;margin:20px;padding-right:20px}.title{font-family:Lato,sans-serif;font-weight:700;font-size:24px;color:var(--primary);margin-bottom:5px}.title.success{color:var(--primary)}.title.error{color:var(--error-color)}.title.warning{color:var(--support-orange)}.title.info,.title.title-success{color:var(--primary)}.title.title-error{color:var(--error)}.title.title-warning{color:var(--support-orange)}.title.title-info{color:var(--primary)}.message-spacer{height:16px}.message{font-family:Lato,sans-serif;font-weight:400;font-size:26px;line-height:100%;color:var(--message-color)}.icon-container{width:150px;height:150px;flex-shrink:0}.alert-icon{width:100%;height:100%;object-fit:contain}@media(max-width:768px){:host{left:55%;max-width:95%}.dialog-container{max-width:90%;width:400px}.alert-wrapper{flex-direction:column;text-align:center}.text-content{padding-right:0;margin-bottom:10px}.icon-container{width:100px;height:100px}}\n"] }]
2323
- }] });
2324
-
2325
- class BaseAlertService {
2326
- overlay;
2327
- constructor(overlay) {
2328
- this.overlay = overlay;
2329
- }
2330
- defaultTime = 3000;
2331
- show(config) {
2332
- const overlayRef = this.overlay.create({
2333
- hasBackdrop: false,
2334
- positionStrategy: this.overlay.position().global().centerHorizontally().top("10%"),
2335
- scrollStrategy: this.overlay.scrollStrategies.block(),
2336
- });
2337
- const alertPortal = new ComponentPortal(this.generateComponentPortal());
2338
- const componentRef = overlayRef.attach(alertPortal);
2339
- componentRef.instance.data = config;
2340
- setTimeout(() => {
2341
- overlayRef.dispose();
2342
- }, this.defaultTime);
2343
- }
2344
- generateComponentPortal() {
2345
- return BaseAlert;
2220
+ }], paginator: [{
2221
+ type: ViewChild,
2222
+ args: [MatPaginator]
2223
+ }] } });
2224
+
2225
+ class BaseFilterTablePaginatedService {
2226
+ filterSubject = new Subject();
2227
+ filter$ = this.filterSubject.asObservable();
2228
+ updateFilter(filterValue) {
2229
+ this.filterSubject.next(filterValue);
2346
2230
  }
2347
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseAlertService, deps: [{ token: i1$4.Overlay }], target: i0.ɵɵFactoryTarget.Injectable });
2348
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseAlertService, providedIn: "root" });
2231
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTablePaginatedService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2232
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTablePaginatedService, providedIn: "root" });
2349
2233
  }
2350
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseAlertService, decorators: [{
2234
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseFilterTablePaginatedService, decorators: [{
2351
2235
  type: Injectable,
2352
2236
  args: [{
2353
2237
  providedIn: "root",
2354
2238
  }]
2355
- }], ctorParameters: () => [{ type: i1$4.Overlay }] });
2356
-
2357
- class StepComponent {
2358
- title = "";
2359
- isActive = false;
2360
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: StepComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2361
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: StepComponent, isStandalone: true, selector: "cao-step", inputs: { title: "title", isActive: "isActive" }, ngImport: i0, template: "<div class=\"step d-flex aic jcc\" [ngClass]=\"{'active': isActive}\"> {{ title }} </div>\n", styles: [".step{width:44px;height:44px;border-radius:100%;font-size:18px;font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
2362
- }
2363
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: StepComponent, decorators: [{
2364
- type: Component,
2365
- args: [{ selector: "cao-step", standalone: true, imports: [CommonModule], template: "<div class=\"step d-flex aic jcc\" [ngClass]=\"{'active': isActive}\"> {{ title }} </div>\n", styles: [".step{width:44px;height:44px;border-radius:100%;font-size:18px;font-weight:700}\n"] }]
2366
- }], propDecorators: { title: [{
2367
- type: Input
2368
- }], isActive: [{
2369
- type: Input
2370
- }] } });
2239
+ }] });
2371
2240
 
2372
- class StepperComponent {
2241
+ class BasePaginationService {
2242
+ pageSubject = new BehaviorSubject(1);
2243
+ pageSizeSubject = new BehaviorSubject(10);
2244
+ totalItemsSubject = new BehaviorSubject(0);
2245
+ currentPage$ = this.pageSubject.asObservable();
2246
+ pageSize$ = this.pageSizeSubject.asObservable();
2247
+ totalItems$ = this.totalItemsSubject.asObservable();
2373
2248
  constructor() { }
2374
- steps;
2375
- title;
2376
- activeStepIndex = 0;
2377
- lengthStep = 0;
2378
- showLine = true;
2379
- maxReachedEvent = new EventEmitter();
2380
- ngAfterContentInit() {
2381
- if (this.steps.length > 0) {
2382
- this.steps.toArray()[0].isActive = true;
2383
- this.lengthStep = this.steps.length;
2249
+ /**
2250
+ * Sets the current page number
2251
+ * @param page The page number to set
2252
+ */
2253
+ setPage(page) {
2254
+ if (page !== this.pageSubject.value) {
2255
+ this.pageSubject.next(page);
2384
2256
  }
2385
2257
  }
2386
- nextStep() {
2387
- if (this.steps.length > 0) {
2388
- if (this.activeStepIndex < this.steps.length - 1) {
2389
- this.activeStepIndex++;
2390
- this.steps.toArray()[this.activeStepIndex].isActive = true;
2391
- }
2392
- else {
2393
- this.maxReachedEvent.emit(null);
2394
- }
2258
+ /**
2259
+ * Sets the page size
2260
+ * @param size The page size to set
2261
+ */
2262
+ setPageSize(size) {
2263
+ if (size !== this.pageSizeSubject.value) {
2264
+ this.pageSizeSubject.next(size);
2395
2265
  }
2396
2266
  }
2397
- prevStep() {
2398
- if (this.steps.length > 0) {
2399
- if (this.activeStepIndex > 0) {
2400
- this.steps.toArray()[this.activeStepIndex].isActive = false;
2401
- this.activeStepIndex--;
2402
- this.steps.toArray()[this.activeStepIndex].isActive = true;
2403
- }
2267
+ /**
2268
+ * Sets the total number of items
2269
+ * @param total The total number of items
2270
+ */
2271
+ setTotalItems(total) {
2272
+ if (total !== this.totalItemsSubject.value) {
2273
+ this.totalItemsSubject.next(total);
2404
2274
  }
2405
2275
  }
2406
- resetStepper() {
2407
- this.activeStepIndex = 0;
2408
- this.steps.forEach((step) => (step.isActive = false));
2409
- if (this.steps.length > 0) {
2410
- this.steps.toArray()[0].isActive = true;
2411
- }
2276
+ /**
2277
+ * Gets the current page
2278
+ */
2279
+ getCurrentPage() {
2280
+ return this.pageSubject.value;
2412
2281
  }
2413
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: StepperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2414
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: StepperComponent, isStandalone: true, selector: "cao-stepper", inputs: { title: "title" }, outputs: { maxReachedEvent: "maxReachedEvent" }, queries: [{ propertyName: "steps", predicate: StepComponent }], ngImport: i0, template: "@if(title){\n<h3 class=\"stepper-title\">{{ title }}</h3>\n}\n<div class=\"d-flex step-container aic jcsb\">\n @if (showLine) {\n <div class=\"line\"></div>\n }\n <div class=\"steps d-flex aic jcsb\">\n <ng-content />\n </div>\n</div>\n", styles: [".step-container{position:relative}.steps{z-index:2;gap:24px}.line{width:100%;position:absolute;top:50%;height:1.5px;background-color:var(--return-color);z-index:1}\n"] });
2415
- }
2416
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: StepperComponent, decorators: [{
2417
- type: Component,
2418
- args: [{ selector: "cao-stepper", standalone: true, template: "@if(title){\n<h3 class=\"stepper-title\">{{ title }}</h3>\n}\n<div class=\"d-flex step-container aic jcsb\">\n @if (showLine) {\n <div class=\"line\"></div>\n }\n <div class=\"steps d-flex aic jcsb\">\n <ng-content />\n </div>\n</div>\n", styles: [".step-container{position:relative}.steps{z-index:2;gap:24px}.line{width:100%;position:absolute;top:50%;height:1.5px;background-color:var(--return-color);z-index:1}\n"] }]
2419
- }], ctorParameters: () => [], propDecorators: { steps: [{
2420
- type: ContentChildren,
2421
- args: [StepComponent]
2422
- }], title: [{
2423
- type: Input
2424
- }], maxReachedEvent: [{
2425
- type: Output
2426
- }] } });
2427
-
2428
- class CaoTabContentDirective {
2429
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2430
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: CaoTabContentDirective, isStandalone: true, selector: "[caoTabContent]", ngImport: i0 });
2282
+ /**
2283
+ * Gets the current page size
2284
+ */
2285
+ getPageSize() {
2286
+ return this.pageSizeSubject.value;
2287
+ }
2288
+ /**
2289
+ * Gets the total number of items
2290
+ */
2291
+ getTotalItems() {
2292
+ return this.totalItemsSubject.value;
2293
+ }
2294
+ /**
2295
+ * Resets pagination to default values
2296
+ */
2297
+ reset() {
2298
+ this.pageSubject.next(1);
2299
+ this.pageSizeSubject.next(10);
2300
+ this.totalItemsSubject.next(0);
2301
+ }
2302
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BasePaginationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2303
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BasePaginationService, providedIn: "root" });
2431
2304
  }
2432
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabContentDirective, decorators: [{
2433
- type: Directive,
2305
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BasePaginationService, decorators: [{
2306
+ type: Injectable,
2434
2307
  args: [{
2435
- selector: '[caoTabContent]',
2436
- standalone: true,
2308
+ providedIn: "root",
2437
2309
  }]
2438
- }] });
2310
+ }], ctorParameters: () => [] });
2439
2311
 
2440
- class CaoTabLabelDirective {
2441
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabLabelDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2442
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: CaoTabLabelDirective, isStandalone: true, selector: "[caoTabLabel]", ngImport: i0 });
2312
+ class TablePaginatedService {
2313
+ tableConfigSubject = new BehaviorSubject(null);
2314
+ dataSubject = new BehaviorSubject([]);
2315
+ columnsSubject = new BehaviorSubject([]);
2316
+ tableConfig$ = this.tableConfigSubject.asObservable();
2317
+ columns$ = this.columnsSubject.asObservable();
2318
+ data$ = this.dataSubject.asObservable();
2319
+ visibleColumns$ = this.columns$.pipe(map((columns) => columns.filter((col) => col.visible).map((col) => col.key || col.element || "")));
2320
+ createTable(data, columns, customConfig) {
2321
+ const tableConfig = {
2322
+ columns: columns ? columns.map((col) => col.key || col.element || "") : [],
2323
+ data,
2324
+ columnData: {},
2325
+ result: {
2326
+ noData: "Não há dados para o filtro selecionado.",
2327
+ defaultMessage: "Nenhum resultado encontrado.",
2328
+ },
2329
+ ...customConfig,
2330
+ };
2331
+ if (data.length > 0 && columns) {
2332
+ const columnData = {};
2333
+ columns.forEach((col) => {
2334
+ columnData[col.key || col.element || ""] = {
2335
+ ...col,
2336
+ type: col.type || this.inferColumnType(data[0][col.key || col.element || ""]),
2337
+ visible: col.visible !== undefined ? col.visible : true,
2338
+ };
2339
+ });
2340
+ tableConfig.columnData = columnData;
2341
+ }
2342
+ else if (data.length === 0 && columns) {
2343
+ const columnData = {};
2344
+ columns.forEach((col) => {
2345
+ columnData[col.key || col.element || ""] = {
2346
+ ...col,
2347
+ type: col.type || "STRING",
2348
+ visible: col.visible !== undefined ? col.visible : true,
2349
+ };
2350
+ });
2351
+ tableConfig.columnData = columnData;
2352
+ }
2353
+ this.tableConfigSubject.next(tableConfig);
2354
+ this.columnsSubject.next(columns || []);
2355
+ this.dataSubject.next(data);
2356
+ }
2357
+ inferColumnType(value) {
2358
+ if (value === null || value === undefined) {
2359
+ return "STRING";
2360
+ }
2361
+ switch (typeof value) {
2362
+ case "boolean":
2363
+ return "BOOLEAN";
2364
+ case "number":
2365
+ return "NUMBER";
2366
+ case "string":
2367
+ return this.isValidDate(value) ? "DATE" : "STRING";
2368
+ default:
2369
+ return "STRING";
2370
+ }
2371
+ }
2372
+ isValidDate(value) {
2373
+ return !isNaN(Date.parse(value));
2374
+ }
2375
+ toggleColumnVisibility(columnKey) {
2376
+ const currentColumns = this.columnsSubject.value;
2377
+ const updatedColumns = currentColumns.map((col) => col.key === columnKey || col.element === columnKey ? { ...col, visible: !col.visible } : col);
2378
+ const currentConfig = this.tableConfigSubject.value;
2379
+ if (currentConfig) {
2380
+ const updatedColumnData = { ...currentConfig.columnData };
2381
+ const columnToUpdate = Object.keys(updatedColumnData).find((key) => key === columnKey);
2382
+ if (columnToUpdate) {
2383
+ updatedColumnData[columnToUpdate].visible = !updatedColumnData[columnToUpdate].visible;
2384
+ this.tableConfigSubject.next({
2385
+ ...currentConfig,
2386
+ columnData: updatedColumnData,
2387
+ });
2388
+ }
2389
+ }
2390
+ this.columnsSubject.next(updatedColumns);
2391
+ }
2392
+ getVisibleColumns() {
2393
+ return this.columnsSubject.value.filter((col) => col.visible);
2394
+ }
2395
+ setColumns(columns) {
2396
+ const currentConfig = this.tableConfigSubject.value;
2397
+ if (currentConfig) {
2398
+ const columnData = {};
2399
+ columns.forEach((col) => {
2400
+ columnData[col.key || col.element || ""] = col;
2401
+ });
2402
+ this.tableConfigSubject.next({
2403
+ ...currentConfig,
2404
+ columns: columns.map((col) => col.key || col.element || ""),
2405
+ columnData,
2406
+ });
2407
+ }
2408
+ this.columnsSubject.next(columns);
2409
+ }
2410
+ setData(data) {
2411
+ this.dataSubject.next(data);
2412
+ const currentConfig = this.tableConfigSubject.value;
2413
+ if (currentConfig) {
2414
+ this.tableConfigSubject.next({
2415
+ ...currentConfig,
2416
+ data,
2417
+ });
2418
+ }
2419
+ }
2420
+ updateTableData(data) {
2421
+ this.setData(data);
2422
+ }
2423
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TablePaginatedService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2424
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TablePaginatedService, providedIn: "root" });
2443
2425
  }
2444
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabLabelDirective, decorators: [{
2445
- type: Directive,
2426
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: TablePaginatedService, decorators: [{
2427
+ type: Injectable,
2446
2428
  args: [{
2447
- selector: '[caoTabLabel]',
2448
- standalone: true,
2429
+ providedIn: "root",
2449
2430
  }]
2450
2431
  }] });
2451
2432
 
2452
- class CaoTabPanel {
2453
- label = '';
2454
- isLucideIcon = true;
2455
- trailingIcon = null;
2456
- leadingIcon = null;
2457
- isDisabled = false;
2458
- labelTemplate;
2459
- lazyContent;
2460
- content;
2461
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
2462
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: CaoTabPanel, isStandalone: true, selector: "cao-tab-panel", inputs: { label: "label", isLucideIcon: "isLucideIcon", trailingIcon: "trailingIcon", leadingIcon: "leadingIcon", isDisabled: "isDisabled" }, queries: [{ propertyName: "labelTemplate", first: true, predicate: CaoTabLabelDirective, descendants: true, read: TemplateRef }, { propertyName: "lazyContent", first: true, predicate: CaoTabContentDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "content", first: true, predicate: ["implicitContent"], descendants: true, static: true }], ngImport: i0, template: `
2463
- <ng-template #implicitContent>
2464
- <ng-content />
2465
- </ng-template>
2466
- `, isInline: true, styles: [""] });
2433
+ function getPtBrPaginatorIntlBasePaginated() {
2434
+ const paginatorIntl = new MatPaginatorIntl();
2435
+ paginatorIntl.itemsPerPageLabel = "Itens por página:";
2436
+ paginatorIntl.nextPageLabel = "Próxima página";
2437
+ paginatorIntl.previousPageLabel = "Página anterior";
2438
+ paginatorIntl.firstPageLabel = "Primeira página";
2439
+ paginatorIntl.lastPageLabel = "Última página";
2440
+ paginatorIntl.getRangeLabel = (page, pageSize, length) => {
2441
+ if (length === 0 || pageSize === 0) {
2442
+ return `0 de ${length}`;
2443
+ }
2444
+ const startIndex = page * pageSize;
2445
+ const endIndex = Math.min(startIndex + pageSize, length);
2446
+ return `${startIndex + 1} – ${endIndex} de ${length}`;
2447
+ };
2448
+ return paginatorIntl;
2467
2449
  }
2468
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabPanel, decorators: [{
2469
- type: Component,
2470
- args: [{ selector: "cao-tab-panel", imports: [], template: `
2471
- <ng-template #implicitContent>
2472
- <ng-content />
2473
- </ng-template>
2474
- ` }]
2475
- }], propDecorators: { label: [{
2476
- type: Input
2477
- }], isLucideIcon: [{
2478
- type: Input
2479
- }], trailingIcon: [{
2480
- type: Input
2481
- }], leadingIcon: [{
2482
- type: Input
2483
- }], isDisabled: [{
2484
- type: Input
2485
- }], labelTemplate: [{
2486
- type: ContentChild,
2487
- args: [CaoTabLabelDirective, { read: TemplateRef }]
2488
- }], lazyContent: [{
2489
- type: ContentChild,
2490
- args: [CaoTabContentDirective, { read: TemplateRef }]
2491
- }], content: [{
2492
- type: ViewChild,
2493
- args: ['implicitContent', { static: true }]
2494
- }] } });
2495
-
2496
- class CaoTabGroup {
2497
- get _hostStyles() {
2498
- return {
2499
- '--caoTabLabelHeight': this.labelHeight,
2500
- '--caoTabLabelPx': this.labelPaddingX,
2501
- '--caoTabLabelGap': this.labelGap,
2502
- '--caoTabColorText': this.colorText,
2503
- '--caoTabColorActive': this.colorActive,
2504
- '--caoTabColorHoverBg': this.colorHoverBg,
2505
- '--caoTabColorDisabled': this.colorDisabled,
2506
- '--caoTabColorInkBar': this.colorInkBar,
2507
- '--caoTabColorHeaderBorder': this.colorHeaderBorder,
2508
- '--caoTabInkBarHeight': this.inkBarHeight,
2509
- '--caoTabContentPt': this.contentPaddingTop,
2510
- '--caoTabRadius': this.labelRadius,
2511
- };
2512
- }
2513
- set selectedIndex(val) {
2514
- this.selectIndex(val, false);
2450
+ class BaseTablePaginated {
2451
+ paginationSubscriptions = [];
2452
+ getColumnCssClass;
2453
+ customClass = "";
2454
+ pageSizeOptions = [5, 10, 20, 50];
2455
+ showFirstLastButtons = true;
2456
+ pageChanged = new EventEmitter();
2457
+ pageSizeChanged = new EventEmitter();
2458
+ firstPageClicked = new EventEmitter();
2459
+ lastPageClicked = new EventEmitter();
2460
+ selectionChanged = new EventEmitter();
2461
+ pageEvent = new EventEmitter();
2462
+ rowClicked = new EventEmitter();
2463
+ dataSource = new MatTableDataSource([]);
2464
+ selection = new SelectionModel(true, []);
2465
+ allColumns = [];
2466
+ displayedColumns = [];
2467
+ filterValue = "";
2468
+ configSubscription = null;
2469
+ visibleColumnsSubscription = null;
2470
+ dataSubscription = null;
2471
+ filterSubscription = null;
2472
+ tableConfig = null;
2473
+ sort;
2474
+ paginator;
2475
+ totalItems = 0;
2476
+ pageSize = 10;
2477
+ currentPage = 1;
2478
+ previousPage = 1;
2479
+ paginationService = inject(BasePaginationService);
2480
+ tableService = inject(TablePaginatedService);
2481
+ liveAnnouncer = inject(LiveAnnouncer);
2482
+ filterTableService = inject(BaseFilterTablePaginatedService);
2483
+ constructor() {
2484
+ this.initializeSortingAccessor();
2485
+ this.initializeFilterPredicate();
2515
2486
  }
2516
- get selectedIndex() {
2517
- return this.activeIndex();
2487
+ onPageChanged(page) {
2488
+ this.currentPage = page;
2489
+ this.pageChanged.emit(page);
2490
+ if (this.paginator && this.paginator.pageIndex !== page - 1) {
2491
+ this.paginator.pageIndex = page - 1;
2492
+ }
2518
2493
  }
2519
- labelHeight = '48px';
2520
- labelPaddingX = '16px';
2521
- labelGap = '6px';
2522
- colorText = '#6b7280';
2523
- colorActive = '#4f46e5';
2524
- colorHoverBg = '#f3f4f6';
2525
- colorDisabled = '#d1d5db';
2526
- colorInkBar = '#4f46e5';
2527
- colorHeaderBorder = '#e5e7eb';
2528
- inkBarHeight = '2px';
2529
- contentPaddingTop = '20px';
2530
- labelRadius = '4px';
2531
- animationDuration = '300ms';
2532
- dynamicHeight = false;
2533
- labelAlign = 'start';
2534
- iconColorActive = '';
2535
- iconColorInactive = '';
2536
- strokeWidthIcon = 1;
2537
- selectedTabChange = new EventEmitter();
2538
- focusChange = new EventEmitter();
2539
- tabs;
2540
- tabBtns;
2541
- inkBar;
2542
- activeIndex = signal(0, ...(ngDevMode ? [{ debugName: "activeIndex" }] : []));
2543
- activatedSet = new Set();
2544
- tabList = [];
2545
- subs = new Subscription();
2546
- isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
2547
- ngAfterContentInit() {
2548
- this.tabList = this.tabs.toArray();
2549
- this.activatedSet.add(this.activeIndex());
2550
- this.subs.add(this.tabs.changes.subscribe(() => {
2551
- this.tabList = this.tabs.toArray();
2552
- const safe = Math.min(this.activeIndex(), this.tabList.length - 1);
2553
- this.activeIndex.set(Math.max(0, safe));
2554
- this.scheduleInkBar();
2494
+ ngOnInit() {
2495
+ this.configSubscription = this.tableService.tableConfig$.subscribe((config) => {
2496
+ if (config) {
2497
+ this.tableConfig = config;
2498
+ this.allColumns = config.columns;
2499
+ }
2500
+ });
2501
+ this.visibleColumnsSubscription = this.tableService.visibleColumns$.subscribe((visibleColumns) => {
2502
+ this.displayedColumns = visibleColumns.filter((col) => col !== "select");
2503
+ });
2504
+ this.dataSubscription = this.tableService.data$.subscribe((data) => {
2505
+ this.dataSource.data = data;
2506
+ this.updateTotalItems();
2507
+ });
2508
+ this.filterSubscription = this.filterTableService.filter$.subscribe((filterValue) => {
2509
+ this.filterValue = filterValue;
2510
+ this.applyFilter();
2511
+ });
2512
+ this.paginationSubscriptions.push(this.paginationService.currentPage$.subscribe((page) => {
2513
+ if (this.currentPage !== page) {
2514
+ this.onPageChanged(page);
2515
+ }
2516
+ }), this.paginationService.pageSize$.subscribe((size) => {
2517
+ if (this.pageSize !== size) {
2518
+ this.onPageSizeChanged(size);
2519
+ }
2555
2520
  }));
2556
- this.scheduleInkBar();
2557
2521
  }
2558
2522
  ngOnDestroy() {
2559
- this.subs.unsubscribe();
2560
- }
2561
- selectTab(index) {
2562
- this.selectIndex(index, true);
2563
- }
2564
- get activeTab() {
2565
- return this.tabList[this.activeIndex()] ?? null;
2566
- }
2567
- isActive(index) {
2568
- return this.activeIndex() === index;
2569
- }
2570
- wasActivated(index) {
2571
- return this.activatedSet.has(index);
2523
+ this.configSubscription?.unsubscribe();
2524
+ this.visibleColumnsSubscription?.unsubscribe();
2525
+ this.dataSubscription?.unsubscribe();
2526
+ this.filterSubscription?.unsubscribe();
2527
+ this.paginationSubscriptions.forEach((sub) => sub.unsubscribe());
2572
2528
  }
2573
- onTabClick(index) {
2574
- if (this.tabList[index]?.isDisabled) {
2575
- return;
2529
+ updateTotalItems(newTotalItens) {
2530
+ this.totalItems = newTotalItens ?? this.totalItems;
2531
+ this.paginationService.setTotalItems(this.totalItems);
2532
+ const lastPage = this.pageSize > 0 ? Math.ceil(this.totalItems / this.pageSize) : 1;
2533
+ const lastValidPage = lastPage > 0 ? lastPage : 1;
2534
+ if (this.currentPage > lastValidPage) {
2535
+ this.paginationService.setPage(1);
2576
2536
  }
2577
- this.selectIndex(index, true);
2578
2537
  }
2579
- onKeydown(event, currentIndex) {
2580
- let next = currentIndex;
2581
- switch (event.key) {
2582
- case 'ArrowRight':
2583
- next = this.nextEnabled(currentIndex, 1);
2584
- break;
2585
- case 'ArrowLeft':
2586
- next = this.nextEnabled(currentIndex, -1);
2587
- break;
2588
- case 'Home':
2589
- next = this.nextEnabled(-1, 1);
2590
- break;
2591
- case 'End':
2592
- next = this.nextEnabled(this.tabList.length, -1);
2593
- break;
2594
- default: return;
2538
+ onPageSizeChanged(pageSize) {
2539
+ this.pageSize = pageSize;
2540
+ this.pageSizeChanged.emit(pageSize);
2541
+ if (this.paginator && this.paginator.pageSize !== pageSize) {
2542
+ this.paginator.pageSize = pageSize;
2595
2543
  }
2596
- event.preventDefault();
2597
- this.selectIndex(next, true);
2598
- this.focusTab(next);
2599
2544
  }
2600
- onFocus(index) {
2601
- this.focusChange.emit(index);
2545
+ getColumnHeader(column) {
2546
+ if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2547
+ return column;
2548
+ }
2549
+ return this.tableConfig.columnData[column].header || column;
2602
2550
  }
2603
- nextEnabled(from, dir) {
2604
- const tabs = this.tabList;
2605
- let idx = from + dir;
2606
- while (idx >= 0 && idx < tabs.length) {
2607
- if (!tabs[idx].isDisabled) {
2608
- return idx;
2609
- }
2610
- idx += dir;
2551
+ getColumnElement(column) {
2552
+ if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2553
+ return column;
2611
2554
  }
2612
- return from;
2555
+ return this.tableConfig.columnData[column].element || column;
2613
2556
  }
2614
- selectIndex(index, emit) {
2615
- if (!this.tabList) {
2616
- this.activeIndex.set(Math.max(0, index));
2617
- return;
2557
+ getColumnType(column) {
2558
+ if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2559
+ return "STRING";
2618
2560
  }
2619
- const clamped = Math.max(0, Math.min(index, this.tabList.length - 1));
2620
- const previous = this.activeIndex();
2621
- if (clamped === previous && emit) {
2622
- return;
2561
+ return this.tableConfig.columnData[column].type || "STRING";
2562
+ }
2563
+ announceSortChange(sortState) {
2564
+ if (sortState.direction) {
2565
+ this.liveAnnouncer.announce(`Ordenado ${sortState.direction === "asc" ? "ascendente" : "descendente"}`);
2623
2566
  }
2624
- this.activeIndex.set(clamped);
2625
- this.activatedSet.add(clamped);
2626
- if (emit) {
2627
- this.selectedTabChange.emit({
2628
- previousIndex: previous,
2629
- index: clamped,
2630
- tab: this.tabList[clamped],
2631
- });
2567
+ else {
2568
+ this.liveAnnouncer.announce("Ordenação removida");
2632
2569
  }
2633
- this.scheduleInkBar();
2634
2570
  }
2635
- focusTab(index) {
2636
- this.tabBtns?.toArray()[index]?.nativeElement?.focus();
2571
+ handlePageChange(event) {
2572
+ this.pageSize = event.pageSize;
2573
+ this.paginationService.setPageSize(event.pageSize);
2574
+ this.pageChanged.emit(event.pageIndex);
2637
2575
  }
2638
- scheduleInkBar() {
2639
- if (!this.isBrowser) {
2640
- return;
2641
- }
2642
- requestAnimationFrame(() => this.updateInkBar());
2576
+ applyFilter() {
2577
+ const normalizedFilter = this.filterValue.trim().toLowerCase();
2578
+ this.dataSource.filter = normalizedFilter;
2643
2579
  }
2644
- updateInkBar() {
2645
- const btns = this.tabBtns?.toArray();
2646
- const bar = this.inkBar?.nativeElement;
2647
- if (!btns || !bar) {
2648
- return;
2580
+ initializeSortingAccessor() {
2581
+ this.dataSource.sortingDataAccessor = (item, property) => {
2582
+ const value = item[property];
2583
+ if (typeof value === "string") {
2584
+ return value.toLowerCase();
2585
+ }
2586
+ else if (typeof value === "number") {
2587
+ return value;
2588
+ }
2589
+ else if (typeof value === "boolean") {
2590
+ return value ? 1 : 0;
2591
+ }
2592
+ else if (value instanceof Date) {
2593
+ return value.valueOf();
2594
+ }
2595
+ else if (value === null) {
2596
+ return "";
2597
+ }
2598
+ else if (value === undefined) {
2599
+ return undefined;
2600
+ }
2601
+ else if (typeof value === "object") {
2602
+ return value.toString();
2603
+ }
2604
+ return value;
2605
+ };
2606
+ }
2607
+ initializeFilterPredicate() {
2608
+ this.dataSource.filterPredicate = (data, filter) => {
2609
+ const searchTerms = filter.trim().toLowerCase();
2610
+ if (!searchTerms) {
2611
+ return true;
2612
+ }
2613
+ const dataStr = Object.keys(data).reduce((currentTerm, key) => {
2614
+ const value = data[key];
2615
+ return (currentTerm +
2616
+ (value !== null && value !== undefined ? value.toString().toLowerCase() : ""));
2617
+ }, "");
2618
+ return dataStr.indexOf(searchTerms) !== -1;
2619
+ };
2620
+ }
2621
+ onRowClick(row) {
2622
+ this.rowClicked.emit(row);
2623
+ }
2624
+ onPageEvent(event) {
2625
+ const newPage = event.pageIndex + 1;
2626
+ const isFirstPage = newPage === 1 && this.previousPage !== 1;
2627
+ const isLastPage = newPage === Math.ceil(this.totalItems / event.pageSize) && newPage !== this.previousPage;
2628
+ // Handle page size changes
2629
+ if (event.pageSize !== this.pageSize) {
2630
+ this.onPageSizeChanged(event.pageSize);
2649
2631
  }
2650
- const btn = btns[this.activeIndex()]?.nativeElement;
2651
- if (!btn) {
2652
- return;
2632
+ // Handle page changes
2633
+ if (newPage !== this.currentPage) {
2634
+ this.previousPage = this.currentPage; // Store previous page for first/last detection
2635
+ this.onPageChanged(newPage);
2636
+ // Emit specific events for first/last page navigation
2637
+ if (isFirstPage) {
2638
+ this.firstPageClicked.emit();
2639
+ this.liveAnnouncer.announce("Primeira página");
2640
+ }
2641
+ else if (isLastPage) {
2642
+ this.lastPageClicked.emit();
2643
+ this.liveAnnouncer.announce("Última página");
2644
+ }
2653
2645
  }
2654
- bar.style.width = `${btn.offsetWidth}px`;
2655
- bar.style.transform = `translateX(${btn.offsetLeft}px)`;
2656
- bar.style.transitionDuration = this.animationDuration;
2646
+ this.pageEvent.emit(event);
2657
2647
  }
2658
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
2659
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CaoTabGroup, isStandalone: true, selector: "cao-tab-group", inputs: { selectedIndex: "selectedIndex", labelHeight: "labelHeight", labelPaddingX: "labelPaddingX", labelGap: "labelGap", colorText: "colorText", colorActive: "colorActive", colorHoverBg: "colorHoverBg", colorDisabled: "colorDisabled", colorInkBar: "colorInkBar", colorHeaderBorder: "colorHeaderBorder", inkBarHeight: "inkBarHeight", contentPaddingTop: "contentPaddingTop", labelRadius: "labelRadius", animationDuration: "animationDuration", dynamicHeight: "dynamicHeight", labelAlign: "labelAlign", iconColorActive: "iconColorActive", iconColorInactive: "iconColorInactive", strokeWidthIcon: "strokeWidthIcon" }, outputs: { selectedTabChange: "selectedTabChange", focusChange: "focusChange" }, host: { properties: { "style": "this._hostStyles" }, classAttribute: "cao-tab-group" }, queries: [{ propertyName: "tabs", predicate: CaoTabPanel }], viewQueries: [{ propertyName: "inkBar", first: true, predicate: ["inkBar"], descendants: true }, { propertyName: "tabBtns", predicate: ["tabBtn"], descendants: true }], ngImport: i0, template: "<div\n #header\n [class]=\"'cao-tab-header cao-tab-header--align-' + labelAlign\"\n>\n <div class=\"cao-tab-label-list\" role=\"tablist\">\n @for (tab of tabList; track $index; let i = $index) {\n <button\n #tabBtn\n role=\"tab\"\n type=\"button\"\n class=\"cao-tab-label\"\n [class.cao-tab-label--active]=\"isActive(i)\"\n [class.cao-tab-label--disabled]=\"tab.isDisabled\"\n [attr.aria-selected]=\"isActive(i)\"\n [attr.aria-disabled]=\"tab.isDisabled || null\"\n [attr.tabindex]=\"isActive(i) ? 0 : -1\"\n [attr.id]=\"'cao-tab-label-' + i\"\n [attr.aria-controls]=\"'cao-tab-content-' + i\"\n (click)=\"onTabClick(i)\"\n (keydown)=\"onKeydown($event, i)\"\n (focus)=\"onFocus(i)\"\n >\n @if (tab.leadingIcon) {\n <span class=\"leading-icon\">\n @if (tab.isLucideIcon) {\n <svg [lucideIcon]=\"tab.leadingIcon\" [style.color]=\"isActive(i) ? iconColorActive : iconColorInactive\" [strokeWidth]=\"strokeWidthIcon\"></svg>\n } @else {\n <img alt=\"icon\" [src]=\"tab.leadingIcon\" />\n }\n </span>\n }\n\n @if (tab.labelTemplate) {\n <ng-container [ngTemplateOutlet]=\"tab.labelTemplate\" />\n } @else {\n <span class=\"cao-tab-labeltext\">{{ tab.label }}</span>\n }\n\n @if (tab.trailingIcon) {\n <span class=\"trailing-icon\">\n @if (tab.isLucideIcon) {\n <svg [lucideIcon]=\"tab.trailingIcon\" [style.color]=\"isActive(i) ? iconColorActive : iconColorInactive\" [strokeWidth]=\"strokeWidthIcon\"></svg>\n } @else {\n <img alt=\"icon\" [src]=\"tab.trailingIcon\" />\n }\n </span>\n }\n </button>\n }\n </div>\n\n <!-- Ink bar animado -->\n <div class=\"cao-tab-ink-bar-track\">\n <div #inkBar class=\"cao-tab-ink-bar\"></div>\n </div>\n</div>\n\n<!-- \u2550\u2550\u2550 Tab Bodies \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<div\n class=\"cao-tab-body-wrapper\"\n [class.cao-tab-body-wrapper--dynamic]=\"dynamicHeight\"\n>\n @for (tab of tabList; track $index; let i = $index) {\n <div\n role=\"tabpanel\"\n class=\"cao-tab-body\"\n [class.cao-tab-body--active]=\"isActive(i)\"\n [attr.id]=\"'cao-tab-content-' + i\"\n [attr.aria-labelledby]=\"'cao-tab-label-' + i\"\n [attr.aria-hidden]=\"!isActive(i)\"\n [style.--cao-tab-anim-duration]=\"animationDuration\"\n >\n <div class=\"cao-tab-bodycontent\">\n @if (tab.lazyContent) {\n @if (isActive(i) || wasActivated(i)) {\n <ng-container [ngTemplateOutlet]=\"tab.lazyContent\" />\n }\n } @else {\n <ng-container [ngTemplateOutlet]=\"tab.content\" />\n }\n </div>\n </div>\n }\n</div>", styles: [":host{--cao-tab-font-family: inherit;--cao-tab-font-size: .875rem;--cao-tab-font-weight: 500;--caoTabLabelHeight: 48px;--caoTabLabelPx: 16px;--caoTabLabelGap: 6px;--caoTabColorText: #6b7280;--caoTabColorActive: #4f46e5;--caoTabColorHoverBg: #f3f4f6;--caoTabColorDisabled: #d1d5db;--caoTabColorInkBar: #4f46e5;--caoTabColorHeaderBorder: #e5e7eb;--caoTabInkBarHeight: 2px;--caoTabContentPt: 20px;--caoTabRadius: 4px;display:flex;flex-direction:column;width:100%}.cao-tab-header{position:relative;border-bottom:1px solid var(--cao-tab-color-header-border);overflow-x:auto;scrollbar-width:none}.cao-tab-header::-webkit-scrollbar{display:none}.cao-tab-label-list{display:flex;align-items:center;min-width:max-content}.cao-tab-header--align-center .cao-tab-label-list{justify-content:center}.cao-tab-header--align-end .cao-tab-label-list{justify-content:flex-end}.cao-tab-header--align-start .cao-tab-label-list{justify-content:flex-start}.cao-tab-label{display:inline-flex;align-items:center;gap:var(--cao-tab-label-gap);height:var(--cao-tab-label-height);padding:0 var(--cao-tab-label-px);font-family:var(--cao-tab-font-family);font-size:var(--cao-tab-font-size);font-weight:var(--cao-tab-font-weight);color:var(--cao-tab-color-text);white-space:nowrap;background:transparent;border:none;border-radius:var(--cao-tab-radius) var(--cao-tab-radius) 0 0;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .18s ease,background-color .18s ease;outline:none}.cao-tab-label:focus-visible{outline:2px solid var(--cao-tab-color-active);outline-offset:-2px}.cao-tab-label:hover:not(.cao-tab-label--disabled){background-color:var(--cao-tab-color-hover-bg);color:var(--cao-tab-color-active)}.cao-tab-label--active{color:var(--cao-tab-color-active)}.cao-tab-label--disabled{color:var(--cao-tab-color-disabled);cursor:not-allowed;pointer-events:none}.cao-tab-label__icon{flex-shrink:0;color:inherit;transition:color .18s ease}.cao-tab-ink-bar-track{position:absolute;bottom:0;left:0;right:0;height:var(--cao-tab-ink-bar-height);pointer-events:none}.cao-tab-ink-bar{position:absolute;bottom:0;left:0;height:100%;background-color:var(--cao-tab-color-ink-bar);border-radius:2px 2px 0 0;transition-property:transform,width;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}.cao-tab-body-wrapper{position:relative;overflow:hidden}.cao-tab-body-wrapper--dynamic{height:auto}.cao-tab-body{position:absolute;top:0;left:0;width:100%;visibility:hidden;opacity:0;pointer-events:none;transform:translate(24px);transition:opacity var(--cao-tab-anim-duration, .3s) cubic-bezier(.4,0,.2,1),transform var(--cao-tab-anim-duration, .3s) cubic-bezier(.4,0,.2,1)}.cao-tab-body--active{position:relative;visibility:visible;opacity:1;pointer-events:auto;transform:translate(0)}.cao-tab-body__content{padding-top:var(--cao-tab-content-pt)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LucideDynamicIcon, selector: "svg[lucideIcon]", inputs: ["lucideIcon"] }] });
2648
+ getColumnButtons(column) {
2649
+ if (!this.tableConfig || !this.tableConfig.columnData || !this.tableConfig.columnData[column]) {
2650
+ return [];
2651
+ }
2652
+ return this.tableConfig.columnData[column].buttons || [];
2653
+ }
2654
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTablePaginated, deps: [], target: i0.ɵɵFactoryTarget.Component });
2655
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: BaseTablePaginated, isStandalone: true, selector: "cao-table-paginated", inputs: { getColumnCssClass: "getColumnCssClass", customClass: "customClass", pageSizeOptions: "pageSizeOptions", showFirstLastButtons: "showFirstLastButtons" }, outputs: { pageChanged: "pageChanged", pageSizeChanged: "pageSizeChanged", firstPageClicked: "firstPageClicked", lastPageClicked: "lastPageClicked", selectionChanged: "selectionChanged", pageEvent: "pageEvent", rowClicked: "rowClicked" }, providers: [{ provide: MatPaginatorIntl, useValue: getPtBrPaginatorIntlBasePaginated() }], viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }], ngImport: i0, template: "<div class=\"table-container\" [ngClass]=\"customClass\">\n @if (tableConfig) {\n <table mat-table matSort [dataSource]=\"dataSource\" (matSortChange)=\"announceSortChange($event)\">\n @for (column of displayedColumns; track column) {\n <ng-container [matColumnDef]=\"column\">\n <th *matHeaderCellDef mat-header-cell mat-sort-header class=\"table-header\">\n {{ getColumnHeader(column) }}\n </th>\n <td *matCellDef=\"let element\" mat-cell class=\"table-cell\">\n @switch (getColumnType(column)) { @case ('STRING') { @if (getColumnCssClass &&\n getColumnCssClass(column, element[getColumnElement(column)])) {\n <span [class]=\"getColumnCssClass(column, element[getColumnElement(column)])\">\n {{ element[getColumnElement(column)] }}\n </span>\n } @else {\n <span>{{ element[getColumnElement(column)] }}</span>\n } } @case ('BOOLEAN') {\n <mat-checkbox disabled [checked]=\"element[getColumnElement(column)]\" />\n } @case ('DATE') {\n <span>{{ element[getColumnElement(column)] | date:'mediumDate' }}</span>\n } @case ('NUMBER') {\n <span>{{ element[getColumnElement(column)] | number:'1.2-2' }}</span>\n } @case ('SINGLE_BUTTON') {\n <div>\n @for (btn of getColumnButtons(column); track btn) {\n <button type=\"button\" mat-icon-button [matTooltip]=\"btn.tooltip\" (click)=\"btn.onClick(element)\">\n <mat-icon>{{ btn.icon }}</mat-icon>\n </button>\n }\n </div>\n } }\n </td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"footer\">\n <td\n *matFooterCellDef\n mat-footer-cell\n class=\"table-cell\"\n [attr.colspan]=\"displayedColumns.length\">\n Total de Registros: {{ totalItems }}\n </td>\n </ng-container>\n\n <tr *matHeaderRowDef=\"displayedColumns\" mat-header-row></tr>\n <tr *matRowDef=\"let row; columns: displayedColumns;\" mat-row (click)=\"onRowClick(row)\"></tr>\n <tr *matFooterRowDef=\"['footer']\" mat-footer-row class=\"mat-row-footer\"></tr>\n </table>\n @if(totalItems > 0){\n\n <mat-paginator\n #paginator\n aria-label=\"Select page\"\n [length]=\"totalItems\"\n [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\"\n [pageIndex]=\"currentPage - 1\"\n [hidePageSize]=\"false\"\n [showFirstLastButtons]=\"showFirstLastButtons\"\n (page)=\"onPageEvent($event)\" />\n } @else {\n <div class=\"no-data-container\">\n <h2>{{ tableConfig?.result?.noData ?? 'N\u00E3o h\u00E1 dados dispon\u00EDveis' }}</h2>\n <p>{{ tableConfig?.result?.defaultMessage ?? 'Adicione alguns dados' }}</p>\n </div>\n } }\n</div>\n", styles: [".table-container{border-radius:8px;box-shadow:0 4px 6px #0000001a;overflow:hidden}.table-container .table-controls{display:flex;align-items:center;padding:20px;justify-content:center}.table-container .table-controls .filter-field{display:flex;align-items:center;justify-content:space-between;padding:10px;flex-direction:row;border:none;border-radius:10px;background-color:var(--input-disabled-bg);width:50%;height:55px;margin:0 auto}.table-container .table-controls .filter-field input:focus{outline:none!important;box-shadow:none!important;border-color:transparent!important}.table-container .table-controls .filter-field .input-filter{width:100%;box-sizing:border-box;background-color:transparent;border:none;transition:none;text-align:center}.table-container .table-controls .filter-field i{color:var(--icon-collor);margin-left:8px}.table-container .mat-mdc-table{width:100%}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell{border-right:1px solid var(--data-bg);font-weight:600;color:var(--message-color);border-bottom:1px solid var(--input-background);text-transform:uppercase;font-size:.875rem;text-align:center;padding:12px;vertical-align:middle}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell .mat-sort-header-container{justify-content:center}.table-container .mat-mdc-table .mat-mdc-row{transition:background-color .2s ease;background-color:transparent}.table-container .mat-mdc-table .mat-mdc-row:nth-child(2n){background-color:transparent}.table-container .mat-mdc-table .mat-mdc-row:nth-child(odd){background-color:var(--input-background)}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--border-table-ligth);color:var(--gray-dark);border-bottom:1px solid var(--input-background);text-align:center;padding:12px;vertical-align:middle}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row:hover{background-color:#0000000a}.table-container .mat-mdc-table .mat-mdc-row.selected{background-color:#3f51b51a}.table-container .mat-mdc-table .mat-mdc-checkbox{margin:0 auto;display:block}.table-container .mat-mdc-table .mat-mdc-checkbox .mdc-checkbox{--mdc-checkbox-unselected-icon-color: var(--gray-dark);--mdc-checkbox-selected-icon-color: var(--info)}.table-container .mat-mdc-table .mat-mdc-footer-row{background-color:var(--table-background);font-weight:600;color:var(--text-color)}.table-container .mat-mdc-table .mat-mdc-footer-row .mat-mdc-footer-cell{padding:12px;text-align:center}.table-container .no-data-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;text-align:center;background-color:var(--table-background)}.table-container .no-data-container h2{color:var(--input-disabled-bg);margin-bottom:12px}.table-container .no-data-container p{color:var(--input-disabled-bg)}@media(width<=768px){.table-container .table-controls{flex-direction:column;align-items:center}.table-container .table-controls .filter-field{width:80%;margin-right:0;margin-bottom:12px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i2$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: i4$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i1$2.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "directive", type: i7.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i7.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i8.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i8.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i8.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i8.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i8.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i8.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i8.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i8.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i8.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i8.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i8.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i8.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i8.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i8.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }, { kind: "pipe", type: i1.DatePipe, name: "date" }], encapsulation: i0.ViewEncapsulation.None });
2660
2656
  }
2661
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoTabGroup, decorators: [{
2657
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseTablePaginated, decorators: [{
2662
2658
  type: Component,
2663
- args: [{ selector: 'cao-tab-group', standalone: true, imports: [NgTemplateOutlet, LucideDynamicIcon], host: { class: 'cao-tab-group' }, template: "<div\n #header\n [class]=\"'cao-tab-header cao-tab-header--align-' + labelAlign\"\n>\n <div class=\"cao-tab-label-list\" role=\"tablist\">\n @for (tab of tabList; track $index; let i = $index) {\n <button\n #tabBtn\n role=\"tab\"\n type=\"button\"\n class=\"cao-tab-label\"\n [class.cao-tab-label--active]=\"isActive(i)\"\n [class.cao-tab-label--disabled]=\"tab.isDisabled\"\n [attr.aria-selected]=\"isActive(i)\"\n [attr.aria-disabled]=\"tab.isDisabled || null\"\n [attr.tabindex]=\"isActive(i) ? 0 : -1\"\n [attr.id]=\"'cao-tab-label-' + i\"\n [attr.aria-controls]=\"'cao-tab-content-' + i\"\n (click)=\"onTabClick(i)\"\n (keydown)=\"onKeydown($event, i)\"\n (focus)=\"onFocus(i)\"\n >\n @if (tab.leadingIcon) {\n <span class=\"leading-icon\">\n @if (tab.isLucideIcon) {\n <svg [lucideIcon]=\"tab.leadingIcon\" [style.color]=\"isActive(i) ? iconColorActive : iconColorInactive\" [strokeWidth]=\"strokeWidthIcon\"></svg>\n } @else {\n <img alt=\"icon\" [src]=\"tab.leadingIcon\" />\n }\n </span>\n }\n\n @if (tab.labelTemplate) {\n <ng-container [ngTemplateOutlet]=\"tab.labelTemplate\" />\n } @else {\n <span class=\"cao-tab-labeltext\">{{ tab.label }}</span>\n }\n\n @if (tab.trailingIcon) {\n <span class=\"trailing-icon\">\n @if (tab.isLucideIcon) {\n <svg [lucideIcon]=\"tab.trailingIcon\" [style.color]=\"isActive(i) ? iconColorActive : iconColorInactive\" [strokeWidth]=\"strokeWidthIcon\"></svg>\n } @else {\n <img alt=\"icon\" [src]=\"tab.trailingIcon\" />\n }\n </span>\n }\n </button>\n }\n </div>\n\n <!-- Ink bar animado -->\n <div class=\"cao-tab-ink-bar-track\">\n <div #inkBar class=\"cao-tab-ink-bar\"></div>\n </div>\n</div>\n\n<!-- \u2550\u2550\u2550 Tab Bodies \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<div\n class=\"cao-tab-body-wrapper\"\n [class.cao-tab-body-wrapper--dynamic]=\"dynamicHeight\"\n>\n @for (tab of tabList; track $index; let i = $index) {\n <div\n role=\"tabpanel\"\n class=\"cao-tab-body\"\n [class.cao-tab-body--active]=\"isActive(i)\"\n [attr.id]=\"'cao-tab-content-' + i\"\n [attr.aria-labelledby]=\"'cao-tab-label-' + i\"\n [attr.aria-hidden]=\"!isActive(i)\"\n [style.--cao-tab-anim-duration]=\"animationDuration\"\n >\n <div class=\"cao-tab-bodycontent\">\n @if (tab.lazyContent) {\n @if (isActive(i) || wasActivated(i)) {\n <ng-container [ngTemplateOutlet]=\"tab.lazyContent\" />\n }\n } @else {\n <ng-container [ngTemplateOutlet]=\"tab.content\" />\n }\n </div>\n </div>\n }\n</div>", styles: [":host{--cao-tab-font-family: inherit;--cao-tab-font-size: .875rem;--cao-tab-font-weight: 500;--caoTabLabelHeight: 48px;--caoTabLabelPx: 16px;--caoTabLabelGap: 6px;--caoTabColorText: #6b7280;--caoTabColorActive: #4f46e5;--caoTabColorHoverBg: #f3f4f6;--caoTabColorDisabled: #d1d5db;--caoTabColorInkBar: #4f46e5;--caoTabColorHeaderBorder: #e5e7eb;--caoTabInkBarHeight: 2px;--caoTabContentPt: 20px;--caoTabRadius: 4px;display:flex;flex-direction:column;width:100%}.cao-tab-header{position:relative;border-bottom:1px solid var(--cao-tab-color-header-border);overflow-x:auto;scrollbar-width:none}.cao-tab-header::-webkit-scrollbar{display:none}.cao-tab-label-list{display:flex;align-items:center;min-width:max-content}.cao-tab-header--align-center .cao-tab-label-list{justify-content:center}.cao-tab-header--align-end .cao-tab-label-list{justify-content:flex-end}.cao-tab-header--align-start .cao-tab-label-list{justify-content:flex-start}.cao-tab-label{display:inline-flex;align-items:center;gap:var(--cao-tab-label-gap);height:var(--cao-tab-label-height);padding:0 var(--cao-tab-label-px);font-family:var(--cao-tab-font-family);font-size:var(--cao-tab-font-size);font-weight:var(--cao-tab-font-weight);color:var(--cao-tab-color-text);white-space:nowrap;background:transparent;border:none;border-radius:var(--cao-tab-radius) var(--cao-tab-radius) 0 0;cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .18s ease,background-color .18s ease;outline:none}.cao-tab-label:focus-visible{outline:2px solid var(--cao-tab-color-active);outline-offset:-2px}.cao-tab-label:hover:not(.cao-tab-label--disabled){background-color:var(--cao-tab-color-hover-bg);color:var(--cao-tab-color-active)}.cao-tab-label--active{color:var(--cao-tab-color-active)}.cao-tab-label--disabled{color:var(--cao-tab-color-disabled);cursor:not-allowed;pointer-events:none}.cao-tab-label__icon{flex-shrink:0;color:inherit;transition:color .18s ease}.cao-tab-ink-bar-track{position:absolute;bottom:0;left:0;right:0;height:var(--cao-tab-ink-bar-height);pointer-events:none}.cao-tab-ink-bar{position:absolute;bottom:0;left:0;height:100%;background-color:var(--cao-tab-color-ink-bar);border-radius:2px 2px 0 0;transition-property:transform,width;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}.cao-tab-body-wrapper{position:relative;overflow:hidden}.cao-tab-body-wrapper--dynamic{height:auto}.cao-tab-body{position:absolute;top:0;left:0;width:100%;visibility:hidden;opacity:0;pointer-events:none;transform:translate(24px);transition:opacity var(--cao-tab-anim-duration, .3s) cubic-bezier(.4,0,.2,1),transform var(--cao-tab-anim-duration, .3s) cubic-bezier(.4,0,.2,1)}.cao-tab-body--active{position:relative;visibility:visible;opacity:1;pointer-events:auto;transform:translate(0)}.cao-tab-body__content{padding-top:var(--cao-tab-content-pt)}\n"] }]
2664
- }], propDecorators: { _hostStyles: [{
2665
- type: HostBinding,
2666
- args: ['style']
2667
- }], selectedIndex: [{
2668
- type: Input
2669
- }], labelHeight: [{
2670
- type: Input
2671
- }], labelPaddingX: [{
2672
- type: Input
2673
- }], labelGap: [{
2674
- type: Input
2675
- }], colorText: [{
2676
- type: Input
2677
- }], colorActive: [{
2678
- type: Input
2679
- }], colorHoverBg: [{
2680
- type: Input
2681
- }], colorDisabled: [{
2682
- type: Input
2683
- }], colorInkBar: [{
2684
- type: Input
2685
- }], colorHeaderBorder: [{
2686
- type: Input
2687
- }], inkBarHeight: [{
2688
- type: Input
2689
- }], contentPaddingTop: [{
2690
- type: Input
2691
- }], labelRadius: [{
2692
- type: Input
2693
- }], animationDuration: [{
2694
- type: Input
2695
- }], dynamicHeight: [{
2696
- type: Input
2697
- }], labelAlign: [{
2659
+ args: [{ selector: "cao-table-paginated", encapsulation: ViewEncapsulation.None, imports: [CommonModule, MaterialModule], providers: [{ provide: MatPaginatorIntl, useValue: getPtBrPaginatorIntlBasePaginated() }], template: "<div class=\"table-container\" [ngClass]=\"customClass\">\n @if (tableConfig) {\n <table mat-table matSort [dataSource]=\"dataSource\" (matSortChange)=\"announceSortChange($event)\">\n @for (column of displayedColumns; track column) {\n <ng-container [matColumnDef]=\"column\">\n <th *matHeaderCellDef mat-header-cell mat-sort-header class=\"table-header\">\n {{ getColumnHeader(column) }}\n </th>\n <td *matCellDef=\"let element\" mat-cell class=\"table-cell\">\n @switch (getColumnType(column)) { @case ('STRING') { @if (getColumnCssClass &&\n getColumnCssClass(column, element[getColumnElement(column)])) {\n <span [class]=\"getColumnCssClass(column, element[getColumnElement(column)])\">\n {{ element[getColumnElement(column)] }}\n </span>\n } @else {\n <span>{{ element[getColumnElement(column)] }}</span>\n } } @case ('BOOLEAN') {\n <mat-checkbox disabled [checked]=\"element[getColumnElement(column)]\" />\n } @case ('DATE') {\n <span>{{ element[getColumnElement(column)] | date:'mediumDate' }}</span>\n } @case ('NUMBER') {\n <span>{{ element[getColumnElement(column)] | number:'1.2-2' }}</span>\n } @case ('SINGLE_BUTTON') {\n <div>\n @for (btn of getColumnButtons(column); track btn) {\n <button type=\"button\" mat-icon-button [matTooltip]=\"btn.tooltip\" (click)=\"btn.onClick(element)\">\n <mat-icon>{{ btn.icon }}</mat-icon>\n </button>\n }\n </div>\n } }\n </td>\n </ng-container>\n }\n\n <ng-container matColumnDef=\"footer\">\n <td\n *matFooterCellDef\n mat-footer-cell\n class=\"table-cell\"\n [attr.colspan]=\"displayedColumns.length\">\n Total de Registros: {{ totalItems }}\n </td>\n </ng-container>\n\n <tr *matHeaderRowDef=\"displayedColumns\" mat-header-row></tr>\n <tr *matRowDef=\"let row; columns: displayedColumns;\" mat-row (click)=\"onRowClick(row)\"></tr>\n <tr *matFooterRowDef=\"['footer']\" mat-footer-row class=\"mat-row-footer\"></tr>\n </table>\n @if(totalItems > 0){\n\n <mat-paginator\n #paginator\n aria-label=\"Select page\"\n [length]=\"totalItems\"\n [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\"\n [pageIndex]=\"currentPage - 1\"\n [hidePageSize]=\"false\"\n [showFirstLastButtons]=\"showFirstLastButtons\"\n (page)=\"onPageEvent($event)\" />\n } @else {\n <div class=\"no-data-container\">\n <h2>{{ tableConfig?.result?.noData ?? 'N\u00E3o h\u00E1 dados dispon\u00EDveis' }}</h2>\n <p>{{ tableConfig?.result?.defaultMessage ?? 'Adicione alguns dados' }}</p>\n </div>\n } }\n</div>\n", styles: [".table-container{border-radius:8px;box-shadow:0 4px 6px #0000001a;overflow:hidden}.table-container .table-controls{display:flex;align-items:center;padding:20px;justify-content:center}.table-container .table-controls .filter-field{display:flex;align-items:center;justify-content:space-between;padding:10px;flex-direction:row;border:none;border-radius:10px;background-color:var(--input-disabled-bg);width:50%;height:55px;margin:0 auto}.table-container .table-controls .filter-field input:focus{outline:none!important;box-shadow:none!important;border-color:transparent!important}.table-container .table-controls .filter-field .input-filter{width:100%;box-sizing:border-box;background-color:transparent;border:none;transition:none;text-align:center}.table-container .table-controls .filter-field i{color:var(--icon-collor);margin-left:8px}.table-container .mat-mdc-table{width:100%}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell{border-right:1px solid var(--data-bg);font-weight:600;color:var(--message-color);border-bottom:1px solid var(--input-background);text-transform:uppercase;font-size:.875rem;text-align:center;padding:12px;vertical-align:middle}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-header-row .mat-mdc-header-cell .mat-sort-header-container{justify-content:center}.table-container .mat-mdc-table .mat-mdc-row{transition:background-color .2s ease;background-color:transparent}.table-container .mat-mdc-table .mat-mdc-row:nth-child(2n){background-color:transparent}.table-container .mat-mdc-table .mat-mdc-row:nth-child(odd){background-color:var(--input-background)}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell{border-right:1px solid var(--border-table-ligth);color:var(--gray-dark);border-bottom:1px solid var(--input-background);text-align:center;padding:12px;vertical-align:middle}.table-container .mat-mdc-table .mat-mdc-row .mat-mdc-cell:last-child{border-right:none}.table-container .mat-mdc-table .mat-mdc-row:hover{background-color:#0000000a}.table-container .mat-mdc-table .mat-mdc-row.selected{background-color:#3f51b51a}.table-container .mat-mdc-table .mat-mdc-checkbox{margin:0 auto;display:block}.table-container .mat-mdc-table .mat-mdc-checkbox .mdc-checkbox{--mdc-checkbox-unselected-icon-color: var(--gray-dark);--mdc-checkbox-selected-icon-color: var(--info)}.table-container .mat-mdc-table .mat-mdc-footer-row{background-color:var(--table-background);font-weight:600;color:var(--text-color)}.table-container .mat-mdc-table .mat-mdc-footer-row .mat-mdc-footer-cell{padding:12px;text-align:center}.table-container .no-data-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px;text-align:center;background-color:var(--table-background)}.table-container .no-data-container h2{color:var(--input-disabled-bg);margin-bottom:12px}.table-container .no-data-container p{color:var(--input-disabled-bg)}@media(width<=768px){.table-container .table-controls{flex-direction:column;align-items:center}.table-container .table-controls .filter-field{width:80%;margin-right:0;margin-bottom:12px}}\n"] }]
2660
+ }], ctorParameters: () => [], propDecorators: { getColumnCssClass: [{
2698
2661
  type: Input
2699
- }], iconColorActive: [{
2662
+ }], customClass: [{
2700
2663
  type: Input
2701
- }], iconColorInactive: [{
2664
+ }], pageSizeOptions: [{
2702
2665
  type: Input
2703
- }], strokeWidthIcon: [{
2666
+ }], showFirstLastButtons: [{
2704
2667
  type: Input
2705
- }], selectedTabChange: [{
2668
+ }], pageChanged: [{
2706
2669
  type: Output
2707
- }], focusChange: [{
2670
+ }], pageSizeChanged: [{
2708
2671
  type: Output
2709
- }], tabs: [{
2710
- type: ContentChildren,
2711
- args: [CaoTabPanel]
2712
- }], tabBtns: [{
2713
- type: ViewChildren,
2714
- args: ['tabBtn']
2715
- }], inkBar: [{
2672
+ }], firstPageClicked: [{
2673
+ type: Output
2674
+ }], lastPageClicked: [{
2675
+ type: Output
2676
+ }], selectionChanged: [{
2677
+ type: Output
2678
+ }], pageEvent: [{
2679
+ type: Output
2680
+ }], rowClicked: [{
2681
+ type: Output
2682
+ }], sort: [{
2716
2683
  type: ViewChild,
2717
- args: ['inkBar']
2684
+ args: [MatSort]
2685
+ }], paginator: [{
2686
+ type: ViewChild,
2687
+ args: [MatPaginator]
2718
2688
  }] } });
2719
2689
 
2720
- /*
2721
- * Public API Surface of ngx-opalbytes-components
2722
- */
2690
+ class BaseAlert {
2691
+ data;
2692
+ iconPath;
2693
+ titleClass;
2694
+ iconPaths = {
2695
+ success: "https://placehold.co/600x400",
2696
+ error: "https://placehold.co/600x400",
2697
+ info: "https://placehold.co/600x400",
2698
+ warning: "https://placehold.co/600x400",
2699
+ };
2700
+ ngOnInit() {
2701
+ this.iconPath = this.iconPaths[this.data.type];
2702
+ this.titleClass = `title-${this.data.type}`;
2703
+ }
2704
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseAlert, deps: [], target: i0.ɵɵFactoryTarget.Component });
2705
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: BaseAlert, isStandalone: true, selector: "cao-alert", ngImport: i0, template: "<div class=\"dialog-container\">\n <div class=\"dialog-content\">\n <img alt=\"Logo\" class=\"logo\" [ngSrc]=\"data.alertIcon ?? ''\" [fill]=\"true\" />\n <div class=\"alert-wrapper\">\n <div class=\"text-content\">\n @if (data.title) {\n <div class=\"title\" [ngClass]=\"titleClass\">{{ data.title }}</div>\n } @if (data.title && data.message) {\n <div class=\"message-spacer\"></div>\n } @if (data.message) {\n <div class=\"message\">{{ data.message }}</div>\n }\n </div>\n <div class=\"icon-container\">\n <img alt=\"Alert Icon\" class=\"alert-icon\" [ngSrc]=\"iconPath\" [fill]=\"true\" />\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{position:fixed;top:10%;left:55%;transform:translate(-50%);z-index:1000;display:block;animation:slide-in .3s ease-out}@keyframes slide-in{0%{opacity:0;transform:translate(-50%,-20px)}to{opacity:1;transform:translate(-50%)}}.dialog-container{width:600px;border-radius:30px;overflow:hidden;box-shadow:0 4px 6px #0000001a;background-color:var(--white)}.dialog-content{padding:20px 30px;box-sizing:border-box}.logo{width:150px;height:24px;margin-bottom:15px}.alert-wrapper{display:flex;align-items:center;justify-content:space-between}.text-content{flex-grow:1;margin:20px;padding-right:20px}.title{font-family:Lato,sans-serif;font-weight:700;font-size:24px;color:var(--primary);margin-bottom:5px}.title.success{color:var(--primary)}.title.error{color:var(--error-color)}.title.warning{color:var(--support-orange)}.title.info,.title.title-success{color:var(--primary)}.title.title-error{color:var(--error)}.title.title-warning{color:var(--support-orange)}.title.title-info{color:var(--primary)}.message-spacer{height:16px}.message{font-family:Lato,sans-serif;font-weight:400;font-size:26px;line-height:100%;color:var(--message-color)}.icon-container{width:150px;height:150px;flex-shrink:0}.alert-icon{width:100%;height:100%;object-fit:contain}@media(max-width:768px){:host{left:55%;max-width:95%}.dialog-container{max-width:90%;width:400px}.alert-wrapper{flex-direction:column;text-align:center}.text-content{padding-right:0;margin-bottom:10px}.icon-container{width:100px;height:100px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "decoding", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2706
+ }
2707
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseAlert, decorators: [{
2708
+ type: Component,
2709
+ args: [{ selector: 'cao-alert', imports: [CommonModule, NgOptimizedImage], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"dialog-container\">\n <div class=\"dialog-content\">\n <img alt=\"Logo\" class=\"logo\" [ngSrc]=\"data.alertIcon ?? ''\" [fill]=\"true\" />\n <div class=\"alert-wrapper\">\n <div class=\"text-content\">\n @if (data.title) {\n <div class=\"title\" [ngClass]=\"titleClass\">{{ data.title }}</div>\n } @if (data.title && data.message) {\n <div class=\"message-spacer\"></div>\n } @if (data.message) {\n <div class=\"message\">{{ data.message }}</div>\n }\n </div>\n <div class=\"icon-container\">\n <img alt=\"Alert Icon\" class=\"alert-icon\" [ngSrc]=\"iconPath\" [fill]=\"true\" />\n </div>\n </div>\n </div>\n</div>\n", styles: [":host{position:fixed;top:10%;left:55%;transform:translate(-50%);z-index:1000;display:block;animation:slide-in .3s ease-out}@keyframes slide-in{0%{opacity:0;transform:translate(-50%,-20px)}to{opacity:1;transform:translate(-50%)}}.dialog-container{width:600px;border-radius:30px;overflow:hidden;box-shadow:0 4px 6px #0000001a;background-color:var(--white)}.dialog-content{padding:20px 30px;box-sizing:border-box}.logo{width:150px;height:24px;margin-bottom:15px}.alert-wrapper{display:flex;align-items:center;justify-content:space-between}.text-content{flex-grow:1;margin:20px;padding-right:20px}.title{font-family:Lato,sans-serif;font-weight:700;font-size:24px;color:var(--primary);margin-bottom:5px}.title.success{color:var(--primary)}.title.error{color:var(--error-color)}.title.warning{color:var(--support-orange)}.title.info,.title.title-success{color:var(--primary)}.title.title-error{color:var(--error)}.title.title-warning{color:var(--support-orange)}.title.title-info{color:var(--primary)}.message-spacer{height:16px}.message{font-family:Lato,sans-serif;font-weight:400;font-size:26px;line-height:100%;color:var(--message-color)}.icon-container{width:150px;height:150px;flex-shrink:0}.alert-icon{width:100%;height:100%;object-fit:contain}@media(max-width:768px){:host{left:55%;max-width:95%}.dialog-container{max-width:90%;width:400px}.alert-wrapper{flex-direction:column;text-align:center}.text-content{padding-right:0;margin-bottom:10px}.icon-container{width:100px;height:100px}}\n"] }]
2710
+ }] });
2711
+
2712
+ class BaseAlertService {
2713
+ overlay;
2714
+ constructor(overlay) {
2715
+ this.overlay = overlay;
2716
+ }
2717
+ defaultTime = 3000;
2718
+ show(config) {
2719
+ const overlayRef = this.overlay.create({
2720
+ hasBackdrop: false,
2721
+ positionStrategy: this.overlay.position().global().centerHorizontally().top("10%"),
2722
+ scrollStrategy: this.overlay.scrollStrategies.block(),
2723
+ });
2724
+ const alertPortal = new ComponentPortal(this.generateComponentPortal());
2725
+ const componentRef = overlayRef.attach(alertPortal);
2726
+ componentRef.instance.data = config;
2727
+ setTimeout(() => {
2728
+ overlayRef.dispose();
2729
+ }, this.defaultTime);
2730
+ }
2731
+ generateComponentPortal() {
2732
+ return BaseAlert;
2733
+ }
2734
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseAlertService, deps: [{ token: i1$4.Overlay }], target: i0.ɵɵFactoryTarget.Injectable });
2735
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseAlertService, providedIn: "root" });
2736
+ }
2737
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BaseAlertService, decorators: [{
2738
+ type: Injectable,
2739
+ args: [{
2740
+ providedIn: "root",
2741
+ }]
2742
+ }], ctorParameters: () => [{ type: i1$4.Overlay }] });
2723
2743
 
2724
2744
  /**
2725
2745
  * Generated bundle index. Do not edit.
2726
2746
  */
2727
2747
 
2728
- export { BaseAlert, BaseAlertService, BaseDialog, BaseDialogService, BaseFilterTablePaginatedService, BaseFilterTableService, BaseModal, BaseModalService, BasePaginationService, BaseTable, BaseTablePaginated, BaseTableService, BaseTimeRange, CaoAutocompleteComponent, CaoBaseButtonComponent, CaoBaseInput, CaoDropDownComponent, CaoTabGroup, CaoTabPanel, Footer, LinksButton, Paginator, StepComponent, StepperComponent, TablePaginatedService, TimePicker, getPtBrPaginatorIntlBasePaginated, getPtBrPaginatorIntlBaseTable };
2748
+ export { BaseAlert, BaseAlertService, BaseDialog, BaseDialogService, BaseFilterTablePaginatedService, BaseFilterTableService, BaseModal, BaseModalService, BasePaginationService, BaseTable, BaseTablePaginated, BaseTableService, BaseTimeRange, CaoAutocompleteComponent, CaoBaseButtonComponent, CaoBaseIcon, CaoBaseInput, CaoDropDownComponent, CaoTabGroup, CaoTabPanel, Footer, LinksButton, Paginator, StepComponent, StepperComponent, TablePaginatedService, TimePicker, getPtBrPaginatorIntlBasePaginated, getPtBrPaginatorIntlBaseTable };
2729
2749
  //# sourceMappingURL=ngx-opalbytes-components.mjs.map