@masterkeymaterial/ui 1.0.0 → 1.0.2

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,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, computed, model, input, output, effect, Component, HostBinding, ChangeDetectionStrategy, viewChild, ElementRef, inject, ViewContainerRef, contentChild, TemplateRef, HostListener, Directive, Injectable, InjectionToken, Injector, Pipe, Optional, Inject } from '@angular/core';
2
+ import { signal, computed, model, input, output, effect, Component, HostBinding, ChangeDetectionStrategy, viewChild, ElementRef, inject, ChangeDetectorRef, ViewContainerRef, contentChild, TemplateRef, HostListener, Directive, Injectable, InjectionToken, Injector, Pipe, Optional, Inject } from '@angular/core';
3
+ import { DomSanitizer } from '@angular/platform-browser';
3
4
  import { OverlayConfig, Overlay } from '@angular/cdk/overlay';
4
- import { TemplatePortal, DomPortal, ComponentPortal } from '@angular/cdk/portal';
5
+ import { TemplatePortal, ComponentPortal } from '@angular/cdk/portal';
5
6
  import { NgTemplateOutlet, NgComponentOutlet } from '@angular/common';
6
7
  import { RouterLink } from '@angular/router';
7
8
  import { ConfigurableFocusTrapFactory } from '@angular/cdk/a11y';
8
- import { DomSanitizer } from '@angular/platform-browser';
9
9
  import * as i1 from '@angular/cdk/drag-drop';
10
10
  import { DragDropModule } from '@angular/cdk/drag-drop';
11
11
 
