s4y-ui 4.4.0 → 4.6.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,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { ContentChild, Component, signal, computed, Injectable, inject, input, HostBinding, Input, ChangeDetectionStrategy, NgModule, booleanAttribute, forwardRef, HostListener, Directive, EventEmitter, Output, model, output, ViewEncapsulation, effect, Inject, TemplateRef, ViewChild, ContentChildren } from '@angular/core';
2
+ import { ContentChild, Component, signal, computed, Injectable, inject, input, HostBinding, Input, ChangeDetectionStrategy, NgModule, booleanAttribute, forwardRef, HostListener, Directive, EventEmitter, Output, model, output, ViewEncapsulation, effect, Inject, TemplateRef, ViewChild, ContentChildren, ElementRef, ViewContainerRef } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
4
  import { CommonModule, AsyncPipe, JsonPipe, NgClass, NgTemplateOutlet, DOCUMENT, NgIf, NgStyle } from '@angular/common';
5
5
  import * as i1$1 from '@angular/platform-browser';
@@ -7,10 +7,14 @@ import { DomSanitizer } from '@angular/platform-browser';
7
7
  import * as i1$2 from '@angular/router';
8
8
  import { Router, RouterModule, GuardsCheckEnd } from '@angular/router';
9
9
  import { catchError, map, filter } from 'rxjs/operators';
10
- import { defer, from, throwError, BehaviorSubject, map as map$1, Subject, takeUntil } from 'rxjs';
10
+ import { defer, from, throwError, BehaviorSubject, map as map$1, Subject, takeUntil, Subscription, filter as filter$1, fromEvent } from 'rxjs';
11
+ import * as i1$3 from '@angular/cdk/scrolling';
12
+ import { CdkScrollableModule } from '@angular/cdk/scrolling';
11
13
  import * as i2 from '@angular/forms';
12
14
  import { NG_VALUE_ACCESSOR, NgControl, FormsModule } from '@angular/forms';
13
15
  import { trigger, transition, animate, style, group, query, state } from '@angular/animations';
16
+ import { Overlay } from '@angular/cdk/overlay';
17
+ import { TemplatePortal } from '@angular/cdk/portal';
14
18
 
15
19
  class DashboardLayoutComponent {
16
20
  asideTemplate;
@@ -300,11 +304,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
300
304
 
301
305
  class DashboardRoutesComponent {
302
306
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DashboardRoutesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
303
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: DashboardRoutesComponent, isStandalone: false, selector: "s4y-dashboard-routes", ngImport: i0, template: "<ng-content></ng-content>\r\n", styles: [":host{display:block;overflow-y:auto;overflow-x:hidden;height:calc(100dvh - var(--nav-height))}\n"] });
307
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: DashboardRoutesComponent, isStandalone: false, selector: "s4y-dashboard-routes", ngImport: i0, template: "<div class=\"s4y-dashboard-routes-container\" cdkScrollable>\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".s4y-dashboard-routes-container{display:block;overflow-y:auto;overflow-x:hidden;height:calc(100dvh - var(--nav-height))}\n"], dependencies: [{ kind: "directive", type: i1$3.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }] });
304
308
  }
305
309
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DashboardRoutesComponent, decorators: [{
306
310
  type: Component,
307
- args: [{ selector: 's4y-dashboard-routes', standalone: false, template: "<ng-content></ng-content>\r\n", styles: [":host{display:block;overflow-y:auto;overflow-x:hidden;height:calc(100dvh - var(--nav-height))}\n"] }]
311
+ args: [{ selector: 's4y-dashboard-routes', standalone: false, host: {}, template: "<div class=\"s4y-dashboard-routes-container\" cdkScrollable>\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".s4y-dashboard-routes-container{display:block;overflow-y:auto;overflow-x:hidden;height:calc(100dvh - var(--nav-height))}\n"] }]
308
312
  }] });
309
313
 
310
314
  class DashboardContainerComponent {
@@ -329,19 +333,32 @@ class DashboardModule {
329
333
  AsideComponent,
330
334
  NavbarComponent,
331
335
  DashboardRoutesComponent,
332
- DashboardContainerComponent], imports: [RouterModule, CommonModule, AvatarComponent, SvgComponent], exports: [DashboardLayoutComponent,
336
+ DashboardContainerComponent], imports: [RouterModule,
337
+ CommonModule,
338
+ AvatarComponent,
339
+ SvgComponent,
340
+ CdkScrollableModule], exports: [DashboardLayoutComponent,
333
341
  AsideComponent,
334
342
  NavbarComponent,
335
343
  DashboardRoutesComponent,
336
344
  DashboardContainerComponent] });
337
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DashboardModule, imports: [RouterModule, CommonModule, AvatarComponent] });
345
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DashboardModule, imports: [RouterModule,
346
+ CommonModule,
347
+ AvatarComponent,
348
+ CdkScrollableModule] });
338
349
  }
339
350
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: DashboardModule, decorators: [{
340
351
  type: NgModule,
341
352
  args: [{
342
353
  declarations: [COMPONENTS$1],
343
354
  exports: [COMPONENTS$1],
344
- imports: [RouterModule, CommonModule, AvatarComponent, SvgComponent],
355
+ imports: [
356
+ RouterModule,
357
+ CommonModule,
358
+ AvatarComponent,
359
+ SvgComponent,
360
+ CdkScrollableModule,
361
+ ],
345
362
  }]
346
363
  }] });
347
364
 
@@ -1041,8 +1058,6 @@ class TableComponent {
1041
1058
  sortFunction = output();
1042
1059
  sortField = input(null);
1043
1060
  sortOrder = input('none');
1044
- // voltar a direction ao mudar de coluna -- OK
1045
- // deixar o usuário pre preencher a coluna
1046
1061
  sortedData = computed(() => {
1047
1062
  let originalData = [...this.data()];
1048
1063
  const sortBy = this.sortBy();
@@ -1088,11 +1103,11 @@ class TableComponent {
1088
1103
  constructor() { }
1089
1104
  ngAfterViewInit() { }
1090
1105
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1091
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: TableComponent, isStandalone: true, selector: "s4y-table", inputs: { headers: { classPropertyName: "headers", publicName: "headers", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, customSort: { classPropertyName: "customSort", publicName: "customSort", isSignal: true, isRequired: false, transformFunction: null }, sortField: { classPropertyName: "sortField", publicName: "sortField", isSignal: true, isRequired: false, transformFunction: null }, sortOrder: { classPropertyName: "sortOrder", publicName: "sortOrder", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, tableStyle: { classPropertyName: "tableStyle", publicName: "tableStyle", isSignal: true, isRequired: false, transformFunction: null }, errorMessageDefault: { classPropertyName: "errorMessageDefault", publicName: "errorMessageDefault", isSignal: true, isRequired: false, transformFunction: null }, emptyMessageDefault: { classPropertyName: "emptyMessageDefault", publicName: "emptyMessageDefault", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortFunction: "sortFunction" }, queries: [{ propertyName: "rowTemplate", first: true, predicate: ["rowTemplate"], descendants: true }, { propertyName: "headTemplate", first: true, predicate: ["headTemplate"], descendants: true }, { propertyName: "emptyTemplate", first: true, predicate: ["emptyTemplate"], descendants: true }, { propertyName: "errorTemplate", first: true, predicate: ["errorTemplate"], descendants: true }, { propertyName: "customEmptyTemplate", first: true, predicate: ["customEmptyTemplate"], descendants: true }, { propertyName: "customErrorTemplate", first: true, predicate: ["customErrorTemplate"], descendants: true }], ngImport: i0, template: "<div class=\"s4y-table-container\" [ngStyle]=\"tableStyle()\">\r\n <table class=\"s4y-table\">\r\n <thead>\r\n <ng-container [ngTemplateOutlet]=\"headTemplate\"></ng-container>\r\n </thead>\r\n <tbody>\r\n @if (isLoading()) {\r\n <tr class=\"loading\">\r\n <td [colSpan]=\"headers().length\">\r\n <s4y-spinner></s4y-spinner>\r\n </td>\r\n </tr>\r\n } @else if (hasError()) {\r\n @if (errorTemplate) {\r\n <tr class=\"error\">\r\n <td [colSpan]=\"headers().length\">\r\n <ng-container [ngTemplateOutlet]=\"errorTemplate\"></ng-container>\r\n </td>\r\n </tr>\r\n } @else if (customErrorTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"customErrorTemplate\"></ng-container>\r\n } @else {\r\n <tr class=\"error\">\r\n <td [colSpan]=\"headers().length\">\r\n {{ errorMessageDefault() }}\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"tableContent\"></ng-container>\r\n }\r\n </tbody>\r\n </table>\r\n</div>\r\n\r\n<ng-template #SortIcon>\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"currentColor\"\r\n >\r\n <path\r\n d=\"M4.86885 11H2.6665L6 3H8L11.3334 11H9.13113L8.7213 10H5.27869L4.86885 11ZM6.09836 8H7.90163L7 5.8L6.09836 8ZM18.9999 16V3H16.9999V16H13.9999L17.9999 21L21.9999 16H18.9999ZM10.9999 13H2.99992V15H7.85414L2.99992 19V21H10.9999V19H6.14605L10.9999 15V13Z\"\r\n ></path>\r\n </svg>\r\n</ng-template>\r\n\r\n<ng-template #tableContent>\r\n @for (item of sortedData(); track $index) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: item, idx: $index }\"\r\n >\r\n </ng-container>\r\n } @empty {\r\n @if (emptyTemplate) {\r\n <tr class=\"empty-content\">\r\n <td [colSpan]=\"headers().length\">\r\n <ng-container [ngTemplateOutlet]=\"emptyTemplate\"></ng-container>\r\n </td>\r\n </tr>\r\n } @else if (customEmptyTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"customEmptyTemplate\"></ng-container>\r\n } @else {\r\n <tr class=\"empty-content\">\r\n <td [colSpan]=\"headers().length\">\r\n {{ emptyMessageDefault() }}\r\n </td>\r\n </tr>\r\n }\r\n }\r\n</ng-template>\r\n", styles: [".s4y-table-container{overflow:auto;min-height:30rem}@media screen and (min-width: 320px) and (max-width: 480px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}@media screen and (min-width: 481px) and (max-width: 767px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}@media screen and (min-width: 768px) and (max-width: 1024px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}.s4y-table{border:1px solid var(--gray-300);border-collapse:collapse;width:100%}@media screen and (min-width: 320px) and (max-width: 480px){.s4y-table tr{white-space:nowrap}}@media screen and (min-width: 481px) and (max-width: 767px){.s4y-table tr{white-space:nowrap}}@media screen and (min-width: 768px) and (max-width: 1024px){.s4y-table tr{white-space:nowrap}}.s4y-table .s4y-table-head-th__content{display:flex;justify-content:space-between}.s4y-table thead{background-color:#eaeaea}.s4y-table thead tr{font-size:1.3rem;height:5rem;font-weight:700}.s4y-table thead th{transition:.2s ease}.s4y-table tbody tr{background-color:#fff;font-size:1.3rem;font-weight:400;height:5rem;border-bottom:1px solid var(--gray-300)}.s4y-table tfoot{background-color:#eaeaea}.s4y-table th,.s4y-table td{text-align:start;padding:0 .4rem}.s4y-table td:first-child,.s4y-table td:last-child,.s4y-table th:first-child,.s4y-table th:last-child{padding:0 1.4rem}.s4y-table td,.s4y-table th{padding:0 1.4rem}.s4y-table tr.empty-content,.s4y-table tr.loading,.s4y-table tr.error{border:none}.s4y-table tr.empty-content td,.s4y-table tr.loading td,.s4y-table tr.error td{text-align:center;height:28rem;background-color:transparent;color:var(--gray-900);font-weight:700;border:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SpinnerComponent, selector: "s4y-spinner", inputs: ["size", "color"] }], encapsulation: i0.ViewEncapsulation.None });
1106
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: TableComponent, isStandalone: true, selector: "s4y-table", inputs: { headers: { classPropertyName: "headers", publicName: "headers", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, customSort: { classPropertyName: "customSort", publicName: "customSort", isSignal: true, isRequired: false, transformFunction: null }, sortField: { classPropertyName: "sortField", publicName: "sortField", isSignal: true, isRequired: false, transformFunction: null }, sortOrder: { classPropertyName: "sortOrder", publicName: "sortOrder", isSignal: true, isRequired: false, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, tableStyle: { classPropertyName: "tableStyle", publicName: "tableStyle", isSignal: true, isRequired: false, transformFunction: null }, errorMessageDefault: { classPropertyName: "errorMessageDefault", publicName: "errorMessageDefault", isSignal: true, isRequired: false, transformFunction: null }, emptyMessageDefault: { classPropertyName: "emptyMessageDefault", publicName: "emptyMessageDefault", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sortFunction: "sortFunction" }, queries: [{ propertyName: "rowTemplate", first: true, predicate: ["rowTemplate"], descendants: true }, { propertyName: "headTemplate", first: true, predicate: ["headTemplate"], descendants: true }, { propertyName: "emptyTemplate", first: true, predicate: ["emptyTemplate"], descendants: true }, { propertyName: "errorTemplate", first: true, predicate: ["errorTemplate"], descendants: true }, { propertyName: "customEmptyTemplate", first: true, predicate: ["customEmptyTemplate"], descendants: true }, { propertyName: "customErrorTemplate", first: true, predicate: ["customErrorTemplate"], descendants: true }], ngImport: i0, template: "<div class=\"s4y-table-container\" [ngStyle]=\"tableStyle()\" cdkScrollable>\r\n <table class=\"s4y-table\">\r\n <thead>\r\n <ng-container [ngTemplateOutlet]=\"headTemplate\"></ng-container>\r\n </thead>\r\n <tbody>\r\n @if (isLoading()) {\r\n <tr class=\"loading\">\r\n <td [colSpan]=\"headers().length\">\r\n <s4y-spinner></s4y-spinner>\r\n </td>\r\n </tr>\r\n } @else if (hasError()) {\r\n @if (errorTemplate) {\r\n <tr class=\"error\">\r\n <td [colSpan]=\"headers().length\">\r\n <ng-container [ngTemplateOutlet]=\"errorTemplate\"></ng-container>\r\n </td>\r\n </tr>\r\n } @else if (customErrorTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"customErrorTemplate\"></ng-container>\r\n } @else {\r\n <tr class=\"error\">\r\n <td [colSpan]=\"headers().length\">\r\n {{ errorMessageDefault() }}\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"tableContent\"></ng-container>\r\n }\r\n </tbody>\r\n </table>\r\n</div>\r\n\r\n<ng-template #SortIcon>\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"currentColor\"\r\n >\r\n <path\r\n d=\"M4.86885 11H2.6665L6 3H8L11.3334 11H9.13113L8.7213 10H5.27869L4.86885 11ZM6.09836 8H7.90163L7 5.8L6.09836 8ZM18.9999 16V3H16.9999V16H13.9999L17.9999 21L21.9999 16H18.9999ZM10.9999 13H2.99992V15H7.85414L2.99992 19V21H10.9999V19H6.14605L10.9999 15V13Z\"\r\n ></path>\r\n </svg>\r\n</ng-template>\r\n\r\n<ng-template #tableContent>\r\n @for (item of sortedData(); track $index) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: item, idx: $index }\"\r\n >\r\n </ng-container>\r\n } @empty {\r\n @if (emptyTemplate) {\r\n <tr class=\"empty-content\">\r\n <td [colSpan]=\"headers().length\">\r\n <ng-container [ngTemplateOutlet]=\"emptyTemplate\"></ng-container>\r\n </td>\r\n </tr>\r\n } @else if (customEmptyTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"customEmptyTemplate\"></ng-container>\r\n } @else {\r\n <tr class=\"empty-content\">\r\n <td [colSpan]=\"headers().length\">\r\n {{ emptyMessageDefault() }}\r\n </td>\r\n </tr>\r\n }\r\n }\r\n</ng-template>\r\n", styles: [".s4y-table-container{overflow:auto;min-height:30rem}@media screen and (min-width: 320px) and (max-width: 480px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}@media screen and (min-width: 481px) and (max-width: 767px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}@media screen and (min-width: 768px) and (max-width: 1024px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}.s4y-table{border:1px solid var(--gray-300);border-collapse:collapse;width:100%}@media screen and (min-width: 320px) and (max-width: 480px){.s4y-table tr{white-space:nowrap}}@media screen and (min-width: 481px) and (max-width: 767px){.s4y-table tr{white-space:nowrap}}@media screen and (min-width: 768px) and (max-width: 1024px){.s4y-table tr{white-space:nowrap}}.s4y-table .s4y-table-head-th__content{display:flex;justify-content:space-between}.s4y-table thead{background-color:#eaeaea}.s4y-table thead tr{font-size:1.3rem;height:5rem;font-weight:700}.s4y-table thead th{transition:.2s ease}.s4y-table tbody tr{background-color:#fff;font-size:1.3rem;font-weight:400;height:5rem;border-bottom:1px solid var(--gray-300)}.s4y-table tfoot{background-color:#eaeaea}.s4y-table th,.s4y-table td{text-align:start;padding:0 .4rem}.s4y-table td:first-child,.s4y-table td:last-child,.s4y-table th:first-child,.s4y-table th:last-child{padding:0 1.4rem}.s4y-table td,.s4y-table th{padding:0 1.4rem}.s4y-table tr.empty-content,.s4y-table tr.loading,.s4y-table tr.error{border:none}.s4y-table tr.empty-content td,.s4y-table tr.loading td,.s4y-table tr.error td{text-align:center;height:28rem;background-color:transparent;color:var(--gray-900);font-weight:700;border:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SpinnerComponent, selector: "s4y-spinner", inputs: ["size", "color"] }, { kind: "ngmodule", type: CdkScrollableModule }, { kind: "directive", type: i1$3.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }], encapsulation: i0.ViewEncapsulation.None });
1092
1107
  }
1093
1108
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: TableComponent, decorators: [{
1094
1109
  type: Component,
1095
- args: [{ selector: 's4y-table', imports: [CommonModule, SpinnerComponent], encapsulation: ViewEncapsulation.None, template: "<div class=\"s4y-table-container\" [ngStyle]=\"tableStyle()\">\r\n <table class=\"s4y-table\">\r\n <thead>\r\n <ng-container [ngTemplateOutlet]=\"headTemplate\"></ng-container>\r\n </thead>\r\n <tbody>\r\n @if (isLoading()) {\r\n <tr class=\"loading\">\r\n <td [colSpan]=\"headers().length\">\r\n <s4y-spinner></s4y-spinner>\r\n </td>\r\n </tr>\r\n } @else if (hasError()) {\r\n @if (errorTemplate) {\r\n <tr class=\"error\">\r\n <td [colSpan]=\"headers().length\">\r\n <ng-container [ngTemplateOutlet]=\"errorTemplate\"></ng-container>\r\n </td>\r\n </tr>\r\n } @else if (customErrorTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"customErrorTemplate\"></ng-container>\r\n } @else {\r\n <tr class=\"error\">\r\n <td [colSpan]=\"headers().length\">\r\n {{ errorMessageDefault() }}\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"tableContent\"></ng-container>\r\n }\r\n </tbody>\r\n </table>\r\n</div>\r\n\r\n<ng-template #SortIcon>\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"currentColor\"\r\n >\r\n <path\r\n d=\"M4.86885 11H2.6665L6 3H8L11.3334 11H9.13113L8.7213 10H5.27869L4.86885 11ZM6.09836 8H7.90163L7 5.8L6.09836 8ZM18.9999 16V3H16.9999V16H13.9999L17.9999 21L21.9999 16H18.9999ZM10.9999 13H2.99992V15H7.85414L2.99992 19V21H10.9999V19H6.14605L10.9999 15V13Z\"\r\n ></path>\r\n </svg>\r\n</ng-template>\r\n\r\n<ng-template #tableContent>\r\n @for (item of sortedData(); track $index) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: item, idx: $index }\"\r\n >\r\n </ng-container>\r\n } @empty {\r\n @if (emptyTemplate) {\r\n <tr class=\"empty-content\">\r\n <td [colSpan]=\"headers().length\">\r\n <ng-container [ngTemplateOutlet]=\"emptyTemplate\"></ng-container>\r\n </td>\r\n </tr>\r\n } @else if (customEmptyTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"customEmptyTemplate\"></ng-container>\r\n } @else {\r\n <tr class=\"empty-content\">\r\n <td [colSpan]=\"headers().length\">\r\n {{ emptyMessageDefault() }}\r\n </td>\r\n </tr>\r\n }\r\n }\r\n</ng-template>\r\n", styles: [".s4y-table-container{overflow:auto;min-height:30rem}@media screen and (min-width: 320px) and (max-width: 480px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}@media screen and (min-width: 481px) and (max-width: 767px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}@media screen and (min-width: 768px) and (max-width: 1024px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}.s4y-table{border:1px solid var(--gray-300);border-collapse:collapse;width:100%}@media screen and (min-width: 320px) and (max-width: 480px){.s4y-table tr{white-space:nowrap}}@media screen and (min-width: 481px) and (max-width: 767px){.s4y-table tr{white-space:nowrap}}@media screen and (min-width: 768px) and (max-width: 1024px){.s4y-table tr{white-space:nowrap}}.s4y-table .s4y-table-head-th__content{display:flex;justify-content:space-between}.s4y-table thead{background-color:#eaeaea}.s4y-table thead tr{font-size:1.3rem;height:5rem;font-weight:700}.s4y-table thead th{transition:.2s ease}.s4y-table tbody tr{background-color:#fff;font-size:1.3rem;font-weight:400;height:5rem;border-bottom:1px solid var(--gray-300)}.s4y-table tfoot{background-color:#eaeaea}.s4y-table th,.s4y-table td{text-align:start;padding:0 .4rem}.s4y-table td:first-child,.s4y-table td:last-child,.s4y-table th:first-child,.s4y-table th:last-child{padding:0 1.4rem}.s4y-table td,.s4y-table th{padding:0 1.4rem}.s4y-table tr.empty-content,.s4y-table tr.loading,.s4y-table tr.error{border:none}.s4y-table tr.empty-content td,.s4y-table tr.loading td,.s4y-table tr.error td{text-align:center;height:28rem;background-color:transparent;color:var(--gray-900);font-weight:700;border:none}\n"] }]
1110
+ args: [{ selector: 's4y-table', imports: [CommonModule, SpinnerComponent, CdkScrollableModule], encapsulation: ViewEncapsulation.None, template: "<div class=\"s4y-table-container\" [ngStyle]=\"tableStyle()\" cdkScrollable>\r\n <table class=\"s4y-table\">\r\n <thead>\r\n <ng-container [ngTemplateOutlet]=\"headTemplate\"></ng-container>\r\n </thead>\r\n <tbody>\r\n @if (isLoading()) {\r\n <tr class=\"loading\">\r\n <td [colSpan]=\"headers().length\">\r\n <s4y-spinner></s4y-spinner>\r\n </td>\r\n </tr>\r\n } @else if (hasError()) {\r\n @if (errorTemplate) {\r\n <tr class=\"error\">\r\n <td [colSpan]=\"headers().length\">\r\n <ng-container [ngTemplateOutlet]=\"errorTemplate\"></ng-container>\r\n </td>\r\n </tr>\r\n } @else if (customErrorTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"customErrorTemplate\"></ng-container>\r\n } @else {\r\n <tr class=\"error\">\r\n <td [colSpan]=\"headers().length\">\r\n {{ errorMessageDefault() }}\r\n </td>\r\n </tr>\r\n }\r\n } @else {\r\n <ng-container [ngTemplateOutlet]=\"tableContent\"></ng-container>\r\n }\r\n </tbody>\r\n </table>\r\n</div>\r\n\r\n<ng-template #SortIcon>\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"currentColor\"\r\n >\r\n <path\r\n d=\"M4.86885 11H2.6665L6 3H8L11.3334 11H9.13113L8.7213 10H5.27869L4.86885 11ZM6.09836 8H7.90163L7 5.8L6.09836 8ZM18.9999 16V3H16.9999V16H13.9999L17.9999 21L21.9999 16H18.9999ZM10.9999 13H2.99992V15H7.85414L2.99992 19V21H10.9999V19H6.14605L10.9999 15V13Z\"\r\n ></path>\r\n </svg>\r\n</ng-template>\r\n\r\n<ng-template #tableContent>\r\n @for (item of sortedData(); track $index) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"rowTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: item, idx: $index }\"\r\n >\r\n </ng-container>\r\n } @empty {\r\n @if (emptyTemplate) {\r\n <tr class=\"empty-content\">\r\n <td [colSpan]=\"headers().length\">\r\n <ng-container [ngTemplateOutlet]=\"emptyTemplate\"></ng-container>\r\n </td>\r\n </tr>\r\n } @else if (customEmptyTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"customEmptyTemplate\"></ng-container>\r\n } @else {\r\n <tr class=\"empty-content\">\r\n <td [colSpan]=\"headers().length\">\r\n {{ emptyMessageDefault() }}\r\n </td>\r\n </tr>\r\n }\r\n }\r\n</ng-template>\r\n", styles: [".s4y-table-container{overflow:auto;min-height:30rem}@media screen and (min-width: 320px) and (max-width: 480px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}@media screen and (min-width: 481px) and (max-width: 767px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}@media screen and (min-width: 768px) and (max-width: 1024px){.s4y-table-container{width:90dvw;padding-bottom:1.4rem;margin:0 auto}}.s4y-table{border:1px solid var(--gray-300);border-collapse:collapse;width:100%}@media screen and (min-width: 320px) and (max-width: 480px){.s4y-table tr{white-space:nowrap}}@media screen and (min-width: 481px) and (max-width: 767px){.s4y-table tr{white-space:nowrap}}@media screen and (min-width: 768px) and (max-width: 1024px){.s4y-table tr{white-space:nowrap}}.s4y-table .s4y-table-head-th__content{display:flex;justify-content:space-between}.s4y-table thead{background-color:#eaeaea}.s4y-table thead tr{font-size:1.3rem;height:5rem;font-weight:700}.s4y-table thead th{transition:.2s ease}.s4y-table tbody tr{background-color:#fff;font-size:1.3rem;font-weight:400;height:5rem;border-bottom:1px solid var(--gray-300)}.s4y-table tfoot{background-color:#eaeaea}.s4y-table th,.s4y-table td{text-align:start;padding:0 .4rem}.s4y-table td:first-child,.s4y-table td:last-child,.s4y-table th:first-child,.s4y-table th:last-child{padding:0 1.4rem}.s4y-table td,.s4y-table th{padding:0 1.4rem}.s4y-table tr.empty-content,.s4y-table tr.loading,.s4y-table tr.error{border:none}.s4y-table tr.empty-content td,.s4y-table tr.loading td,.s4y-table tr.error td{text-align:center;height:28rem;background-color:transparent;color:var(--gray-900);font-weight:700;border:none}\n"] }]
1096
1111
  }], ctorParameters: () => [], propDecorators: { rowTemplate: [{
1097
1112
  type: ContentChild,
1098
1113
  args: ['rowTemplate']
@@ -1348,7 +1363,7 @@ const modalFadeCombined = trigger('modalFadeCombined', [
1348
1363
  query('.s4y-modal-container', [
1349
1364
  style({ opacity: 0, transform: 'translateY(20px)' }),
1350
1365
  animate('250ms ease-out', style({ opacity: 1, transform: 'translateY(0)' })),
1351
- ]),
1366
+ ], { optional: true }),
1352
1367
  ]),
1353
1368
  ]),
1354
1369
  transition(':leave', [
@@ -1360,7 +1375,7 @@ const modalFadeCombined = trigger('modalFadeCombined', [
1360
1375
  // ]),
1361
1376
  query('.s4y-modal-container', [
1362
1377
  animate('200ms ease-in', style({ opacity: 0, transform: 'translateY(20px)' })),
1363
- ]),
1378
+ ], { optional: true }),
1364
1379
  ]),
1365
1380
  ]),
1366
1381
  ]);
@@ -1374,7 +1389,7 @@ class ModalComponent {
1374
1389
  centeredModal = input(true);
1375
1390
  title = input('Titulo');
1376
1391
  modalStyle = input();
1377
- visible = input(false);
1392
+ visible = model(false);
1378
1393
  requestClose = output();
1379
1394
  withHeader = input(true);
1380
1395
  constructor(renderer, document) {
@@ -1392,6 +1407,7 @@ class ModalComponent {
1392
1407
  });
1393
1408
  }
1394
1409
  onClose() {
1410
+ this.visible.set(false);
1395
1411
  this.requestClose.emit(false);
1396
1412
  }
1397
1413
  ngAfterViewInit() { }
@@ -1404,7 +1420,7 @@ class ModalComponent {
1404
1420
  window.removeEventListener('keydown', this.escListener);
1405
1421
  }
1406
1422
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ModalComponent, deps: [{ token: i0.Renderer2 }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Component });
1407
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: ModalComponent, isStandalone: true, selector: "s4y-modal", inputs: { scrollableContent: { classPropertyName: "scrollableContent", publicName: "scrollableContent", isSignal: true, isRequired: false, transformFunction: null }, centeredModal: { classPropertyName: "centeredModal", publicName: "centeredModal", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, modalStyle: { classPropertyName: "modalStyle", publicName: "modalStyle", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, withHeader: { classPropertyName: "withHeader", publicName: "withHeader", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { requestClose: "requestClose" }, queries: [{ propertyName: "modalHeaderTemplate", first: true, predicate: ["modalHeaderTemplate"], descendants: true }, { propertyName: "modalFooterTemplate", first: true, predicate: ["modalFooterTemplate"], descendants: true }], ngImport: i0, template: "@if (visible()) {\r\n <div\r\n class=\"s4y-modal-wrapper\"\r\n [class.s4y-modal-wrapper-with-scrollable]=\"!scrollableContent()\"\r\n [class.s4y-modal-wrapper-centered]=\"centeredModal()\"\r\n (click)=\"onClose()\"\r\n @modalFadeCombined\r\n >\r\n <div\r\n class=\"s4y-modal-container\"\r\n (click)=\"$event.stopPropagation()\"\r\n [class.s4y-modal-container__scrollable-content]=\"scrollableContent()\"\r\n [ngStyle]=\"modalStyle()\"\r\n >\r\n @if (modalHeaderTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"modalHeaderTemplate\"></ng-container>\r\n }\r\n @if (!modalHeaderTemplate && withHeader()) {\r\n <div class=\"s4y-modal-header\">\r\n <h2 class=\"s4y-modal-header__title\">{{ title() }}</h2>\r\n <button role=\"button\" (click)=\"onClose()\">\r\n <p>&times;</p>\r\n </button>\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"s4y-modal-body\"\r\n [class.s4y-modal-body__scrollable-content]=\"scrollableContent()\"\r\n >\r\n <ng-content></ng-content>\r\n </div>\r\n @if (modalFooterTemplate) {\r\n <div class=\"s4y-modal-footer\">\r\n <ng-container [ngTemplateOutlet]=\"modalFooterTemplate\"></ng-container>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [".s4y-modal-wrapper{position:fixed;inset:0;display:flex;align-items:flex-start;justify-content:center;z-index:var(--z-index-modal-backdrop);padding:3.8rem;background-color:#000000b3}.s4y-modal-wrapper.s4y-modal-wrapper-with-scrollable{overflow-y:auto;-webkit-overflow-scrolling:auto}.s4y-modal-wrapper.s4y-modal-wrapper-centered{align-items:center;justify-content:center}.s4y-modal-container{background:#fff;width:100%;min-width:300px;max-width:500px;border-radius:var(--radius);z-index:var(--z-index-modal);box-shadow:0 4px 12px #0003;animation:fadeInUp .3s ease;padding:1.8rem 2rem 2.2rem;display:flex;flex-direction:column}@media screen and (min-width: 320px) and (max-width: 480px){.s4y-modal-container{width:90%}}@media screen and (min-width: 481px) and (max-width: 767px){.s4y-modal-container{width:90%}}@media screen and (min-width: 768px) and (max-width: 1024px){.s4y-modal-container{width:90%}}.s4y-modal-header{padding-bottom:1rem;flex-shrink:0;display:flex;align-items:center;justify-content:space-between}.s4y-modal-header button{padding:.6rem 1.2rem;font-size:1.8rem;cursor:pointer}.s4y-modal-header .s4y-modal-header__title{font-size:1.8rem;color:var(--primary-color)}.s4y-modal-body{flex-grow:1}.s4y-modal-footer{padding:1rem 0;flex-shrink:0}.s4y-modal-body__scrollable-content{overflow-y:auto}.s4y-modal-container__scrollable-content{max-height:90dvh;min-height:18rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], animations: [modalFadeCombined] });
1423
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: ModalComponent, isStandalone: true, selector: "s4y-modal", inputs: { scrollableContent: { classPropertyName: "scrollableContent", publicName: "scrollableContent", isSignal: true, isRequired: false, transformFunction: null }, centeredModal: { classPropertyName: "centeredModal", publicName: "centeredModal", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, modalStyle: { classPropertyName: "modalStyle", publicName: "modalStyle", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, withHeader: { classPropertyName: "withHeader", publicName: "withHeader", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visible: "visibleChange", requestClose: "requestClose" }, queries: [{ propertyName: "modalHeaderTemplate", first: true, predicate: ["modalHeaderTemplate"], descendants: true }, { propertyName: "modalFooterTemplate", first: true, predicate: ["modalFooterTemplate"], descendants: true }], ngImport: i0, template: "@if (visible()) {\r\n <div\r\n class=\"s4y-modal-wrapper\"\r\n [class.s4y-modal-wrapper-with-scrollable]=\"!scrollableContent()\"\r\n [class.s4y-modal-wrapper-centered]=\"centeredModal()\"\r\n (click)=\"onClose()\"\r\n @modalFadeCombined\r\n >\r\n <div\r\n class=\"s4y-modal-container\"\r\n (click)=\"$event.stopPropagation()\"\r\n [class.s4y-modal-container__scrollable-content]=\"scrollableContent()\"\r\n [ngStyle]=\"modalStyle()\"\r\n >\r\n @if (modalHeaderTemplate) {\r\n <ng-container [ngTemplateOutlet]=\"modalHeaderTemplate\"></ng-container>\r\n }\r\n @if (!modalHeaderTemplate && withHeader()) {\r\n <div class=\"s4y-modal-header\">\r\n <h2 class=\"s4y-modal-header__title\">{{ title() }}</h2>\r\n <button role=\"button\" (click)=\"onClose()\">\r\n <p>&times;</p>\r\n </button>\r\n </div>\r\n }\r\n\r\n <div\r\n class=\"s4y-modal-body\"\r\n [class.s4y-modal-body__scrollable-content]=\"scrollableContent()\"\r\n >\r\n <ng-content></ng-content>\r\n </div>\r\n @if (modalFooterTemplate) {\r\n <div class=\"s4y-modal-footer\">\r\n <ng-container [ngTemplateOutlet]=\"modalFooterTemplate\"></ng-container>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n}\r\n", styles: [".s4y-modal-wrapper{position:fixed;inset:0;display:flex;align-items:flex-start;justify-content:center;z-index:var(--z-index-modal-backdrop);padding:3.8rem;background-color:#000000b3}.s4y-modal-wrapper.s4y-modal-wrapper-with-scrollable{overflow-y:auto;-webkit-overflow-scrolling:auto}.s4y-modal-wrapper.s4y-modal-wrapper-centered{align-items:center;justify-content:center}.s4y-modal-container{background:#fff;width:100%;min-width:300px;max-width:500px;border-radius:var(--radius);z-index:var(--z-index-modal);box-shadow:0 4px 12px #0003;animation:fadeInUp .3s ease;padding:1.8rem 2rem 2.2rem;display:flex;flex-direction:column}@media screen and (min-width: 320px) and (max-width: 480px){.s4y-modal-container{width:90%}}@media screen and (min-width: 481px) and (max-width: 767px){.s4y-modal-container{width:90%}}@media screen and (min-width: 768px) and (max-width: 1024px){.s4y-modal-container{width:90%}}.s4y-modal-header{padding-bottom:1rem;flex-shrink:0;display:flex;align-items:center;justify-content:space-between}.s4y-modal-header button{padding:.6rem 1.2rem;font-size:1.8rem;cursor:pointer}.s4y-modal-header .s4y-modal-header__title{font-size:1.8rem;color:var(--primary-color)}.s4y-modal-body{flex-grow:1}.s4y-modal-footer{padding:1rem 0;flex-shrink:0}.s4y-modal-body__scrollable-content{overflow-y:auto}.s4y-modal-container__scrollable-content{max-height:90dvh;min-height:18rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], animations: [modalFadeCombined] });
1408
1424
  }
1409
1425
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ModalComponent, decorators: [{
1410
1426
  type: Component,
@@ -2883,6 +2899,293 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
2883
2899
  type: Input
2884
2900
  }] } });
2885
2901
 
2902
+ class PopoverPanelComponent {
2903
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PopoverPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2904
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: PopoverPanelComponent, isStandalone: true, selector: "s4y-popover-panel", ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{z-index:5;padding:1.4rem;border-radius:var(--radius);font-size:1.4rem;box-shadow:var(--shadow-default);border:1px solid var(--gray-300);top:2.9rem;right:0;min-width:14rem;background:#fff;width:fit-content;display:flex;flex-direction:column;align-items:flex-start;gap:.4rem}\n"] });
2905
+ }
2906
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PopoverPanelComponent, decorators: [{
2907
+ type: Component,
2908
+ args: [{ selector: 's4y-popover-panel', imports: [], template: `<ng-content />`, styles: [":host{z-index:5;padding:1.4rem;border-radius:var(--radius);font-size:1.4rem;box-shadow:var(--shadow-default);border:1px solid var(--gray-300);top:2.9rem;right:0;min-width:14rem;background:#fff;width:fit-content;display:flex;flex-direction:column;align-items:flex-start;gap:.4rem}\n"] }]
2909
+ }] });
2910
+
2911
+ class PopoverTriggerDirective {
2912
+ overlay = inject(Overlay);
2913
+ host = inject((ElementRef));
2914
+ vcr = inject(ViewContainerRef);
2915
+ overlayRef;
2916
+ subs = new Subscription();
2917
+ menuTrigger = input(null, {
2918
+ alias: 's4yPopoverTrigger',
2919
+ });
2920
+ menuContext = input(null, { alias: 's4yPopoverTriggerContext' });
2921
+ menuPosition = input('bottom-right', {
2922
+ alias: 's4yPopoverPosition',
2923
+ });
2924
+ popoverOffsetX = input(0, { alias: 's4yPopoverOffsetX' });
2925
+ popoverOffsetY = input(4, { alias: 's4yPopoverOffsetY' });
2926
+ fade = input(true, { alias: 's4yPopoverFade' });
2927
+ fadeDuration = input(140, { alias: 's4yPopoverFadeDuration' });
2928
+ constructor() { }
2929
+ toggle() {
2930
+ if (this.overlayRef?.hasAttached()) {
2931
+ this.close();
2932
+ return;
2933
+ }
2934
+ this.open();
2935
+ }
2936
+ open() {
2937
+ const tpl = this.menuTrigger();
2938
+ if (!tpl)
2939
+ return;
2940
+ const positions = this.buildPositions(this.menuPosition(), this.popoverOffsetX(), this.popoverOffsetY());
2941
+ if (!this.overlayRef) {
2942
+ const positionStrategy = this.overlay
2943
+ .position()
2944
+ .flexibleConnectedTo(this.host)
2945
+ .withFlexibleDimensions(false)
2946
+ .withPush(true)
2947
+ .withGrowAfterOpen(true)
2948
+ .withPositions(positions);
2949
+ this.overlayRef = this.overlay.create({
2950
+ positionStrategy,
2951
+ hasBackdrop: false, // deixa scrollar tabela
2952
+ panelClass: ['s4y-dropdown-panel', 's4y-popover-fade'],
2953
+ scrollStrategy: this.overlay.scrollStrategies.close(),
2954
+ });
2955
+ // fecha no clique no backdrop
2956
+ this.subs.add(this.overlayRef.backdropClick().subscribe(() => this.close()));
2957
+ // fecha quando o overlay é detachado
2958
+ this.subs.add(this.overlayRef.detachments().subscribe(() => this.cleanup()));
2959
+ // fecha no ESC enquanto focado dentro do painel
2960
+ this.subs.add(this.overlayRef
2961
+ .keydownEvents()
2962
+ .pipe(filter$1((e) => e.key === 'Escape'))
2963
+ .subscribe(() => this.close()));
2964
+ // fecha ao clicar fora (sem backdrop)
2965
+ this.subs.add(fromEvent(document, 'mousedown')
2966
+ .pipe(filter$1((ev) => {
2967
+ const t = ev.target;
2968
+ const inside = this.overlayRef.overlayElement.contains(t) ||
2969
+ this.host.nativeElement.contains(t);
2970
+ return !inside;
2971
+ }))
2972
+ .subscribe(() => this.close()));
2973
+ }
2974
+ else {
2975
+ const strategy = this.overlayRef.getConfig()
2976
+ .positionStrategy;
2977
+ strategy.withPositions(positions);
2978
+ this.overlayRef.updatePosition();
2979
+ }
2980
+ const portal = new TemplatePortal(tpl, this.vcr, {
2981
+ $implicit: this.menuContext(),
2982
+ row: this.menuContext(),
2983
+ });
2984
+ this.overlayRef.attach(portal);
2985
+ const el = this.overlayRef.overlayElement;
2986
+ el.style.setProperty('--s4y-popover-fade-duration', `${this.fadeDuration()}ms`);
2987
+ // animação de ENTRADA
2988
+ if (this.fade()) {
2989
+ // estado inicial já é opaco=0 (via CSS). Força reflow e aplica "enter".
2990
+ el.classList.remove('leave');
2991
+ // força reflow pra garantir a transição
2992
+ void el.offsetWidth;
2993
+ el.classList.add('enter');
2994
+ }
2995
+ // acessibilidade: foco no primeiro botão/item do menu
2996
+ queueMicrotask(() => {
2997
+ const first = this.overlayRef.overlayElement.querySelector('button,[href],[tabindex]:not([tabindex="-1"])');
2998
+ first?.focus();
2999
+ });
3000
+ }
3001
+ async close() {
3002
+ if (!this.overlayRef?.hasAttached())
3003
+ return;
3004
+ const el = this.overlayRef.overlayElement;
3005
+ if (this.fade()) {
3006
+ // troca enter -> leave e espera transição terminar
3007
+ el.classList.remove('enter');
3008
+ el.classList.add('leave');
3009
+ await this.waitTransitionEnd(el, this.fadeDuration());
3010
+ }
3011
+ this.overlayRef.detach();
3012
+ }
3013
+ waitTransitionEnd(el, maxMs) {
3014
+ return new Promise((resolve) => {
3015
+ let done = false;
3016
+ const off = () => {
3017
+ if (done)
3018
+ return;
3019
+ done = true;
3020
+ el.removeEventListener('transitionend', onEnd);
3021
+ resolve();
3022
+ };
3023
+ const onEnd = (e) => {
3024
+ // garante que veio do opacity/transform do próprio elemento
3025
+ if (e.target === el)
3026
+ off();
3027
+ };
3028
+ el.addEventListener('transitionend', onEnd, { once: true });
3029
+ // fallback se o evento não disparar
3030
+ setTimeout(off, maxMs + 50);
3031
+ });
3032
+ }
3033
+ cleanup() {
3034
+ const el = this.overlayRef?.overlayElement;
3035
+ if (el) {
3036
+ el.classList.remove('enter', 'leave');
3037
+ }
3038
+ }
3039
+ buildPositions(preset, ox, oy) {
3040
+ // helpers
3041
+ const P = (originX, originY, overlayX, overlayY, offsetX = 0, offsetY = 0) => ({
3042
+ originX,
3043
+ originY,
3044
+ overlayX,
3045
+ overlayY,
3046
+ offsetX,
3047
+ offsetY,
3048
+ });
3049
+ // presets principais
3050
+ const map = {
3051
+ // TOP
3052
+ 'top-left': [
3053
+ P('start', 'top', 'start', 'bottom', ox, -oy),
3054
+ P('start', 'bottom', 'start', 'top', ox, oy),
3055
+ P('end', 'top', 'end', 'bottom', ox, -oy),
3056
+ P('center', 'top', 'center', 'bottom', ox, -oy),
3057
+ ],
3058
+ 'top-center': [
3059
+ P('center', 'top', 'center', 'bottom', ox, -oy),
3060
+ P('center', 'bottom', 'center', 'top', ox, oy),
3061
+ P('start', 'top', 'start', 'bottom', ox, -oy),
3062
+ P('end', 'top', 'end', 'bottom', ox, -oy),
3063
+ ],
3064
+ 'top-right': [
3065
+ P('end', 'top', 'end', 'bottom', ox, -oy),
3066
+ P('end', 'bottom', 'end', 'top', ox, oy),
3067
+ P('start', 'top', 'start', 'bottom', ox, -oy),
3068
+ P('center', 'top', 'center', 'bottom', ox, -oy),
3069
+ ],
3070
+ // BOTTOM
3071
+ 'bottom-left': [
3072
+ P('start', 'bottom', 'start', 'top', ox, oy),
3073
+ P('start', 'top', 'start', 'bottom', ox, -oy),
3074
+ P('end', 'bottom', 'end', 'top', ox, oy),
3075
+ P('center', 'bottom', 'center', 'top', ox, oy),
3076
+ ],
3077
+ 'bottom-center': [
3078
+ P('center', 'bottom', 'center', 'top', ox, oy),
3079
+ P('center', 'top', 'center', 'bottom', ox, -oy),
3080
+ P('start', 'bottom', 'start', 'top', ox, oy),
3081
+ P('end', 'bottom', 'end', 'top', ox, oy),
3082
+ ],
3083
+ 'bottom-right': [
3084
+ P('end', 'bottom', 'end', 'top', ox, oy),
3085
+ P('end', 'top', 'end', 'bottom', ox, -oy),
3086
+ P('start', 'bottom', 'start', 'top', ox, oy),
3087
+ P('center', 'bottom', 'center', 'top', ox, oy),
3088
+ ],
3089
+ // LEFT
3090
+ 'left-top': [
3091
+ P('start', 'top', 'end', 'top', -ox, oy),
3092
+ P('start', 'center', 'end', 'center', -ox, 0),
3093
+ P('start', 'bottom', 'end', 'bottom', -ox, -oy),
3094
+ P('end', 'top', 'start', 'top', ox, oy), // fallback espelha para direita
3095
+ ],
3096
+ 'left-center': [
3097
+ P('start', 'center', 'end', 'center', -ox, 0),
3098
+ P('start', 'top', 'end', 'top', -ox, oy),
3099
+ P('start', 'bottom', 'end', 'bottom', -ox, -oy),
3100
+ P('end', 'center', 'start', 'center', ox, 0),
3101
+ ],
3102
+ 'left-bottom': [
3103
+ P('start', 'bottom', 'end', 'bottom', -ox, -oy),
3104
+ P('start', 'center', 'end', 'center', -ox, 0),
3105
+ P('start', 'top', 'end', 'top', -ox, oy),
3106
+ P('end', 'bottom', 'start', 'bottom', ox, -oy),
3107
+ ],
3108
+ // RIGHT
3109
+ 'right-top': [
3110
+ P('end', 'top', 'start', 'top', ox, oy),
3111
+ P('end', 'center', 'start', 'center', ox, 0),
3112
+ P('end', 'bottom', 'start', 'bottom', ox, -oy),
3113
+ P('start', 'top', 'end', 'top', -ox, oy), // fallback espelha para esquerda
3114
+ ],
3115
+ 'right-center': [
3116
+ P('end', 'center', 'start', 'center', ox, 0),
3117
+ P('end', 'top', 'start', 'top', ox, oy),
3118
+ P('end', 'bottom', 'start', 'bottom', ox, -oy),
3119
+ P('start', 'center', 'end', 'center', -ox, 0),
3120
+ ],
3121
+ 'right-bottom': [
3122
+ P('end', 'bottom', 'start', 'bottom', ox, -oy),
3123
+ P('end', 'center', 'start', 'center', ox, 0),
3124
+ P('end', 'top', 'start', 'top', ox, oy),
3125
+ P('start', 'bottom', 'end', 'bottom', -ox, -oy),
3126
+ ],
3127
+ };
3128
+ return map[preset] ?? map['bottom-left'];
3129
+ }
3130
+ ngOnDestroy() {
3131
+ this.close();
3132
+ this.subs.unsubscribe();
3133
+ this.overlayRef?.dispose();
3134
+ }
3135
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PopoverTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3136
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.15", type: PopoverTriggerDirective, isStandalone: true, selector: "[s4yPopoverTrigger]", inputs: { menuTrigger: { classPropertyName: "menuTrigger", publicName: "s4yPopoverTrigger", isSignal: true, isRequired: false, transformFunction: null }, menuContext: { classPropertyName: "menuContext", publicName: "s4yPopoverTriggerContext", isSignal: true, isRequired: false, transformFunction: null }, menuPosition: { classPropertyName: "menuPosition", publicName: "s4yPopoverPosition", isSignal: true, isRequired: false, transformFunction: null }, popoverOffsetX: { classPropertyName: "popoverOffsetX", publicName: "s4yPopoverOffsetX", isSignal: true, isRequired: false, transformFunction: null }, popoverOffsetY: { classPropertyName: "popoverOffsetY", publicName: "s4yPopoverOffsetY", isSignal: true, isRequired: false, transformFunction: null }, fade: { classPropertyName: "fade", publicName: "s4yPopoverFade", isSignal: true, isRequired: false, transformFunction: null }, fadeDuration: { classPropertyName: "fadeDuration", publicName: "s4yPopoverFadeDuration", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "toggle()" } }, ngImport: i0 });
3137
+ }
3138
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: PopoverTriggerDirective, decorators: [{
3139
+ type: Directive,
3140
+ args: [{
3141
+ selector: '[s4yPopoverTrigger]',
3142
+ standalone: true,
3143
+ }]
3144
+ }], ctorParameters: () => [], propDecorators: { toggle: [{
3145
+ type: HostListener,
3146
+ args: ['click']
3147
+ }] } });
3148
+
3149
+ class MenuComponent {
3150
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: MenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3151
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: MenuComponent, isStandalone: true, selector: "s4y-menu", ngImport: i0, template: '<ng-content/>', isInline: true, styles: [":host{z-index:5;padding:1.4rem;background-color:#fff;border-radius:var(--radius);font-size:1.4rem;box-shadow:var(--shadow-default);border:1px solid var(--gray-400);top:2.9rem;right:0;min-width:14rem;max-width:240px;display:flex;flex-direction:column;align-items:flex-start;gap:.4rem}\n"] });
3152
+ }
3153
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: MenuComponent, decorators: [{
3154
+ type: Component,
3155
+ args: [{ selector: 's4y-menu', imports: [], template: '<ng-content/>', styles: [":host{z-index:5;padding:1.4rem;background-color:#fff;border-radius:var(--radius);font-size:1.4rem;box-shadow:var(--shadow-default);border:1px solid var(--gray-400);top:2.9rem;right:0;min-width:14rem;max-width:240px;display:flex;flex-direction:column;align-items:flex-start;gap:.4rem}\n"] }]
3156
+ }] });
3157
+
3158
+ class MenuItemComponent {
3159
+ iconUri = input();
3160
+ imageUri = input();
3161
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: MenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3162
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.15", type: MenuItemComponent, isStandalone: true, selector: "button[s4yMenuItem], a[s4yMenuItem]", inputs: { iconUri: { classPropertyName: "iconUri", publicName: "iconUri", isSignal: true, isRequired: false, transformFunction: null }, imageUri: { classPropertyName: "imageUri", publicName: "imageUri", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-label": "Mais informa\u00E7\u00F5es" } }, ngImport: i0, template: `
3163
+ @if (iconUri()) {
3164
+ <s4y-svg [size]="18" [src]="iconUri()"></s4y-svg>
3165
+ }
3166
+
3167
+ @if (imageUri()) {
3168
+ <img [src]="imageUri()" alt="icon" width="18" height="18" />
3169
+ }
3170
+ <ng-content></ng-content>
3171
+ `, isInline: true, styles: [":host{display:flex;align-items:center;justify-content:flex-start;gap:.8rem;padding:0 .4rem;min-height:4rem;width:100%;&:hover{text-decoration:underline}}\n"], dependencies: [{ kind: "component", type: SvgComponent, selector: "s4y-svg", inputs: ["src", "color", "size"] }] });
3172
+ }
3173
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: MenuItemComponent, decorators: [{
3174
+ type: Component,
3175
+ args: [{ selector: 'button[s4yMenuItem], a[s4yMenuItem]', standalone: true, imports: [SvgComponent], template: `
3176
+ @if (iconUri()) {
3177
+ <s4y-svg [size]="18" [src]="iconUri()"></s4y-svg>
3178
+ }
3179
+
3180
+ @if (imageUri()) {
3181
+ <img [src]="imageUri()" alt="icon" width="18" height="18" />
3182
+ }
3183
+ <ng-content></ng-content>
3184
+ `, host: {
3185
+ 'aria-label': 'Mais informações',
3186
+ }, styles: [":host{display:flex;align-items:center;justify-content:flex-start;gap:.8rem;padding:0 .4rem;min-height:4rem;width:100%;&:hover{text-decoration:underline}}\n"] }]
3187
+ }] });
3188
+
2886
3189
  /*
2887
3190
  * Public API Surface of s4y-components
2888
3191
  */