@@ -3707,6 +3707,7 @@ class UiFilePreview {
3707
3707
  removivel = input(false, /* @ts-ignore */
3708
3708
  ...(ngDevMode ? [{ debugName: "removivel" }] : /* istanbul ignore next */ []));
3709
3709
  remover = output();
3710
+ sanitizer = inject(DomSanitizer);
3710
3711
  tipoDisplay = computed(() => {
3711
3712
  const type = (this.arquivo().type ?? '').toLowerCase();
3712
3713
  const ext = (this.arquivo().extension ?? '').toLowerCase();
@@ -3728,15 +3729,23 @@ class UiFilePreview {
3728
3729
  ...(ngDevMode ? [{ debugName: "isImage" }] : /* istanbul ignore next */ []));
3729
3730
  isPdf = computed(() => this.tipoDisplay() === 'pdf', /* @ts-ignore */
3730
3731
  ...(ngDevMode ? [{ debugName: "isPdf" }] : /* istanbul ignore next */ []));
3732
+ // <embed src> usa SecurityContext.RESOURCE_URL — requer SafeResourceUrl explícito
3733
+ safePdfUrl = computed(() => {
3734
+ const b64 = this.arquivo().base64;
3735
+ if (!b64)
3736
+ return null;
3737
+ return this.sanitizer.bypassSecurityTrustResourceUrl(b64);
3738
+ }, /* @ts-ignore */
3739
+ ...(ngDevMode ? [{ debugName: "safePdfUrl" }] : /* istanbul ignore next */ []));
3731
3740
  onRemover() {
3732
3741
  this.remover.emit(this.arquivo());
3733
3742
  }
3734
3743
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UiFilePreview, deps: [], target: i0.ɵɵFactoryTarget.Component });
3735
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: UiFilePreview, isStandalone: true, selector: "ui-file-preview", inputs: { arquivo: { classPropertyName: "arquivo", publicName: "arquivo", isSignal: true, isRequired: true, transformFunction: null }, removivel: { classPropertyName: "removivel", publicName: "removivel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { remover: "remover" }, ngImport: i0, template: "<div class=\"preview-container\">\n\t@if (isImage()) {\n\t\t<img [src]=\"arquivo().base64\" [alt]=\"arquivo().name\" class=\"preview-img\" />\n\t} @else if (isPdf()) {\n\t\t<embed [src]=\"arquivo().base64\" type=\"application/pdf\" class=\"preview-embed\" />\n\t} @else {\n\t\t<div class=\"preview-other\">\n\t\t\t<ui-icon name=\"file-earmark\"></ui-icon>\n\t\t\t<span class=\"preview-ext\">{{ arquivo().extension.slice(1) }}</span>\n\t\t</div>\n\t}\n\t@if (removivel()) {\n\t\t<button class=\"btn-remover\" (click)=\"onRemover()\" type=\"button\" title=\"Remover\">\n\t\t\t<ui-icon name=\"x\"></ui-icon>\n\t\t</button>\n\t}\n</div>\n", styles: [":host{display:inline-flex;position:relative;height:var(--ui-altura-miniatura, 80px);width:auto;overflow:hidden;border-radius:var(--sys-border-radius, 8px);background-color:var(--sys-primary-15, rgba(0, 0, 0, .06));flex-shrink:0}.preview-container{position:relative;height:100%;display:flex;align-items:center;justify-content:center;overflow:hidden}.preview-img{height:100%;width:auto;object-fit:cover;display:block}.preview-embed{height:100%;width:80px;pointer-events:none}.preview-other{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:8px;gap:4px;min-width:60px;font-size:1.8rem;color:var(--sys-primary, #666)}.preview-ext{font-size:.65rem;color:var(--sys-primary, #666);font-weight:600;text-transform:uppercase}.btn-remover{position:absolute;top:3px;right:3px;width:20px;height:20px;border-radius:50%;border:none;background-color:#0000008c;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;font-size:.8rem;opacity:0;transition:opacity .15s ease;z-index:2;line-height:1}.preview-container:hover .btn-remover{opacity:1}@media(hover:none){.btn-remover{opacity:1}}\n"], dependencies: [{ kind: "component", type: UiIcon, selector: "ui-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3744
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: UiFilePreview, isStandalone: true, selector: "ui-file-preview", inputs: { arquivo: { classPropertyName: "arquivo", publicName: "arquivo", isSignal: true, isRequired: true, transformFunction: null }, removivel: { classPropertyName: "removivel", publicName: "removivel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { remover: "remover" }, ngImport: i0, template: "<div class=\"preview-container\">\n\t@if (isImage()) {\n\t\t<img [src]=\"arquivo().base64\" [alt]=\"arquivo().name\" class=\"preview-img\" />\n\t} @else if (isPdf()) {\n\t\t@if (safePdfUrl()) {\n\t\t\t<embed [src]=\"safePdfUrl()\" type=\"application/pdf\" class=\"preview-embed\" />\n\t\t} @else {\n\t\t\t<div class=\"preview-other\">\n\t\t\t\t<ui-icon name=\"file-earmark\"></ui-icon>\n\t\t\t\t<span class=\"preview-ext\">pdf</span>\n\t\t\t</div>\n\t\t}\n\t} @else {\n\t\t<div class=\"preview-other\">\n\t\t\t<ui-icon name=\"file-earmark\"></ui-icon>\n\t\t\t<span class=\"preview-ext\">{{ arquivo().extension.slice(1) }}</span>\n\t\t</div>\n\t}\n\t@if (removivel()) {\n\t\t<button class=\"btn-remover\" (click)=\"onRemover()\" type=\"button\" title=\"Remover\">\n\t\t\t<ui-icon name=\"x\"></ui-icon>\n\t\t</button>\n\t}\n</div>\n", styles: [":host{display:inline-flex;position:relative;height:var(--ui-altura-miniatura, 80px);width:auto;overflow:hidden;border-radius:var(--sys-border-radius, 8px);background-color:var(--sys-primary-15, rgba(0, 0, 0, .06));flex-shrink:0}.preview-container{position:relative;height:100%;display:flex;align-items:center;justify-content:center;overflow:hidden}.preview-img{height:100%;width:auto;object-fit:cover;display:block}.preview-embed{height:100%;width:80px;pointer-events:none}.preview-other{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:8px;gap:4px;min-width:60px;font-size:1.8rem;color:var(--sys-primary, #666)}.preview-ext{font-size:.65rem;color:var(--sys-primary, #666);font-weight:600;text-transform:uppercase}.btn-remover{position:absolute;top:3px;right:3px;width:20px;height:20px;border-radius:50%;border:none;background-color:#0000008c;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;font-size:.8rem;opacity:0;transition:opacity .15s ease;z-index:2;line-height:1}.preview-container:hover .btn-remover{opacity:1}@media(hover:none){.btn-remover{opacity:1}}\n"], dependencies: [{ kind: "component", type: UiIcon, selector: "ui-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3736
3745
  }
3737
3746
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UiFilePreview, decorators: [{
3738
3747
  type: Component,
3739
- args: [{ selector: 'ui-file-preview', imports: [UiIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"preview-container\">\n\t@if (isImage()) {\n\t\t<img [src]=\"arquivo().base64\" [alt]=\"arquivo().name\" class=\"preview-img\" />\n\t} @else if (isPdf()) {\n\t\t<embed [src]=\"arquivo().base64\" type=\"application/pdf\" class=\"preview-embed\" />\n\t} @else {\n\t\t<div class=\"preview-other\">\n\t\t\t<ui-icon name=\"file-earmark\"></ui-icon>\n\t\t\t<span class=\"preview-ext\">{{ arquivo().extension.slice(1) }}</span>\n\t\t</div>\n\t}\n\t@if (removivel()) {\n\t\t<button class=\"btn-remover\" (click)=\"onRemover()\" type=\"button\" title=\"Remover\">\n\t\t\t<ui-icon name=\"x\"></ui-icon>\n\t\t</button>\n\t}\n</div>\n", styles: [":host{display:inline-flex;position:relative;height:var(--ui-altura-miniatura, 80px);width:auto;overflow:hidden;border-radius:var(--sys-border-radius, 8px);background-color:var(--sys-primary-15, rgba(0, 0, 0, .06));flex-shrink:0}.preview-container{position:relative;height:100%;display:flex;align-items:center;justify-content:center;overflow:hidden}.preview-img{height:100%;width:auto;object-fit:cover;display:block}.preview-embed{height:100%;width:80px;pointer-events:none}.preview-other{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:8px;gap:4px;min-width:60px;font-size:1.8rem;color:var(--sys-primary, #666)}.preview-ext{font-size:.65rem;color:var(--sys-primary, #666);font-weight:600;text-transform:uppercase}.btn-remover{position:absolute;top:3px;right:3px;width:20px;height:20px;border-radius:50%;border:none;background-color:#0000008c;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;font-size:.8rem;opacity:0;transition:opacity .15s ease;z-index:2;line-height:1}.preview-container:hover .btn-remover{opacity:1}@media(hover:none){.btn-remover{opacity:1}}\n"] }]
3748
+ args: [{ selector: 'ui-file-preview', imports: [UiIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"preview-container\">\n\t@if (isImage()) {\n\t\t<img [src]=\"arquivo().base64\" [alt]=\"arquivo().name\" class=\"preview-img\" />\n\t} @else if (isPdf()) {\n\t\t@if (safePdfUrl()) {\n\t\t\t<embed [src]=\"safePdfUrl()\" type=\"application/pdf\" class=\"preview-embed\" />\n\t\t} @else {\n\t\t\t<div class=\"preview-other\">\n\t\t\t\t<ui-icon name=\"file-earmark\"></ui-icon>\n\t\t\t\t<span class=\"preview-ext\">pdf</span>\n\t\t\t</div>\n\t\t}\n\t} @else {\n\t\t<div class=\"preview-other\">\n\t\t\t<ui-icon name=\"file-earmark\"></ui-icon>\n\t\t\t<span class=\"preview-ext\">{{ arquivo().extension.slice(1) }}</span>\n\t\t</div>\n\t}\n\t@if (removivel()) {\n\t\t<button class=\"btn-remover\" (click)=\"onRemover()\" type=\"button\" title=\"Remover\">\n\t\t\t<ui-icon name=\"x\"></ui-icon>\n\t\t</button>\n\t}\n</div>\n", styles: [":host{display:inline-flex;position:relative;height:var(--ui-altura-miniatura, 80px);width:auto;overflow:hidden;border-radius:var(--sys-border-radius, 8px);background-color:var(--sys-primary-15, rgba(0, 0, 0, .06));flex-shrink:0}.preview-container{position:relative;height:100%;display:flex;align-items:center;justify-content:center;overflow:hidden}.preview-img{height:100%;width:auto;object-fit:cover;display:block}.preview-embed{height:100%;width:80px;pointer-events:none}.preview-other{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:8px;gap:4px;min-width:60px;font-size:1.8rem;color:var(--sys-primary, #666)}.preview-ext{font-size:.65rem;color:var(--sys-primary, #666);font-weight:600;text-transform:uppercase}.btn-remover{position:absolute;top:3px;right:3px;width:20px;height:20px;border-radius:50%;border:none;background-color:#0000008c;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;font-size:.8rem;opacity:0;transition:opacity .15s ease;z-index:2;line-height:1}.preview-container:hover .btn-remover{opacity:1}@media(hover:none){.btn-remover{opacity:1}}\n"] }]
3740
3749
  }], propDecorators: { arquivo: [{ type: i0.Input, args: [{ isSignal: true, alias: "arquivo", required: true }] }], removivel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removivel", required: false }] }], remover: [{ type: i0.Output, args: ["remover"] }] } });
3741
3750
 
3742
3751
  class UiMicroGallery {
@@ -3768,6 +3777,14 @@ class UiArquivos {
3768
3777
  ...(ngDevMode ? [{ debugName: "fileInput" }] : /* istanbul ignore next */ []));
3769
3778
  temArquivos = computed(() => this.arquivos().length > 0, /* @ts-ignore */
3770
3779
  ...(ngDevMode ? [{ debugName: "temArquivos" }] : /* istanbul ignore next */ []));
3780
+ _cdr = inject(ChangeDetectorRef);
3781
+ constructor() {
3782
+ // Garante que o OnPush re-renderiza quando arquivos muda (ex.: input inicial do pai)
3783
+ effect(() => {
3784
+ this.arquivos();
3785
+ this._cdr.markForCheck();
3786
+ });
3787
+ }
3771
3788
  onDropChanged(dropOutput) {
3772
3789
  if (dropOutput.tipo === 'file' && Array.isArray(dropOutput.data)) {
3773
3790
  this.arquivos.set(dropOutput.data);
@@ -3816,7 +3833,7 @@ class UiArquivos {
3816
3833
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UiArquivos, decorators: [{
3817
3834
  type: Component,
3818
3835
  args: [{ selector: 'ui-arquivos', imports: [UiDropZone, UiMicroGallery], changeDetection: ChangeDetectionStrategy.OnPush, template: "<input #fileInput type=\"file\" class=\"file-input-hidden\"\n\t[accept]=\"accept()\" [multiple]=\"multiple()\" [disabled]=\"disabled()\"\n\t(change)=\"onFileInputChange($event)\" />\n\n<ui-drop-zone [sobrepor]=\"temArquivos()\" [disabled]=\"disabled()\"\n\t(changed)=\"onDropChanged($event)\" (clicked)=\"onDropClicked()\">\n\t@if (temArquivos()) {\n\t\t<ui-micro-gallery [arquivos]=\"arquivos()\" (remover)=\"onRemover($event)\">\n\t\t</ui-micro-gallery>\n\t}\n</ui-drop-zone>\n", styles: [":host{display:flex;flex:1;min-height:var(--ui-min-height, 200px);min-width:var(--ui-min-width, 200px)}.file-input-hidden{display:none}\n"] }]
3819
- }], propDecorators: { arquivos: [{ type: i0.Input, args: [{ isSignal: true, alias: "arquivos", required: false }] }, { type: i0.Output, args: ["arquivosChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }], fileInput: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }] } });
3836
+ }], ctorParameters: () => [], propDecorators: { arquivos: [{ type: i0.Input, args: [{ isSignal: true, alias: "arquivos", required: false }] }, { type: i0.Output, args: ["arquivosChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }], fileInput: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }] } });
3820
3837
 
3821
3838
  /**
3822
3839
  * Cria um OverlayRef conectado a um elemento trigger com FlexibleConnectedPositionStrategy.
@@ -4484,6 +4501,13 @@ class UiMenu {
4484
4501
  const closestTrigger = target.closest('.e-menu-trigger[id]');
4485
4502
  const isOwnTrigger = closestTrigger === this.menuTrigger()?.nativeElement;
4486
4503
  if (closestTrigger && !isOwnTrigger) {
4504
+ // Fechar submenus irmãos que estejam abertos antes de abrir o clicado
4505
+ const container = event.currentTarget;
4506
+ container.querySelectorAll('.e-menu-trigger.open').forEach(openTrigger => {
4507
+ if (openTrigger !== closestTrigger) {
4508
+ openTrigger.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape', bubbles: false }));
4509
+ }
4510
+ });
4487
4511
  // Um trigger de submenu filho foi clicado — não fechar ainda, aguardar o filho fechar
4488
4512
  if (this.autoCloseInCascade()) {
4489
4513
  closestTrigger.addEventListener('menu-closed', () => this.closeOverlay(), { once: true });
@@ -4875,6 +4899,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
4875
4899
  args: [{ selector: 'ui-pagination', imports: [UiIcon], template: "<div class=\"pagination\">\n\t<div class=\"pagination-info\">\n\t\t<select class=\"pg-tamanho\" (change)=\"mudarTamanho($event)\">\n\t\t\t@for(op of opcoesTamanho(); track op) {\n\t\t\t<option [value]=\"op\" [selected]=\"op === tamanhoPagina()\">{{ op }} / p\u00E1g.</option>\n\t\t\t}\n\t\t</select>\n\t\t<span class=\"pg-total\">{{ total() }} itens</span>\n\t</div>\n\n\t<div class=\"pagination-controles\">\n\t\t<button class=\"pg-btn\" type=\"button\" (click)=\"irPara(1)\" [disabled]=\"pagina() === 1\" title=\"Primeira\">\n\t\t\t<ui-icon name=\"chevron-double-left\"></ui-icon>\n\t\t</button>\n\t\t<button class=\"pg-btn\" type=\"button\" (click)=\"irPara(pagina() - 1)\" [disabled]=\"pagina() === 1\" title=\"Anterior\">\n\t\t\t<ui-icon name=\"chevron-left\"></ui-icon>\n\t\t</button>\n\n\t\t@for(p of paginasVisiveis(); track $index) {\n\t\t@if(p === '...') {\n\t\t<span class=\"pg-ellipsis\">\u2026</span>\n\t\t} @else {\n\t\t<button class=\"pg-btn pg-num\" type=\"button\" [class.ativo]=\"pagina() === p\" (click)=\"irPara(+p)\">{{ p }}</button>\n\t\t}\n\t\t}\n\n\t\t<button class=\"pg-btn\" type=\"button\" (click)=\"irPara(pagina() + 1)\" [disabled]=\"pagina() === totalPaginas()\"\n\t\t\ttitle=\"Pr\u00F3xima\">\n\t\t\t<ui-icon name=\"chevron-right\"></ui-icon>\n\t\t</button>\n\t\t<button class=\"pg-btn\" type=\"button\" (click)=\"irPara(totalPaginas())\" [disabled]=\"pagina() === totalPaginas()\"\n\t\t\ttitle=\"\u00DAltima\">\n\t\t\t<ui-icon name=\"chevron-double-right\"></ui-icon>\n\t\t</button>\n\t</div>\n</div>", styles: [":host{display:block}.pagination{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px;padding:8px 0;font-size:.875em}.pagination-info{display:flex;align-items:center;gap:12px}.pg-tamanho{border:1px solid var(--sys-outline, #ccc);background:var(--sys-surface, #fff);border-radius:var(--sys-border-radius, 6px);padding:4px 8px;font-size:inherit;color:inherit;cursor:pointer}.pg-total{opacity:.55}.pagination-controles{display:flex;align-items:center;gap:2px}.pg-btn{min-width:32px;height:32px;padding:0 8px;border:1px solid var(--sys-outline, #ccc);background:var(--sys-surface, #fff);border-radius:var(--sys-border-radius, 6px);cursor:pointer;font-size:.875em;color:inherit;display:inline-flex;align-items:center;justify-content:center;transition:background .15s,color .15s}.pg-btn:hover:not(:disabled){background:var(--sys-surface-variant, rgba(0, 0, 0, .05))}.pg-btn:disabled{opacity:.35;cursor:not-allowed}.pg-btn.ativo{background:var(--sys-primary);color:var(--sys-on-primary, #fff);border-color:var(--sys-primary);font-weight:700}.pg-ellipsis{min-width:32px;height:32px;display:inline-flex;align-items:center;justify-content:center;opacity:.4}\n"] }]
4876
4900
  }], propDecorators: { total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: false }] }], pagina: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagina", required: false }] }, { type: i0.Output, args: ["paginaChange"] }], tamanhoPagina: [{ type: i0.Input, args: [{ isSignal: true, alias: "tamanhoPagina", required: false }] }, { type: i0.Output, args: ["tamanhoPaginaChange"] }], opcoesTamanho: [{ type: i0.Input, args: [{ isSignal: true, alias: "opcoesTamanho", required: false }] }], pageChanged: [{ type: i0.Output, args: ["pageChanged"] }] } });
4877
4901
 
4902
+ /** Componente interno — não exportar via public-api.ts */
4903
+ class UiTooltipBubble {
4904
+ texto = input('', /* @ts-ignore */
4905
+ ...(ngDevMode ? [{ debugName: "texto" }] : /* istanbul ignore next */ []));
4906
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UiTooltipBubble, deps: [], target: i0.ɵɵFactoryTarget.Component });
4907
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.1", type: UiTooltipBubble, isStandalone: true, selector: "ui-tooltip-bubble", inputs: { texto: { classPropertyName: "texto", publicName: "texto", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ui-tooltip-bubble" }, ngImport: i0, template: `{{ texto() }}`, isInline: true, styles: [":host{display:block;pointer-events:none;background:var(--sys-tooltip-bg, rgba(30, 30, 30, .9));color:var(--sys-tooltip-color, #fff);font-size:12px;font-weight:500;padding:5px 10px;border-radius:5px;white-space:normal;max-width:260px;box-shadow:0 2px 8px #0003;opacity:0;transition:opacity .15s ease}:host.visible{opacity:1}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4908
+ }
4909
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UiTooltipBubble, decorators: [{
4910
+ type: Component,
4911
+ args: [{ selector: 'ui-tooltip-bubble', host: { class: 'ui-tooltip-bubble' }, template: `{{ texto() }}`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;pointer-events:none;background:var(--sys-tooltip-bg, rgba(30, 30, 30, .9));color:var(--sys-tooltip-color, #fff);font-size:12px;font-weight:500;padding:5px 10px;border-radius:5px;white-space:normal;max-width:260px;box-shadow:0 2px 8px #0003;opacity:0;transition:opacity .15s ease}:host.visible{opacity:1}\n"] }]
4912
+ }], propDecorators: { texto: [{ type: i0.Input, args: [{ isSignal: true, alias: "texto", required: false }] }] } });
4913
+
4878
4914
  class UiTooltip {
4879
4915
  uiTooltip = input('', /* @ts-ignore */
4880
4916
  ...(ngDevMode ? [{ debugName: "uiTooltip" }] : /* istanbul ignore next */ []));
@@ -4897,12 +4933,9 @@ class UiTooltip {
4897
4933
  scrollStrategy: this.overlay.scrollStrategies.reposition(),
4898
4934
  panelClass: 'ui-tooltip-panel',
4899
4935
  });
4900
- const tooltipEl = document.createElement('div');
4901
- tooltipEl.className = 'ui-tooltip-bubble';
4902
- tooltipEl.textContent = this.uiTooltip();
4903
- document.body.appendChild(tooltipEl);
4904
- this.overlayRef.attach(new DomPortal(tooltipEl));
4905
- requestAnimationFrame(() => tooltipEl.classList.add('visible'));
4936
+ const ref = this.overlayRef.attach(new ComponentPortal(UiTooltipBubble));
4937
+ ref.setInput('texto', this.uiTooltip());
4938
+ requestAnimationFrame(() => ref.location.nativeElement.classList.add('visible'));
4906
4939
  }
4907
4940
  hide() {
4908
4941
  this.overlayRef?.dispose();
@@ -5007,14 +5040,14 @@ class UiModalBox {
5007
5040
  this.data.close();
5008
5041
  }
5009
5042
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UiModalBox, deps: [], target: i0.ɵɵFactoryTarget.Component });
5010
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: UiModalBox, isStandalone: true, selector: "ui-modal-box", host: { attributes: { "role": "dialog", "aria-modal": "true" } }, ngImport: i0, template: "<div class=\"modal-box\" [attr.data-tamanho]=\"config.tamanho ?? 'md'\">\n\n\t@if(config.titulo || config.closeable !== false) {\n\t<div class=\"modal-header\">\n\t\t@if(config.titulo) { <h2 class=\"modal-titulo\">{{ config.titulo }}</h2> }\n\t\t@if(config.closeable !== false) {\n\t\t<button class=\"modal-close\" type=\"button\" (click)=\"fechar()\" aria-label=\"Fechar\">\n\t\t\t<ui-icon name=\"x-lg\"></ui-icon>\n\t\t</button>\n\t\t}\n\t</div>\n\t}\n\n\t@if(config.mensagem) {\n\t<div class=\"modal-body\">\n\t\t<p>{{ config.mensagem }}</p>\n\t</div>\n\t}\n\n\t@if(conteudoComponent) {\n\t<div class=\"modal-body\">\n\t\t<ng-container *ngComponentOutlet=\"conteudoComponent\"></ng-container>\n\t</div>\n\t}\n\n\t@if(conteudoTemplate) {\n\t<div class=\"modal-body\">\n\t\t<ng-container *ngTemplateOutlet=\"conteudoTemplate\"></ng-container>\n\t</div>\n\t}\n\n\t@if(config.acoes && config.acoes.length > 0) {\n\t<div class=\"modal-footer\">\n\t\t@for(acao of config.acoes; track $index) {\n\t\t<ui-button [tema]=\"acao.tema\" tipo=\"fill\"\n\t\t\t(clicked)=\"acao.callback && acao.callback(); fechar()\">\n\t\t\t{{ acao.label }}\n\t\t</ui-button>\n\t\t}\n\t</div>\n\t}\n\n</div>\n", styles: [":host{display:none}.ui-modal-panel{padding:16px;box-sizing:border-box;max-height:90vh;display:flex;align-items:center;justify-content:center}.cdk-overlay-dark-backdrop{background:#00000073;animation:overlay-in .2s ease}@keyframes overlay-in{0%{opacity:0}to{opacity:1}}.modal-box{background:var(--sys-surface, #fff);border-radius:var(--sys-border-radius, 12px);box-shadow:0 8px 40px #00000040;display:flex;flex-direction:column;overflow:hidden;animation:box-in .2s ease;max-height:90vh;width:100%}@keyframes box-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.modal-box[data-tamanho=sm]{max-width:360px}.modal-box[data-tamanho=md]{max-width:520px}.modal-box[data-tamanho=lg]{max-width:720px}.modal-box[data-tamanho=xl]{max-width:960px}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px 12px;border-bottom:1px solid var(--sys-outline, #eee)}.modal-titulo{margin:0;font-size:1.1em;font-weight:600}.modal-close{background:none;border:none;cursor:pointer;font-size:18px;padding:4px;opacity:.55;color:inherit;line-height:1;border-radius:4px;transition:opacity .15s}.modal-close:hover{opacity:1}.modal-body{padding:20px;overflow-y:auto;flex:1}.modal-body p{margin:0;line-height:1.6}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 20px;border-top:1px solid var(--sys-outline, #eee)}\n"], dependencies: [{ kind: "component", type: UiButton, selector: "ui-button", inputs: ["icone", "iconeNome", "iconeAntes", "iconeDepois", "iconeCategory", "disabled", "eventPropagation", "radiusTabFormat", "tabindex", "tipo", "tema", "classes", "ativo"], outputs: ["iconeChange", "iconeAntesChange", "iconeDepoisChange", "iconeCategoryChange", "clicked", "temaChange"] }, { kind: "component", type: UiIcon, selector: "ui-icon", inputs: ["name"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
5043
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: UiModalBox, isStandalone: true, selector: "ui-modal-box", host: { attributes: { "role": "dialog", "aria-modal": "true" } }, ngImport: i0, template: "<div class=\"modal-box\" [attr.data-tamanho]=\"config.tamanho ?? 'md'\">\n\n\t@if(config.titulo || config.closeable !== false) {\n\t<div class=\"modal-header\">\n\t\t@if(config.titulo) { <h2 class=\"modal-titulo\">{{ config.titulo }}</h2> }\n\t\t@if(config.closeable !== false) {\n\t\t<button class=\"modal-close\" type=\"button\" (click)=\"fechar()\" aria-label=\"Fechar\">\n\t\t\t<ui-icon name=\"x-lg\"></ui-icon>\n\t\t</button>\n\t\t}\n\t</div>\n\t}\n\n\t@if(config.mensagem) {\n\t<div class=\"modal-body\">\n\t\t<p>{{ config.mensagem }}</p>\n\t</div>\n\t}\n\n\t@if(conteudoComponent) {\n\t<div class=\"modal-body\">\n\t\t<ng-container *ngComponentOutlet=\"conteudoComponent\"></ng-container>\n\t</div>\n\t}\n\n\t@if(conteudoTemplate) {\n\t<div class=\"modal-body\">\n\t\t<ng-container *ngTemplateOutlet=\"conteudoTemplate\"></ng-container>\n\t</div>\n\t}\n\n\t@if(config.acoes && config.acoes.length > 0) {\n\t<div class=\"modal-footer\">\n\t\t@for(acao of config.acoes; track $index) {\n\t\t<ui-button [tema]=\"acao.tema\" tipo=\"fill\"\n\t\t\t(clicked)=\"acao.callback && acao.callback(); fechar()\">\n\t\t\t{{ acao.label }}\n\t\t</ui-button>\n\t\t}\n\t</div>\n\t}\n\n</div>\n", styles: [".ui-modal-panel{padding:16px;box-sizing:border-box;max-height:90vh;display:flex;align-items:center;justify-content:center}.cdk-overlay-dark-backdrop{background:#00000073;animation:overlay-in .2s ease}@keyframes overlay-in{0%{opacity:0}to{opacity:1}}.modal-box{background:var(--sys-surface, #fff);border-radius:var(--sys-border-radius, 12px);box-shadow:0 8px 40px #00000040;display:flex;flex-direction:column;overflow:hidden;animation:box-in .2s ease;max-height:90vh;width:100%}@keyframes box-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.modal-box[data-tamanho=sm]{max-width:360px}.modal-box[data-tamanho=md]{max-width:520px}.modal-box[data-tamanho=lg]{max-width:720px}.modal-box[data-tamanho=xl]{max-width:960px}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px 12px;border-bottom:1px solid var(--sys-outline, #eee)}.modal-titulo{margin:0;font-size:1.1em;font-weight:600}.modal-close{background:none;border:none;cursor:pointer;font-size:18px;padding:4px;opacity:.55;color:inherit;line-height:1;border-radius:4px;transition:opacity .15s}.modal-close:hover{opacity:1}.modal-body{padding:20px;overflow-y:auto;flex:1}.modal-body p{margin:0;line-height:1.6}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 20px;border-top:1px solid var(--sys-outline, #eee)}\n"], dependencies: [{ kind: "component", type: UiButton, selector: "ui-button", inputs: ["icone", "iconeNome", "iconeAntes", "iconeDepois", "iconeCategory", "disabled", "eventPropagation", "radiusTabFormat", "tabindex", "tipo", "tema", "classes", "ativo"], outputs: ["iconeChange", "iconeAntesChange", "iconeDepoisChange", "iconeCategoryChange", "clicked", "temaChange"] }, { kind: "component", type: UiIcon, selector: "ui-icon", inputs: ["name"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
5011
5044
  }
5012
5045
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UiModalBox, decorators: [{
5013
5046
  type: Component,
5014
5047
  args: [{ selector: 'ui-modal-box', imports: [UiButton, UiIcon, NgComponentOutlet, NgTemplateOutlet], host: {
5015
5048
  'role': 'dialog',
5016
5049
  'aria-modal': 'true',
5017
- }, template: "<div class=\"modal-box\" [attr.data-tamanho]=\"config.tamanho ?? 'md'\">\n\n\t@if(config.titulo || config.closeable !== false) {\n\t<div class=\"modal-header\">\n\t\t@if(config.titulo) { <h2 class=\"modal-titulo\">{{ config.titulo }}</h2> }\n\t\t@if(config.closeable !== false) {\n\t\t<button class=\"modal-close\" type=\"button\" (click)=\"fechar()\" aria-label=\"Fechar\">\n\t\t\t<ui-icon name=\"x-lg\"></ui-icon>\n\t\t</button>\n\t\t}\n\t</div>\n\t}\n\n\t@if(config.mensagem) {\n\t<div class=\"modal-body\">\n\t\t<p>{{ config.mensagem }}</p>\n\t</div>\n\t}\n\n\t@if(conteudoComponent) {\n\t<div class=\"modal-body\">\n\t\t<ng-container *ngComponentOutlet=\"conteudoComponent\"></ng-container>\n\t</div>\n\t}\n\n\t@if(conteudoTemplate) {\n\t<div class=\"modal-body\">\n\t\t<ng-container *ngTemplateOutlet=\"conteudoTemplate\"></ng-container>\n\t</div>\n\t}\n\n\t@if(config.acoes && config.acoes.length > 0) {\n\t<div class=\"modal-footer\">\n\t\t@for(acao of config.acoes; track $index) {\n\t\t<ui-button [tema]=\"acao.tema\" tipo=\"fill\"\n\t\t\t(clicked)=\"acao.callback && acao.callback(); fechar()\">\n\t\t\t{{ acao.label }}\n\t\t</ui-button>\n\t\t}\n\t</div>\n\t}\n\n</div>\n", styles: [":host{display:none}.ui-modal-panel{padding:16px;box-sizing:border-box;max-height:90vh;display:flex;align-items:center;justify-content:center}.cdk-overlay-dark-backdrop{background:#00000073;animation:overlay-in .2s ease}@keyframes overlay-in{0%{opacity:0}to{opacity:1}}.modal-box{background:var(--sys-surface, #fff);border-radius:var(--sys-border-radius, 12px);box-shadow:0 8px 40px #00000040;display:flex;flex-direction:column;overflow:hidden;animation:box-in .2s ease;max-height:90vh;width:100%}@keyframes box-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.modal-box[data-tamanho=sm]{max-width:360px}.modal-box[data-tamanho=md]{max-width:520px}.modal-box[data-tamanho=lg]{max-width:720px}.modal-box[data-tamanho=xl]{max-width:960px}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px 12px;border-bottom:1px solid var(--sys-outline, #eee)}.modal-titulo{margin:0;font-size:1.1em;font-weight:600}.modal-close{background:none;border:none;cursor:pointer;font-size:18px;padding:4px;opacity:.55;color:inherit;line-height:1;border-radius:4px;transition:opacity .15s}.modal-close:hover{opacity:1}.modal-body{padding:20px;overflow-y:auto;flex:1}.modal-body p{margin:0;line-height:1.6}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 20px;border-top:1px solid var(--sys-outline, #eee)}\n"] }]
5050
+ }, template: "<div class=\"modal-box\" [attr.data-tamanho]=\"config.tamanho ?? 'md'\">\n\n\t@if(config.titulo || config.closeable !== false) {\n\t<div class=\"modal-header\">\n\t\t@if(config.titulo) { <h2 class=\"modal-titulo\">{{ config.titulo }}</h2> }\n\t\t@if(config.closeable !== false) {\n\t\t<button class=\"modal-close\" type=\"button\" (click)=\"fechar()\" aria-label=\"Fechar\">\n\t\t\t<ui-icon name=\"x-lg\"></ui-icon>\n\t\t</button>\n\t\t}\n\t</div>\n\t}\n\n\t@if(config.mensagem) {\n\t<div class=\"modal-body\">\n\t\t<p>{{ config.mensagem }}</p>\n\t</div>\n\t}\n\n\t@if(conteudoComponent) {\n\t<div class=\"modal-body\">\n\t\t<ng-container *ngComponentOutlet=\"conteudoComponent\"></ng-container>\n\t</div>\n\t}\n\n\t@if(conteudoTemplate) {\n\t<div class=\"modal-body\">\n\t\t<ng-container *ngTemplateOutlet=\"conteudoTemplate\"></ng-container>\n\t</div>\n\t}\n\n\t@if(config.acoes && config.acoes.length > 0) {\n\t<div class=\"modal-footer\">\n\t\t@for(acao of config.acoes; track $index) {\n\t\t<ui-button [tema]=\"acao.tema\" tipo=\"fill\"\n\t\t\t(clicked)=\"acao.callback && acao.callback(); fechar()\">\n\t\t\t{{ acao.label }}\n\t\t</ui-button>\n\t\t}\n\t</div>\n\t}\n\n</div>\n", styles: [".ui-modal-panel{padding:16px;box-sizing:border-box;max-height:90vh;display:flex;align-items:center;justify-content:center}.cdk-overlay-dark-backdrop{background:#00000073;animation:overlay-in .2s ease}@keyframes overlay-in{0%{opacity:0}to{opacity:1}}.modal-box{background:var(--sys-surface, #fff);border-radius:var(--sys-border-radius, 12px);box-shadow:0 8px 40px #00000040;display:flex;flex-direction:column;overflow:hidden;animation:box-in .2s ease;max-height:90vh;width:100%}@keyframes box-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.modal-box[data-tamanho=sm]{max-width:360px}.modal-box[data-tamanho=md]{max-width:520px}.modal-box[data-tamanho=lg]{max-width:720px}.modal-box[data-tamanho=xl]{max-width:960px}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px 12px;border-bottom:1px solid var(--sys-outline, #eee)}.modal-titulo{margin:0;font-size:1.1em;font-weight:600}.modal-close{background:none;border:none;cursor:pointer;font-size:18px;padding:4px;opacity:.55;color:inherit;line-height:1;border-radius:4px;transition:opacity .15s}.modal-close:hover{opacity:1}.modal-body{padding:20px;overflow-y:auto;flex:1}.modal-body p{margin:0;line-height:1.6}.modal-footer{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 20px;border-top:1px solid var(--sys-outline, #eee)}\n"] }]
5018
5051
  }] });
5019
5052
 
5020
5053
  class UiModalService {
@@ -5185,6 +5218,60 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
5185
5218
  }, imports: [UiIcon], template: "<div class=\"rating\" (mouseleave)=\"onMouseLeave()\">\n\t@for(i of estrelas(); track i) {\n\t<button class=\"estrela\" type=\"button\" [class.full]=\"pontuacaoEstrela(i) === 'full'\"\n\t\t[class.half]=\"pontuacaoEstrela(i) === 'half'\" [disabled]=\"readonly()\" (mousemove)=\"onMouseMove($event, i)\"\n\t\t(click)=\"selecionar(i, $event)\" [attr.aria-label]=\"'Avaliar ' + i + ' de ' + max()\">\n\t\t<ui-icon name=\"star-fill\" class=\"icone-fundo\"></ui-icon>\n\t\t<ui-icon name=\"star-fill\" class=\"icone-frente\"></ui-icon>\n\t</button>\n\t}\n</div>", styles: [":host{display:inline-flex}.rating{display:flex;align-items:center;gap:2px}.estrela{background:none;border:none;cursor:pointer;padding:2px;position:relative;font-size:24px;color:var(--sys-warning, #f5c518);line-height:1;overflow:hidden;display:inline-block}:host(.readonly) .estrela{cursor:default}.icone-fundo{opacity:.2}.icone-frente{position:absolute;left:2px;top:2px;width:0%;overflow:hidden;white-space:nowrap;transition:width .1s}.estrela.full .icone-frente{width:100%}.estrela.half .icone-frente{width:50%}.estrela.empty .icone-frente{width:0%}\n"] }]
5186
5219
  }], propDecorators: { valor: [{ type: i0.Input, args: [{ isSignal: true, alias: "valor", required: false }] }, { type: i0.Output, args: ["valorChange"] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], meiaPasso: [{ type: i0.Input, args: [{ isSignal: true, alias: "meiaPasso", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
5187
5220
 
5221
+ const UI_TREE_CTX = new InjectionToken('UI_TREE_CTX');
5222
+
5223
+ class UiTreeNo {
5224
+ no = input.required(/* @ts-ignore */
5225
+ ...(ngDevMode ? [{ debugName: "no" }] : /* istanbul ignore next */ []));
5226
+ nivel = input(0, /* @ts-ignore */
5227
+ ...(ngDevMode ? [{ debugName: "nivel" }] : /* istanbul ignore next */ []));
5228
+ ctx = inject(UI_TREE_CTX);
5229
+ ehCategoria = computed(() => this.no().filhos !== undefined, /* @ts-ignore */
5230
+ ...(ngDevMode ? [{ debugName: "ehCategoria" }] : /* istanbul ignore next */ []));
5231
+ eExpandido = computed(() => this.ctx.isExpandido(this.no().id), /* @ts-ignore */
5232
+ ...(ngDevMode ? [{ debugName: "eExpandido" }] : /* istanbul ignore next */ []));
5233
+ eSelecionado = computed(() => this.ctx.isSelecionado(this.no().id), /* @ts-ignore */
5234
+ ...(ngDevMode ? [{ debugName: "eSelecionado" }] : /* istanbul ignore next */ []));
5235
+ eIndeterminado = computed(() => {
5236
+ if (!this.ehCategoria())
5237
+ return false;
5238
+ const todos = this.ctx.coletarTodosFilhos(this.no());
5239
+ if (!todos.length)
5240
+ return false;
5241
+ const sel = todos.filter(id => this.ctx.isSelecionado(id)).length;
5242
+ return sel > 0 && sel < todos.length;
5243
+ }, /* @ts-ignore */
5244
+ ...(ngDevMode ? [{ debugName: "eIndeterminado" }] : /* istanbul ignore next */ []));
5245
+ onClickRow() {
5246
+ const no = this.no();
5247
+ if (no.desabilitado)
5248
+ return;
5249
+ if (this.ehCategoria()) {
5250
+ this.ctx.toggleExpandir(no);
5251
+ if (!this.ctx.multiplo()) {
5252
+ this.ctx.toggleSelecionar(no);
5253
+ }
5254
+ }
5255
+ else {
5256
+ this.ctx.toggleSelecionar(no);
5257
+ }
5258
+ }
5259
+ onCheckChanged(valor) {
5260
+ if (valor) {
5261
+ this.ctx.selecionarTodos(this.no());
5262
+ }
5263
+ else {
5264
+ this.ctx.desselecionarTodos(this.no());
5265
+ }
5266
+ }
5267
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UiTreeNo, deps: [], target: i0.ɵɵFactoryTarget.Component });
5268
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: UiTreeNo, isStandalone: true, selector: "ui-tree-no", inputs: { no: { classPropertyName: "no", publicName: "no", isSignal: true, isRequired: true, transformFunction: null }, nivel: { classPropertyName: "nivel", publicName: "nivel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<li class=\"tree-no\" [class.desabilitado]=\"no().desabilitado\">\n\t<div class=\"tree-row\" [class.selecionado]=\"eSelecionado()\" (click)=\"onClickRow()\">\n\t\t@if (ehCategoria()) {\n\t\t\t<button class=\"tree-toggle\" type=\"button\"\n\t\t\t\t(click)=\"$event.stopPropagation(); ctx.toggleExpandir(no())\"\n\t\t\t\t[attr.aria-expanded]=\"eExpandido()\">\n\t\t\t\t<ui-icon [name]=\"eExpandido() ? 'chevron-down' : 'chevron-right'\" />\n\t\t\t</button>\n\t\t} @else {\n\t\t\t<span class=\"tree-toggle-space\"></span>\n\t\t}\n\t\t@if (ctx.multiplo() && ehCategoria()) {\n\t\t\t<ui-check-box\n\t\t\t\t[value]=\"eSelecionado()\"\n\t\t\t\t[hasDash]=\"eIndeterminado()\"\n\t\t\t\t[disabled]=\"no().desabilitado\"\n\t\t\t\t(click)=\"$event.stopPropagation()\"\n\t\t\t\t(changed)=\"onCheckChanged($event)\"\n\t\t\t/>\n\t\t}\n\t\t@if (no().icone) {\n\t\t\t<i class=\"tree-icone\" [class]=\"no().icone\"></i>\n\t\t}\n\t\t<span class=\"tree-label\">{{ no().label }}</span>\n\t</div>\n\t@if (ehCategoria() && eExpandido()) {\n\t\t<ul class=\"tree-list tree-filhos\">\n\t\t\t@for (filho of no().filhos!; track filho.id) {\n\t\t\t\t<ui-tree-no [no]=\"filho\" [nivel]=\"nivel() + 1\" />\n\t\t\t}\n\t\t</ul>\n\t}\n</li>\n", styles: [":host{display:contents}.tree-list{list-style:none;margin:0;padding:0}.tree-filhos{padding-left:20px}.tree-no{-webkit-user-select:none;user-select:none}.tree-no.desabilitado{opacity:.4;pointer-events:none}.tree-row{display:flex;align-items:center;gap:6px;padding:5px 8px;border-radius:var(--sys-border-radius, 6px);cursor:pointer;transition:background .12s;font-size:.9em;--ui-size: 16px}.tree-row:hover{background:var(--sys-surface-variant, rgba(0, 0, 0, .05))}.tree-row.selecionado{background:color-mix(in srgb,var(--sys-primary) 12%,transparent);color:var(--sys-primary);font-weight:500}.tree-toggle{background:none;border:none;cursor:pointer;padding:0;color:inherit;opacity:.5;width:16px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.tree-toggle:hover{opacity:1}.tree-toggle-space{width:16px;flex-shrink:0}.tree-icone{font-size:14px;opacity:.6;flex-shrink:0}.tree-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"], dependencies: [{ kind: "component", type: UiTreeNo, selector: "ui-tree-no", inputs: ["no", "nivel"] }, { kind: "component", type: UiCheckBox, selector: "ui-check-box", inputs: ["value", "disabled", "focused", "focus", "single", "hasDash"], outputs: ["valueChange", "focusedChange", "changed"] }, { kind: "component", type: UiIcon, selector: "ui-icon", inputs: ["name"] }] });
5269
+ }
5270
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UiTreeNo, decorators: [{
5271
+ type: Component,
5272
+ args: [{ selector: 'ui-tree-no', imports: [UiTreeNo, UiCheckBox, UiIcon], template: "<li class=\"tree-no\" [class.desabilitado]=\"no().desabilitado\">\n\t<div class=\"tree-row\" [class.selecionado]=\"eSelecionado()\" (click)=\"onClickRow()\">\n\t\t@if (ehCategoria()) {\n\t\t\t<button class=\"tree-toggle\" type=\"button\"\n\t\t\t\t(click)=\"$event.stopPropagation(); ctx.toggleExpandir(no())\"\n\t\t\t\t[attr.aria-expanded]=\"eExpandido()\">\n\t\t\t\t<ui-icon [name]=\"eExpandido() ? 'chevron-down' : 'chevron-right'\" />\n\t\t\t</button>\n\t\t} @else {\n\t\t\t<span class=\"tree-toggle-space\"></span>\n\t\t}\n\t\t@if (ctx.multiplo() && ehCategoria()) {\n\t\t\t<ui-check-box\n\t\t\t\t[value]=\"eSelecionado()\"\n\t\t\t\t[hasDash]=\"eIndeterminado()\"\n\t\t\t\t[disabled]=\"no().desabilitado\"\n\t\t\t\t(click)=\"$event.stopPropagation()\"\n\t\t\t\t(changed)=\"onCheckChanged($event)\"\n\t\t\t/>\n\t\t}\n\t\t@if (no().icone) {\n\t\t\t<i class=\"tree-icone\" [class]=\"no().icone\"></i>\n\t\t}\n\t\t<span class=\"tree-label\">{{ no().label }}</span>\n\t</div>\n\t@if (ehCategoria() && eExpandido()) {\n\t\t<ul class=\"tree-list tree-filhos\">\n\t\t\t@for (filho of no().filhos!; track filho.id) {\n\t\t\t\t<ui-tree-no [no]=\"filho\" [nivel]=\"nivel() + 1\" />\n\t\t\t}\n\t\t</ul>\n\t}\n</li>\n", styles: [":host{display:contents}.tree-list{list-style:none;margin:0;padding:0}.tree-filhos{padding-left:20px}.tree-no{-webkit-user-select:none;user-select:none}.tree-no.desabilitado{opacity:.4;pointer-events:none}.tree-row{display:flex;align-items:center;gap:6px;padding:5px 8px;border-radius:var(--sys-border-radius, 6px);cursor:pointer;transition:background .12s;font-size:.9em;--ui-size: 16px}.tree-row:hover{background:var(--sys-surface-variant, rgba(0, 0, 0, .05))}.tree-row.selecionado{background:color-mix(in srgb,var(--sys-primary) 12%,transparent);color:var(--sys-primary);font-weight:500}.tree-toggle{background:none;border:none;cursor:pointer;padding:0;color:inherit;opacity:.5;width:16px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.tree-toggle:hover{opacity:1}.tree-toggle-space{width:16px;flex-shrink:0}.tree-icone{font-size:14px;opacity:.6;flex-shrink:0}.tree-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"] }]
5273
+ }], propDecorators: { no: [{ type: i0.Input, args: [{ isSignal: true, alias: "no", required: true }] }], nivel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nivel", required: false }] }] } });
5274
+
5188
5275
  class UiTree {
5189
5276
  nos = input([], /* @ts-ignore */
5190
5277
  ...(ngDevMode ? [{ debugName: "nos" }] : /* istanbul ignore next */ []));
@@ -5195,6 +5282,12 @@ class UiTree {
5195
5282
  expandidos = signal(new Set(), /* @ts-ignore */
5196
5283
  ...(ngDevMode ? [{ debugName: "expandidos" }] : /* istanbul ignore next */ []));
5197
5284
  carregarFilhos = output();
5285
+ isExpandido(id) {
5286
+ return this.expandidos().has(id);
5287
+ }
5288
+ isSelecionado(id) {
5289
+ return this.selecionado().includes(id);
5290
+ }
5198
5291
  toggleExpandir(no) {
5199
5292
  const set = new Set(this.expandidos());
5200
5293
  if (set.has(no.id)) {
@@ -5202,39 +5295,46 @@ class UiTree {
5202
5295
  }
5203
5296
  else {
5204
5297
  set.add(no.id);
5205
- if (!no.filhos || no.filhos.length === 0)
5298
+ if (!no.filhos || no.filhos.length === 0) {
5206
5299
  this.carregarFilhos.emit(no);
5300
+ }
5207
5301
  }
5208
5302
  this.expandidos.set(set);
5209
5303
  }
5210
- isExpandido(id) {
5211
- return this.expandidos().has(id);
5212
- }
5213
5304
  toggleSelecionar(no) {
5214
5305
  if (no.desabilitado)
5215
5306
  return;
5216
5307
  const atual = this.selecionado();
5217
5308
  if (this.multiplo()) {
5218
- if (atual.includes(no.id)) {
5219
- this.selecionado.set(atual.filter(id => id !== no.id));
5220
- }
5221
- else {
5222
- this.selecionado.set([...atual, no.id]);
5223
- }
5309
+ this.selecionado.set(atual.includes(no.id) ? atual.filter(id => id !== no.id) : [...atual, no.id]);
5224
5310
  }
5225
5311
  else {
5226
5312
  this.selecionado.set(atual.includes(no.id) ? [] : [no.id]);
5227
5313
  }
5228
5314
  }
5229
- isSelecionado(id) {
5230
- return this.selecionado().includes(id);
5315
+ coletarTodosFilhos(no) {
5316
+ const ids = [];
5317
+ const visitar = (n) => {
5318
+ ids.push(n.id);
5319
+ n.filhos?.forEach(f => visitar(f));
5320
+ };
5321
+ no.filhos?.forEach(f => visitar(f));
5322
+ return ids;
5323
+ }
5324
+ selecionarTodos(no) {
5325
+ const filhos = this.coletarTodosFilhos(no);
5326
+ this.selecionado.set([...new Set([...this.selecionado(), no.id, ...filhos])]);
5327
+ }
5328
+ desselecionarTodos(no) {
5329
+ const paraRemover = new Set([no.id, ...this.coletarTodosFilhos(no)]);
5330
+ this.selecionado.set(this.selecionado().filter(id => !paraRemover.has(id)));
5231
5331
  }
5232
5332
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UiTree, deps: [], target: i0.ɵɵFactoryTarget.Component });
5233
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: UiTree, isStandalone: true, selector: "ui-tree", inputs: { nos: { classPropertyName: "nos", publicName: "nos", isSignal: true, isRequired: false, transformFunction: null }, multiplo: { classPropertyName: "multiplo", publicName: "multiplo", isSignal: true, isRequired: false, transformFunction: null }, selecionado: { classPropertyName: "selecionado", publicName: "selecionado", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selecionado: "selecionadoChange", carregarFilhos: "carregarFilhos" }, ngImport: i0, template: "<ul class=\"tree-list\">\n\t@for(no of nos(); track no.id) {\n\t<ng-container *ngTemplateOutlet=\"noTemplate; context: { $implicit: no, nivel: 0 }\" />\n\t}\n</ul>\n\n<ng-template #noTemplate let-no let-nivel=\"nivel\">\n\t<li class=\"tree-no\" [class.desabilitado]=\"no.desabilitado\" [style.--nivel]=\"nivel\">\n\t\t<div class=\"tree-row\" [class.selecionado]=\"isSelecionado(no.id)\" (click)=\"toggleSelecionar(no)\">\n\t\t\t<span class=\"tree-indent\"></span>\n\t\t\t@if(no.filhos !== undefined) {\n\t\t\t<button class=\"tree-toggle\" type=\"button\" (click)=\"$event.stopPropagation(); toggleExpandir(no)\"\n\t\t\t\t[attr.aria-expanded]=\"isExpandido(no.id)\">\n\t\t\t\t<ui-icon [name]=\"isExpandido(no.id) ? 'chevron-down' : 'chevron-right'\"></ui-icon>\n\t\t\t</button>\n\t\t\t} @else {\n\t\t\t<span class=\"tree-toggle-space\"></span>\n\t\t\t}\n\t\t\t@if(no.icone) { <i class=\"tree-icone\" [class]=\"no.icone\"></i> }\n\t\t\t<span class=\"tree-label\">{{ no.label }}</span>\n\t\t</div>\n\n\t\t@if(no.filhos && isExpandido(no.id)) {\n\t\t<ul class=\"tree-list tree-filhos\">\n\t\t\t@for(filho of no.filhos; track filho.id) {\n\t\t\t<ng-container *ngTemplateOutlet=\"noTemplate; context: { $implicit: filho, nivel: nivel + 1 }\" />\n\t\t\t}\n\t\t</ul>\n\t\t}\n\t</li>\n</ng-template>", styles: [":host{display:block}.tree-list{list-style:none;margin:0;padding:0}.tree-filhos{padding-left:20px}.tree-no{-webkit-user-select:none;user-select:none}.tree-no.desabilitado{opacity:.4;pointer-events:none}.tree-row{display:flex;align-items:center;gap:6px;padding:5px 8px;border-radius:var(--sys-border-radius, 6px);cursor:pointer;transition:background .12s;font-size:.9em}.tree-row:hover{background:var(--sys-surface-variant, rgba(0, 0, 0, .05))}.tree-row.selecionado{background:color-mix(in srgb,var(--sys-primary) 12%,transparent);color:var(--sys-primary);font-weight:500}.tree-toggle{background:none;border:none;cursor:pointer;padding:0;color:inherit;font-size:11px;opacity:.5;width:16px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.tree-toggle-space{width:16px;flex-shrink:0}.tree-icone{font-size:14px;opacity:.6;flex-shrink:0}.tree-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: UiIcon, selector: "ui-icon", inputs: ["name"] }] });
5333
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: UiTree, isStandalone: true, selector: "ui-tree", inputs: { nos: { classPropertyName: "nos", publicName: "nos", isSignal: true, isRequired: false, transformFunction: null }, multiplo: { classPropertyName: "multiplo", publicName: "multiplo", isSignal: true, isRequired: false, transformFunction: null }, selecionado: { classPropertyName: "selecionado", publicName: "selecionado", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selecionado: "selecionadoChange", carregarFilhos: "carregarFilhos" }, providers: [{ provide: UI_TREE_CTX, useExisting: UiTree }], ngImport: i0, template: "<ul class=\"tree-list\">\n\t@for (no of nos(); track no.id) {\n\t\t<ui-tree-no [no]=\"no\" [nivel]=\"0\" />\n\t}\n</ul>\n", styles: [":host{display:block}.tree-list{list-style:none;margin:0;padding:0}\n"], dependencies: [{ kind: "component", type: UiTreeNo, selector: "ui-tree-no", inputs: ["no", "nivel"] }] });
5234
5334
  }
5235
5335
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UiTree, decorators: [{
5236
5336
  type: Component,
5237
- args: [{ selector: 'ui-tree', imports: [NgTemplateOutlet, UiIcon], template: "<ul class=\"tree-list\">\n\t@for(no of nos(); track no.id) {\n\t<ng-container *ngTemplateOutlet=\"noTemplate; context: { $implicit: no, nivel: 0 }\" />\n\t}\n</ul>\n\n<ng-template #noTemplate let-no let-nivel=\"nivel\">\n\t<li class=\"tree-no\" [class.desabilitado]=\"no.desabilitado\" [style.--nivel]=\"nivel\">\n\t\t<div class=\"tree-row\" [class.selecionado]=\"isSelecionado(no.id)\" (click)=\"toggleSelecionar(no)\">\n\t\t\t<span class=\"tree-indent\"></span>\n\t\t\t@if(no.filhos !== undefined) {\n\t\t\t<button class=\"tree-toggle\" type=\"button\" (click)=\"$event.stopPropagation(); toggleExpandir(no)\"\n\t\t\t\t[attr.aria-expanded]=\"isExpandido(no.id)\">\n\t\t\t\t<ui-icon [name]=\"isExpandido(no.id) ? 'chevron-down' : 'chevron-right'\"></ui-icon>\n\t\t\t</button>\n\t\t\t} @else {\n\t\t\t<span class=\"tree-toggle-space\"></span>\n\t\t\t}\n\t\t\t@if(no.icone) { <i class=\"tree-icone\" [class]=\"no.icone\"></i> }\n\t\t\t<span class=\"tree-label\">{{ no.label }}</span>\n\t\t</div>\n\n\t\t@if(no.filhos && isExpandido(no.id)) {\n\t\t<ul class=\"tree-list tree-filhos\">\n\t\t\t@for(filho of no.filhos; track filho.id) {\n\t\t\t<ng-container *ngTemplateOutlet=\"noTemplate; context: { $implicit: filho, nivel: nivel + 1 }\" />\n\t\t\t}\n\t\t</ul>\n\t\t}\n\t</li>\n</ng-template>", styles: [":host{display:block}.tree-list{list-style:none;margin:0;padding:0}.tree-filhos{padding-left:20px}.tree-no{-webkit-user-select:none;user-select:none}.tree-no.desabilitado{opacity:.4;pointer-events:none}.tree-row{display:flex;align-items:center;gap:6px;padding:5px 8px;border-radius:var(--sys-border-radius, 6px);cursor:pointer;transition:background .12s;font-size:.9em}.tree-row:hover{background:var(--sys-surface-variant, rgba(0, 0, 0, .05))}.tree-row.selecionado{background:color-mix(in srgb,var(--sys-primary) 12%,transparent);color:var(--sys-primary);font-weight:500}.tree-toggle{background:none;border:none;cursor:pointer;padding:0;color:inherit;font-size:11px;opacity:.5;width:16px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.tree-toggle-space{width:16px;flex-shrink:0}.tree-icone{font-size:14px;opacity:.6;flex-shrink:0}.tree-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n"] }]
5337
+ args: [{ selector: 'ui-tree', imports: [UiTreeNo], providers: [{ provide: UI_TREE_CTX, useExisting: UiTree }], template: "<ul class=\"tree-list\">\n\t@for (no of nos(); track no.id) {\n\t\t<ui-tree-no [no]=\"no\" [nivel]=\"0\" />\n\t}\n</ul>\n", styles: [":host{display:block}.tree-list{list-style:none;margin:0;padding:0}\n"] }]
5238
5338
  }], propDecorators: { nos: [{ type: i0.Input, args: [{ isSignal: true, alias: "nos", required: false }] }], multiplo: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiplo", required: false }] }], selecionado: [{ type: i0.Input, args: [{ isSignal: true, alias: "selecionado", required: false }] }, { type: i0.Output, args: ["selecionadoChange"] }], carregarFilhos: [{ type: i0.Output, args: ["carregarFilhos"] }] } });
5239
5339
 
5240
5340
  class UiTimeline {