@@ -2892,5 +3195,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImpo
2892
3195
  * Generated bundle index. Do not edit.
2893
3196
  */
2894
3197
 
2895
- export { AsideComponent, AsideService, AvatarComponent, BreadcrumbComponent, BreadcrumbItemDirective, BreadcrumbService, ButtonComponent, CheckboxComponent, ClickOutsideDirective, DashboardContainerComponent, DashboardLayoutComponent, DashboardModule, DashboardRoutesComponent, DrawerComponent, ErrorMessageComponent, FormFieldComponent, FormFieldPasswordComponent, FormsKitModule, HintComponent, InputComponent, InputPrefixComponent, InputSufixComponent, LabelComponent, LoadingModalComponent, LoadingModalService, MaskDirective, ModalComponent, ModalConfirmationComponent, ModalConfirmationService, NavbarComponent, PaginationComponent, RadioComponent, SearchBarComponent, SelectComponent, SidebarRightComponent, SidebarRightService, SliderComponent, SpinnerComponent, StepComponent, StepPanelComponent, StepperComponent, SvgComponent, SvgService, TableComponent, TableSortDirective, ToastComponent, ToastService, ToggleComponent, TooltipComponent, TooltipDirective, TooltipModule, TooltipPosition, sidebarRightAnimation };
3198
+ export { AsideComponent, AsideService, AvatarComponent, BreadcrumbComponent, BreadcrumbItemDirective, BreadcrumbService, ButtonComponent, CheckboxComponent, ClickOutsideDirective, DashboardContainerComponent, DashboardLayoutComponent, DashboardModule, DashboardRoutesComponent, DrawerComponent, ErrorMessageComponent, FormFieldComponent, FormFieldPasswordComponent, FormsKitModule, HintComponent, InputComponent, InputPrefixComponent, InputSufixComponent, LabelComponent, LoadingModalComponent, LoadingModalService, MaskDirective, MenuComponent, MenuItemComponent, ModalComponent, ModalConfirmationComponent, ModalConfirmationService, NavbarComponent, PaginationComponent, PopoverPanelComponent, PopoverTriggerDirective, RadioComponent, SearchBarComponent, SelectComponent, SidebarRightComponent, SidebarRightService, SliderComponent, SpinnerComponent, StepComponent, StepPanelComponent, StepperComponent, SvgComponent, SvgService, TableComponent, TableSortDirective, ToastComponent, ToastService, ToggleComponent, TooltipComponent, TooltipDirective, TooltipModule, TooltipPosition, modalFadeCombined, sidebarRightAnimation };
2896
3199
  //# sourceMappingURL=s4y-ui.mjs.map