UNPKG

govbr-ds-angular

Version:

Implementação em Angular do Design System GovBR.

1,017 lines (1,004 loc) 149 kB
import * as i0 from '@angular/core'; import { Injectable, Pipe, signal, inject, ChangeDetectionStrategy, Component, ViewEncapsulation, EventEmitter, booleanAttribute, Output, Input, HostBinding, ElementRef, input, output, forwardRef, Renderer2, Directive, computed, numberAttribute } from '@angular/core'; import { NgClass, NgTemplateOutlet } from '@angular/common'; import { Subject } from 'rxjs'; import { trigger, transition, style, animate } from '@angular/animations'; import { Router, ActivatedRoute, NavigationEnd, RouterLink, RouterLinkActive } from '@angular/router'; import BRBreadcrumb from '@govbr-ds/core/dist/components/breadcrumb/breadcrumb'; import * as i1 from '@angular/cdk/accordion'; import { CdkAccordionModule } from '@angular/cdk/accordion'; import BRCookiebar from '@govbr-ds/core/dist/components/cookiebar/cookiebar'; import * as i1$1 from '@angular/forms'; import { Validators, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms'; import BRDateTimePicker from '@govbr-ds/core/dist/components/datetimepicker/datetimepicker'; import { DialogRef, DIALOG_DATA } from '@angular/cdk/dialog'; import BRInput from '@govbr-ds/core/dist/components/input/input'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; import BRMenu from '@govbr-ds/core/dist/components/menu/menu'; import BRSelect from '@govbr-ds/core/dist/components/select/select'; import { finalize } from 'rxjs/operators'; /** * Serviço para exibir alertas na aplicação. * @public * @example * // Exemplo de uso do serviço de alerta. * private alertService = inject(AlertService); * alertService.showAlert('success', 'Operação realizada com sucesso.'); */ class AlertService { _alert = new Subject(); _clear = new Subject(); /** Observable para eventos de alerta. */ get alertEvents$() { return this._alert.asObservable(); } /** * Define e emite um novo evento de alerta. * @internal * */ set alertEvents(value) { this._alert.next(value); } /** * Observable para eventos de limpeza de alerta. * @internal * */ get clearEvent$() { return this._clear.asObservable(); } /** * Exibe um alerta com as propriedades especificadas. * @param type - Tipo do estado do alerta. * @param message - Mensagem do alerta. * @param title - Título opcional do alerta. * @param autoClose - Indica se o alerta deve fechar automaticamente. * @param duration - Duração opcional do alerta em milissegundos. * @param closable - Indica se o alerta pode ser fechado manualmente. * @param delay - Atraso opcional antes de exibir o alerta. */ showAlert(type, message, title, autoClose = true, duration = 4000, closable = true, delay = 0) { if (delay) { setTimeout(() => { this.alertEvents = { type, message, title, duration, autoClose, closable }; }, delay); } else { this.alertEvents = { type, message, title, duration, autoClose, closable }; } } /** Limpa todos os alertas emitindo um evento de limpeza. */ clearAlerts() { this._clear.next(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: AlertService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: AlertService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: AlertService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }] }); /** * Pipe HasErrorPipe é responsável por verificar se um campo possui erro. * @example * <div *ngIf="form.get('campo') | hasError : 'required'">Campo obrigatório</div> * @standalone */ class HasErrorPipe { transform(value, error) { if (error) { return value.invalid && value.hasError(error) && (value.dirty || value.touched); } return value.invalid && (value.dirty || value.touched); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: HasErrorPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.6", ngImport: i0, type: HasErrorPipe, isStandalone: true, name: "hasError", pure: false }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: HasErrorPipe, decorators: [{ type: Pipe, args: [{ name: 'hasError', standalone: true, pure: false, }] }] }); const ICONS_BY_STATE = { success: 'fa-check-circle', danger: 'fa-times-circle', warning: 'fa-exclamation-triangle', info: 'fa-info-circle', ['']: '', }; /** * Função que retorna o ícone de acordo com o estado passado. * @param state * @returns Ícone correspondente ao estado. * @example * getIconByStateUtils('success'); * // Retorna 'fa-check-circle' */ const getIconByStateUtils = (state) => { return ICONS_BY_STATE[state] || ''; }; class GetIconByStatePipe { transform(state) { return getIconByStateUtils(state); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GetIconByStatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.6", ngImport: i0, type: GetIconByStatePipe, isStandalone: true, name: "getIconByState" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: GetIconByStatePipe, decorators: [{ type: Pipe, args: [{ name: 'getIconByState', standalone: true, }] }] }); /** * Componente AlertComponent é responsável por exibir mensagens de alerta com animações. * Ele escuta eventos de alerta do AlertService e gerencia o comportamento de exibição e fechamento automático dos alertas. * @example * <app-alert></app-alert> * @see AlertService * @public * {@link https://www.gov.br/ds/components/message?tab=desenvolvedor|Documentação oficial} */ class AlertComponent { /** Sinal para manter o evento de alerta atual */ alert = signal(null); /** Instância do AlertService para se inscrever nos eventos de alerta */ alertService = inject(AlertService); constructor() { } /** * Inicializa o componente inscrevendo-se nos eventos de alerta e eventos de limpeza do AlertService. * @internal */ ngOnInit() { this.alertService.alertEvents$.subscribe(event => { this.alert.set(event); if (event.autoClose) this.registerCloseTime(event); }); this.alertService.clearEvent$.subscribe(() => this.onHide()); } /** * Oculta o alerta definindo o sinal de alerta como null. * @internal */ onHide() { this.alert.set(null); } /** * Registra um timeout para fechar automaticamente o alerta após a duração especificada. * @param event - O evento de alerta contendo a duração e o closeTimeId. * @internal */ registerCloseTime(event) { event.closeTimeId = setTimeout(() => this.onHide(), event.duration); } /** * Limpa o timeout de fechamento automático quando o mouse entra no alerta. * @param event - O evento de alerta contendo o closeTimeId. * @internal */ onMouseEnter(event) { if (!event.autoClose) return; clearTimeout(event.closeTimeId); } /** * Re-registra o timeout de fechamento automático quando o mouse é pressionado no alerta. * @internal * @param event - O evento de alerta contendo o closeTimeId. */ onMouseDown(event) { if (!event.autoClose) return; this.registerCloseTime(event); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: AlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.6", type: AlertComponent, isStandalone: true, selector: "app-alert", host: { classAttribute: "alert-container" }, ngImport: i0, template: "@if (alert(); as alert) {\n\t<div\n\t\t(mouseenter)=\"onMouseEnter(alert)\"\n\t\t(mouseleave)=\"onMouseDown(alert)\"\n\t\tclass=\"br-message {{ alert.type }}\"\n\t\t@scaleFadeIn\n\t>\n\t\t<div class=\"d-flex w-100 container-lg\">\n\t\t\t<div class=\"icon\"><i class=\"fas fa-lg\" [ngClass]=\"alert.type | getIconByState\" aria-hidden=\"true\"></i></div>\n\t\t\t<div class=\"content\" [attr.aria-label]=\"alert.message\" role=\"alert\">\n\t\t\t\t@if (alert.title) {\n\t\t\t\t\t<span class=\"message-title\">{{ alert.title }}</span>\n\t\t\t\t}\n\t\t\t\t<span class=\"message-body\"> {{ alert.message }}</span>\n\t\t\t</div>\n\t\t\t@if (alert.closable) {\n\t\t\t\t<div (click)=\"onHide()\" class=\"close\">\n\t\t\t\t\t<button class=\"br-button circle small\" type=\"button\" aria-label=\"Fechar a mensagem alerta\">\n\t\t\t\t\t\t<i class=\"fas fa-times\" aria-hidden=\"true\"></i>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t}\n\t\t</div>\n\t</div>\n}\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: GetIconByStatePipe, name: "getIconByState" }], animations: [ trigger('scaleFadeIn', [ transition(':enter', [ style({ transform: 'scale(0.8)', opacity: 0, }), animate(`500ms cubic-bezier(0.35, 0, 0.25, 1)`, style({ transform: 'scale(1)', opacity: 1, })), ]), transition(':leave', [style({ opacity: 1 }), animate(`300ms ease-in`, style({ opacity: 0 }))]), ]), ], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: AlertComponent, decorators: [{ type: Component, args: [{ selector: 'app-alert', standalone: true, imports: [NgClass, GetIconByStatePipe], host: { class: 'alert-container', }, changeDetection: ChangeDetectionStrategy.OnPush, animations: [ trigger('scaleFadeIn', [ transition(':enter', [ style({ transform: 'scale(0.8)', opacity: 0, }), animate(`500ms cubic-bezier(0.35, 0, 0.25, 1)`, style({ transform: 'scale(1)', opacity: 1, })), ]), transition(':leave', [style({ opacity: 1 }), animate(`300ms ease-in`, style({ opacity: 0 }))]), ]), ], template: "@if (alert(); as alert) {\n\t<div\n\t\t(mouseenter)=\"onMouseEnter(alert)\"\n\t\t(mouseleave)=\"onMouseDown(alert)\"\n\t\tclass=\"br-message {{ alert.type }}\"\n\t\t@scaleFadeIn\n\t>\n\t\t<div class=\"d-flex w-100 container-lg\">\n\t\t\t<div class=\"icon\"><i class=\"fas fa-lg\" [ngClass]=\"alert.type | getIconByState\" aria-hidden=\"true\"></i></div>\n\t\t\t<div class=\"content\" [attr.aria-label]=\"alert.message\" role=\"alert\">\n\t\t\t\t@if (alert.title) {\n\t\t\t\t\t<span class=\"message-title\">{{ alert.title }}</span>\n\t\t\t\t}\n\t\t\t\t<span class=\"message-body\"> {{ alert.message }}</span>\n\t\t\t</div>\n\t\t\t@if (alert.closable) {\n\t\t\t\t<div (click)=\"onHide()\" class=\"close\">\n\t\t\t\t\t<button class=\"br-button circle small\" type=\"button\" aria-label=\"Fechar a mensagem alerta\">\n\t\t\t\t\t\t<i class=\"fas fa-times\" aria-hidden=\"true\"></i>\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t}\n\t\t</div>\n\t</div>\n}\n" }] }], ctorParameters: () => [] }); /** * Componente BreadcrumbComponent é responsável por exibir a navegação de breadcrumb. * Ele escuta eventos de navegação do Angular Router e constrói a trilha de navegação dinamicamente. * @example * <app-breadcrumb></app-breadcrumb> * * @public * {@link https://www.gov.br/ds/components/breadcrumb?tab=desenvolvedor|Documentação oficial} */ class BreadcrumbComponent { /** Instância do componente BRBreadcrumb */ instance; /** Lista de breadcrumbs a serem exibidos */ crumbs = []; /** Sinal para controlar a exibição do breadcrumb */ showBreadcrumb = signal(false); /** Instância do Angular Router */ router = inject(Router); /** Instância do ActivatedRoute para acessar informações da rota */ route = inject(ActivatedRoute); constructor() { } /** * @internal */ ngOnInit() { this.router.events.subscribe(event => { if (event instanceof NavigationEnd) { this.crumbs = [ { label: 'Página Inicial', url: '/home', home: true, }, ]; this.showBreadcrumb.set(false); const firstChild = this.route.root?.firstChild; if (firstChild) { this.buildBreadcrumbs(firstChild); const lastCrumb = this.crumbs[this.crumbs.length - 1]; if (lastCrumb && lastCrumb.url !== '/home' && lastCrumb.url !== '/login') { this.showBreadcrumb.set(true); setTimeout(() => { this.setNewInstance(); }); } } } }); } /** * Cria uma nova instância do componente BRBreadcrumb. * @internal */ setNewInstance() { this.instance = new BRBreadcrumb('br-breadcrumb', document.querySelector('.br-breadcrumb')); } /** * Constrói a trilha de navegação de breadcrumbs recursivamente com base na rota ativa. * @internal */ buildBreadcrumbs(route, url = '') { if (route.snapshot.routeConfig) { const routePath = route.snapshot.routeConfig.path; if (routePath) { url += `/${routePath}`; } if (route.snapshot.data['breadCrumb'] && routePath) { this.crumbs.push({ label: route.snapshot.data['breadCrumb'], url: url, active: route.children.length === 0, }); } } if (route.firstChild) { this.buildBreadcrumbs(route.firstChild, url); } } /** * Método do ciclo de vida do Angular chamado após a visualização ser inicializada. * Cria uma nova instância do componente BRBreadcrumb. * @internal */ ngAfterViewInit() { this.setNewInstance(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: BreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.6", type: BreadcrumbComponent, isStandalone: true, selector: "app-breadcrumb", host: { properties: { "class.d-none": "!showBreadcrumb()" }, classAttribute: "br-breadcrumb" }, ngImport: i0, template: "@if (showBreadcrumb()) {\n\t<ul class=\"crumb-list\">\n\t\t@for (crumb of crumbs; track crumb.label; let first = $first; let last = $last) {\n\t\t\t<li [ngClass]=\"{ home: first }\" class=\"crumb\" [attr.data-active]=\"last ? 'active' : null\">\n\t\t\t\t@if (first) {\n\t\t\t\t\t<a class=\"br-button circle\" [routerLink]=\"['/home']\">\n\t\t\t\t\t\t<span class=\"sr-only\">P\u00E1gina inicial</span>\n\t\t\t\t\t\t<i class=\"fas fa-home\"> </i>\n\t\t\t\t\t</a>\n\t\t\t\t} @else if (!first && !last) {\n\t\t\t\t\t<i class=\"icon fas fa-chevron-right\"></i>\n\t\t\t\t\t<a [routerLink]=\"[crumb.url]\">{{ crumb.label }}</a>\n\t\t\t\t} @else {\n\t\t\t\t\t<i class=\"icon fas fa-chevron-right\"></i>\n\t\t\t\t\t<span>{{ crumb.label }}</span>\n\t\t\t\t}\n\t\t\t</li>\n\t\t}\n\t</ul>\n}\n", styles: ["@media (max-width: 768px){.br-breadcrumb .crumb-list{padding:0}}.br-breadcrumb .br-item a.br-button{display:none!important}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: BreadcrumbComponent, decorators: [{ type: Component, args: [{ selector: 'app-breadcrumb', standalone: true, imports: [RouterLink, NgClass], host: { class: 'br-breadcrumb', '[class.d-none]': '!showBreadcrumb()', }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (showBreadcrumb()) {\n\t<ul class=\"crumb-list\">\n\t\t@for (crumb of crumbs; track crumb.label; let first = $first; let last = $last) {\n\t\t\t<li [ngClass]=\"{ home: first }\" class=\"crumb\" [attr.data-active]=\"last ? 'active' : null\">\n\t\t\t\t@if (first) {\n\t\t\t\t\t<a class=\"br-button circle\" [routerLink]=\"['/home']\">\n\t\t\t\t\t\t<span class=\"sr-only\">P\u00E1gina inicial</span>\n\t\t\t\t\t\t<i class=\"fas fa-home\"> </i>\n\t\t\t\t\t</a>\n\t\t\t\t} @else if (!first && !last) {\n\t\t\t\t\t<i class=\"icon fas fa-chevron-right\"></i>\n\t\t\t\t\t<a [routerLink]=\"[crumb.url]\">{{ crumb.label }}</a>\n\t\t\t\t} @else {\n\t\t\t\t\t<i class=\"icon fas fa-chevron-right\"></i>\n\t\t\t\t\t<span>{{ crumb.label }}</span>\n\t\t\t\t}\n\t\t\t</li>\n\t\t}\n\t</ul>\n}\n", styles: ["@media (max-width: 768px){.br-breadcrumb .crumb-list{padding:0}}.br-breadcrumb .br-item a.br-button{display:none!important}\n"] }] }], ctorParameters: () => [] }); /** * Componente CheckboxComponent é responsável por exibir um checkbox com estado e rótulo. * @ * @example * <app-checkbox [label]="'Aceitar termos'" [id]="'checkbox1'" [(value)]="isChecked"></app-checkbox> * * @public * {@link https://www.gov.br/ds/components/checkbox?tab=desenvolvedor|Documentação oficial} */ class CheckboxComponent { /** * Estado do checkbox. * @type {'valid' | 'invalid' | ''} * @default '' * @optional */ state = ''; /** * Rótulo do checkbox. * @type {string} * @required */ label = ''; /** * ID do checkbox. * @type {string} * @required */ id = ''; /** * Indica se o checkbox está desabilitado. * @default false * @type {boolean} */ disabled = false; /** * Indica se o checkbox está marcado. * @default false * @type {boolean} */ checked = false; /** Classe CSS para o estado desabilitado. */ get disabledClass() { return this.disabled; } _value = this.checked; /** * Obtém o valor do checkbox. * @returns O valor atual do checkbox. */ get value() { return this._value; } /** * Define o valor do checkbox. * @param val - O novo valor do checkbox. */ set value(val) { if (this.disabled) return; this._value = val; } /** Evento emitido quando o valor do checkbox muda. */ valueChange = new EventEmitter(); /** * Manipulador de evento para mudança de estado do checkbox. * @param event - O evento de mudança. * @internal */ onChangeCheck(event) { const target = event.target; if (target) this.value = target.checked; this.valueChange.emit(this.value); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: CheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "19.2.6", type: CheckboxComponent, isStandalone: true, selector: "app-checkbox", inputs: { state: "state", label: "label", id: "id", disabled: ["disabled", "disabled", booleanAttribute], checked: ["checked", "checked", booleanAttribute], value: "value" }, outputs: { valueChange: "valueChange" }, host: { properties: { "class.valid": "state === \"valid\"", "class.invalid": "state === \"invalid\"", "class.disabled": "this.disabledClass" }, classAttribute: "br-checkbox" }, ngImport: i0, template: "<input\n\t(change)=\"onChangeCheck($event)\"\n\tid=\"checkbox-{{ id }}\"\n\tname=\"checkbox-{{ id }}\"\n\ttype=\"checkbox\"\n\t[attr.aria-label]=\"label\"\n\t[checked]=\"value\"\n/>\n<label for=\"checkbox-{{ id }}\">{{ label }}</label>\n" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: CheckboxComponent, decorators: [{ type: Component, args: [{ selector: 'app-checkbox', standalone: true, imports: [], host: { class: 'br-checkbox', '[class.valid]': 'state === "valid"', '[class.invalid]': 'state === "invalid"', }, template: "<input\n\t(change)=\"onChangeCheck($event)\"\n\tid=\"checkbox-{{ id }}\"\n\tname=\"checkbox-{{ id }}\"\n\ttype=\"checkbox\"\n\t[attr.aria-label]=\"label\"\n\t[checked]=\"value\"\n/>\n<label for=\"checkbox-{{ id }}\">{{ label }}</label>\n" }] }], propDecorators: { state: [{ type: Input }], label: [{ type: Input, args: [{ required: true }] }], id: [{ type: Input, args: [{ required: true }] }], disabled: [{ type: Input, args: [{ transform: booleanAttribute }] }], checked: [{ type: Input, args: [{ transform: booleanAttribute }] }], disabledClass: [{ type: HostBinding, args: ['class.disabled'] }], value: [{ type: Input }], valueChange: [{ type: Output }] } }); /** * Componente de item de colapso. * * @selector app-collapse-item * @standalone true * @imports CdkAccordionModule */ class CollapseItemComponent { /** * Rótulo do item de colapso. * @type {string} * @required */ label; /** * ID do item de colapso. * @type {string} * @required */ id; /** * Indica se o item de colapso está expandido. * @type {boolean} * @default false */ expanded = false; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: CollapseItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.6", type: CollapseItemComponent, isStandalone: true, selector: "app-collapse-item", inputs: { label: "label", id: "id", expanded: ["expanded", "expanded", booleanAttribute] }, ngImport: i0, template: "<cdk-accordion-item\n\t#accordionItem=\"cdkAccordionItem\"\n\t[expanded]=\"expanded\"\n\tclass=\"accordion-item\"\n\trole=\"button\"\n\ttabindex=\"0\"\n\t[attr.id]=\"'accordion-header-' + id\"\n\t[attr.aria-expanded]=\"accordionItem.expanded\"\n\t[attr.aria-controls]=\"'accordion-body-' + id\"\n>\n\t<div class=\"header\" (click)=\"accordionItem.toggle()\">\n\t\t<span>\n\t\t\t{{ label }}\n\t\t</span>\n\t\t<i class=\"fas fa-chevron-down\" [class.fa-rotate-180]=\"accordionItem.expanded\"> </i>\n\t</div>\n\t@if (accordionItem.expanded) {\n\t\t<div\n\t\t\tclass=\"block\"\n\t\t\trole=\"region\"\n\t\t\t[attr.id]=\"'accordion-body-' + id\"\n\t\t\t[attr.aria-labelledby]=\"'accordion-header-' + id\"\n\t\t>\n\t\t\t<ng-content></ng-content>\n\t\t</div>\n\t}\n</cdk-accordion-item>\n", styles: [".accordion-item{display:inline-flex;align-items:flex-start;gap:8px;flex-direction:column;width:100%}.accordion-item .header{color:var(--pure-100, #000);font-size:20.16px;font-style:normal;font-weight:600;line-height:23.18px;cursor:pointer;margin-bottom:16px;display:flex;align-items:center;gap:8px;outline:none;box-shadow:none}.accordion-item .header:focus{outline:none;box-shadow:none}.accordion-item .header span{pointer-events:none}.accordion-item .header i{transition-duration:.5s;transition-property:transform;color:var(--blue-warm-vivid-70, #1351b4);font-size:16px;line-height:normal}\n"], dependencies: [{ kind: "ngmodule", type: CdkAccordionModule }, { kind: "directive", type: i1.CdkAccordionItem, selector: "cdk-accordion-item, [cdkAccordionItem]", inputs: ["expanded", "disabled"], outputs: ["closed", "opened", "destroyed", "expandedChange"], exportAs: ["cdkAccordionItem"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: CollapseItemComponent, decorators: [{ type: Component, args: [{ selector: 'app-collapse-item', standalone: true, imports: [CdkAccordionModule], template: "<cdk-accordion-item\n\t#accordionItem=\"cdkAccordionItem\"\n\t[expanded]=\"expanded\"\n\tclass=\"accordion-item\"\n\trole=\"button\"\n\ttabindex=\"0\"\n\t[attr.id]=\"'accordion-header-' + id\"\n\t[attr.aria-expanded]=\"accordionItem.expanded\"\n\t[attr.aria-controls]=\"'accordion-body-' + id\"\n>\n\t<div class=\"header\" (click)=\"accordionItem.toggle()\">\n\t\t<span>\n\t\t\t{{ label }}\n\t\t</span>\n\t\t<i class=\"fas fa-chevron-down\" [class.fa-rotate-180]=\"accordionItem.expanded\"> </i>\n\t</div>\n\t@if (accordionItem.expanded) {\n\t\t<div\n\t\t\tclass=\"block\"\n\t\t\trole=\"region\"\n\t\t\t[attr.id]=\"'accordion-body-' + id\"\n\t\t\t[attr.aria-labelledby]=\"'accordion-header-' + id\"\n\t\t>\n\t\t\t<ng-content></ng-content>\n\t\t</div>\n\t}\n</cdk-accordion-item>\n", styles: [".accordion-item{display:inline-flex;align-items:flex-start;gap:8px;flex-direction:column;width:100%}.accordion-item .header{color:var(--pure-100, #000);font-size:20.16px;font-style:normal;font-weight:600;line-height:23.18px;cursor:pointer;margin-bottom:16px;display:flex;align-items:center;gap:8px;outline:none;box-shadow:none}.accordion-item .header:focus{outline:none;box-shadow:none}.accordion-item .header span{pointer-events:none}.accordion-item .header i{transition-duration:.5s;transition-property:transform;color:var(--blue-warm-vivid-70, #1351b4);font-size:16px;line-height:normal}\n"] }] }], propDecorators: { label: [{ type: Input, args: [{ required: true }] }], id: [{ type: Input, args: [{ required: true }] }], expanded: [{ type: Input, args: [{ transform: booleanAttribute }] }] } }); var cookies = [ { lang: "pt-br", allOptOut: true, acceptButton: "Aceitar Todos os Cookies", optInButton: "Aceitar Cookies Selecionados", optOutButton: "Recusar Todos os Cookies", infoText: "Utilizamos cookies para melhorar a sua experiência em nosso site. Você pode escolher quais cookies deseja permitir ou desabilitar.", mainTitle: "Preferências de Cookies", lastUpdate: "2024-10-01", entryText: "Este site utiliza cookies para fornecer uma melhor experiência, análise de dados e personalização de conteúdo. Escolha suas preferências abaixo.", selectAll: false, allAlertMessage: "Você pode alterar suas preferências de cookies a qualquer momento.", closeLabel: "Fechar", lastUpdateLabel: "Última atualização", cookieGroupsLabel: "Categorias de Cookies", selectAllLabel: "Selecionar Todos", unselectAllLabel: "Desmarcar Todos", selectAllGroupLabel: "Selecionar Todos da Categoria", unselectAllGroupLabel: "Desmarcar Todos da Categoria", onLabel: "Ativado", offLabel: "Desativado", alwaysActiveLabel: "Sempre Ativo", cookieNameLabel: "Nome do Cookie", expiresLabel: "Expiração", domainLabel: "Domínio", enterpriseLabel: "Empresa", purposeLabel: "Finalidade", descriptionLabel: "Descrição", cookieGroups: [ { groupId: "necessarios", groupName: "Cookies Necessários", groupOptOut: false, groupSelected: true, groupAlertMessage: "Esses cookies são essenciais para o funcionamento do site e não podem ser desativados.", groupText: "Cookies que garantem o funcionamento básico do site, como autenticação e segurança.", cookieList: [ { cookieId: "session_id", cookieOptOut: false, cookieSelected: true, alertMessage: "", cookieName: "session_id", expires: "1 dia", domain: "universidade.edu.br", entreprise: "Universidade", purpose: "Manter a sessão do usuário ativa.", description: "Cookie utilizado para identificar a sessão do usuário no sistema." } ] }, { groupId: "analise", groupName: "Cookies de Análise", groupOptOut: true, groupSelected: false, groupAlertMessage: "", groupText: "Cookies usados para analisar o tráfego e o comportamento dos usuários no site.", cookieList: [ { cookieId: "google_analytics", cookieOptOut: true, cookieSelected: false, alertMessage: "", cookieName: "_ga", expires: "2 anos", domain: "universidade.edu.br", entreprise: "Google", purpose: "Coletar dados de uso e desempenho do site.", description: "Utilizado para distinguir os usuários únicos durante visitas ao site." } ] } ], noteTitle: "Perguntas Frequentes", noteList: [ { question: "O que são cookies?", answer: "Cookies são pequenos arquivos de texto usados para armazenar informações diretamente no seu navegador." }, { question: "Posso desativar os cookies?", answer: "Sim, você pode desativar os cookies não essenciais usando as opções acima." } ], links: [ { name: "Política de Privacidade", url: "https://universidade.edu.br/politica-de-privacidade" } ] } ]; class CookieBarComponent { instance; brCookieBar = inject(ElementRef); cookiesJson = input(cookies); submit = output(); ngAfterViewInit() { const component = this.brCookieBar.nativeElement.querySelector('.br-cookiebar'); const params = { name: 'br-cookiebar', component: component, json: this.cookiesJson(), lang: 'pt-br', mode: 'default', callback: (response) => this.submit.emit(response), }; this.instance = new BRCookiebar(params); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: CookieBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.6", type: CookieBarComponent, isStandalone: true, selector: "app-cookie-bar", inputs: { cookiesJson: { classPropertyName: "cookiesJson", publicName: "cookiesJson", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { submit: "submit" }, ngImport: i0, template: "<div class=\"br-cookiebar default d-none\" tabindex=\"-1\"></div>\r\n", styles: [""] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: CookieBarComponent, decorators: [{ type: Component, args: [{ selector: 'app-cookie-bar', standalone: true, imports: [], template: "<div class=\"br-cookiebar default d-none\" tabindex=\"-1\"></div>\r\n" }] }] }); const TYPE_DATE_PICKER = { date: 'text', time: 'time', date_time: 'datetime-local', }; /** * Componente DateTimePickerComponent é responsável por exibir um seletor de data e hora. * Implementa a interface ControlValueAccessor para integração com formulários Angular. * @example * <app-date-time-picker [label]="'Data e Hora'" [id]="'datetimepicker1'" [(ngModel)]="selectedDate"></app-date-time-picker> * * @public * {@link https://www.gov.br/ds/components/datetimepicker?tab=desenvolvedor|Documentação oficial} */ class DateTimePickerComponent { /** * Rótulo do componente DateTimePicker. * @type {string} * @required */ label = ''; /** * ID do componente DateTimePicker. * @type {string} * @required */ id; /** * Indica se o componente deve permitir seleção de intervalo. * @type {boolean} * @default false */ range = false; /** * Indica se o componente está desabilitado. * @type {boolean} * @default false */ disabled = false; /** * Data mínima permitida para seleção. * @type {Date | string} */ minDate; /** * Data máxima permitida para seleção. * @type {Date | string} */ maxDate; /** * Placeholder do campo de entrada. * @type {string} */ placeholder = ''; /** * Dica de uso para o campo de entrada. * @type {string} */ hint = ''; /** * Obtém o tipo de seletor de data/hora. * @type {string} */ get type() { return TYPE_DATE_PICKER[this._type]; } /** * Define o tipo de seletor de data/hora. * @type {TypesDatePicker} */ set type(value) { this._type = value; } /** * Tipo de seletor de data/hora. * @type {TypesDatePicker} * @default 'date' * @private */ _type = 'date'; /** * Obtém se o campo de entrada é obrigatório. * @type {boolean} */ get required() { return this._required ?? this.control?.hasValidator(Validators.required) ?? false; } /** * Define se o campo de entrada é obrigatório. * @type {boolean} */ set required(value) { this._required = value; } /** * Valor do campo de entrada. * @type {string} * @protected */ _value; /** * Obtém o valor do campo de entrada. * @type {string} */ get value() { return this._value; } /** * Define o valor do campo de entrada. * @type {string} */ set value(val) { if (this.disabled) return; this._value = val; this._change(val); } /** Controle abstrato do Angular Forms. */ control; _required; _touched = () => void undefined; _change = () => void undefined; TypeDatePicker = TYPE_DATE_PICKER; instance; brDatePicker = inject(ElementRef); constructor() { } /** * Método do ciclo de vida do Angular chamado após a visualização ser inicializada. * Inicializa a instância do componente BRDateTimePicker. * @internal */ ngAfterViewInit() { let dates = {}; if (this.maxDate) { dates = { maxDate: this.normalizeDate(this.maxDate), }; } if (this.minDate) { dates = { ...dates, minDate: this.normalizeDate(this.minDate), }; } this.instance = new BRDateTimePicker('br-datetimepicker', this.brDatePicker.nativeElement.querySelector('.br-datetimepicker'), { ...dates, }); } /** * Normaliza a data para o formato 'DD/MM/YYYY'. * @param date - A data a ser normalizada. * @returns A data normalizada no formato 'DD/MM/YYYY'. * @internal */ normalizeDate(date) { if (date instanceof Date) { const day = String(date.getDate()).padStart(2, '0'); const month = String(date.getMonth() + 1).padStart(2, '0'); const year = date.getFullYear(); return `${day}/${month}/${year}`; } if (!date) return date; const [day, month, year] = date.split('/'); const parsedDate = new Date(`${year}-${month}-${day}`); const formattedDay = String(parsedDate.getDate()).padStart(2, '0'); const formattedMonth = String(parsedDate.getMonth() + 1).padStart(2, '0'); const formattedYear = parsedDate.getFullYear(); return `${formattedDay}/${formattedMonth}/${formattedYear}`; } /** * @internal */ ngOnInit() { this.mountPlaceholder(); } /** * Configura o placeholder do campo de entrada com base no tipo e se é um intervalo. * @internal */ mountPlaceholder() { if (this.placeholder) return; if (this.range) { this.placeholder = this.type === TYPE_DATE_PICKER.date_time ? 'exemplo: 02/02/2024 02:02 até 03/02/2025 02:02' : 'exemplo: 02/02/2024 até 03/02/2025'; } else if (this.type === TYPE_DATE_PICKER.date) { this.placeholder = 'exemplo: 02/02/2024'; } else if (this.type === TYPE_DATE_PICKER.time) { this.placeholder = 'exemplo: 02:40'; } else { this.placeholder = 'exemplo: 02/02/2024 02:02'; } } writeValue(value) { this.value = this.normalizeDate(value); } setDisabledState(disabled) { this.disabled = disabled; } registerOnChange(fn) { this._change = fn; } registerOnTouched(fn) { this._touched = fn; } onBlur() { this._touched(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: DateTimePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.6", type: DateTimePickerComponent, isStandalone: true, selector: "app-date-time-picker", inputs: { label: "label", id: "id", range: ["range", "range", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], minDate: "minDate", maxDate: "maxDate", placeholder: "placeholder", hint: "hint", type: "type", required: ["required", "required", booleanAttribute] }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateTimePickerComponent), multi: true }], ngImport: i0, template: "<div class=\"br-datetimepicker\" [attr.data-mode]=\"range ? 'range' : 'single'\" [attr.data-type]=\"type\">\n\t<label for=\"timepicker-{{ id }}\">{{ label }}</label>\n\t<div class=\"br-input has-icon\" [class.disabled]=\"disabled\">\n\t\t<input\n\t\t\t(blur)=\"onBlur()\"\n\t\t\t[(ngModel)]=\"value\"\n\t\t\tid=\"timepicker-{{ id }}\"\n\t\t\ttype=\"time\"\n\t\t\t[disabled]=\"disabled\"\n\t\t\t[placeholder]=\"placeholder\"\n\t\t\tdata-input=\"data-input\"\n\t\t/>\n\t\t<button\n\t\t\tclass=\"br-button circle small\"\n\t\t\ttype=\"button\"\n\t\t\t[disabled]=\"disabled\"\n\t\t\taria-label=\"Abrir Datepicker\"\n\t\t\tdata-toggle=\"data-toggle\"\n\t\t\tid=\"timepicker-{{ id }}-btn\"\n\t\t\ttabindex=\"-1\"\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<i\n\t\t\t\tclass=\"fas\"\n\t\t\t\t[ngClass]=\"{\n\t\t\t\t\t'fa-clock': type === TypeDatePicker.time,\n\t\t\t\t\t'fa-calendar-alt': type !== TypeDatePicker.time,\n\t\t\t\t}\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t></i>\n\t\t</button>\n\t</div>\n\t@if (disabled) {\n\t\t<span class=\"feedback warning\" role=\"alert\"\n\t\t\t><i class=\"fas fa-exclamation-triangle\" aria-hidden=\"true\"></i>Campo desabilitado</span\n\t\t>\n\t} @else {\n\t\t@if (hint) {\n\t\t\t<span class=\"feedback warning\" role=\"alert\"\n\t\t\t\t><i class=\"fas fa-exclamation-triangle\" aria-hidden=\"true\"></i>{{ hint }}</span\n\t\t\t>\n\t\t}\n\n\t\t<ng-content></ng-content>\n\t}\n</div>\n", dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: DateTimePickerComponent, decorators: [{ type: Component, args: [{ selector: 'app-date-time-picker', standalone: true, imports: [NgClass, FormsModule], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateTimePickerComponent), multi: true }], template: "<div class=\"br-datetimepicker\" [attr.data-mode]=\"range ? 'range' : 'single'\" [attr.data-type]=\"type\">\n\t<label for=\"timepicker-{{ id }}\">{{ label }}</label>\n\t<div class=\"br-input has-icon\" [class.disabled]=\"disabled\">\n\t\t<input\n\t\t\t(blur)=\"onBlur()\"\n\t\t\t[(ngModel)]=\"value\"\n\t\t\tid=\"timepicker-{{ id }}\"\n\t\t\ttype=\"time\"\n\t\t\t[disabled]=\"disabled\"\n\t\t\t[placeholder]=\"placeholder\"\n\t\t\tdata-input=\"data-input\"\n\t\t/>\n\t\t<button\n\t\t\tclass=\"br-button circle small\"\n\t\t\ttype=\"button\"\n\t\t\t[disabled]=\"disabled\"\n\t\t\taria-label=\"Abrir Datepicker\"\n\t\t\tdata-toggle=\"data-toggle\"\n\t\t\tid=\"timepicker-{{ id }}-btn\"\n\t\t\ttabindex=\"-1\"\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<i\n\t\t\t\tclass=\"fas\"\n\t\t\t\t[ngClass]=\"{\n\t\t\t\t\t'fa-clock': type === TypeDatePicker.time,\n\t\t\t\t\t'fa-calendar-alt': type !== TypeDatePicker.time,\n\t\t\t\t}\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t></i>\n\t\t</button>\n\t</div>\n\t@if (disabled) {\n\t\t<span class=\"feedback warning\" role=\"alert\"\n\t\t\t><i class=\"fas fa-exclamation-triangle\" aria-hidden=\"true\"></i>Campo desabilitado</span\n\t\t>\n\t} @else {\n\t\t@if (hint) {\n\t\t\t<span class=\"feedback warning\" role=\"alert\"\n\t\t\t\t><i class=\"fas fa-exclamation-triangle\" aria-hidden=\"true\"></i>{{ hint }}</span\n\t\t\t>\n\t\t}\n\n\t\t<ng-content></ng-content>\n\t}\n</div>\n" }] }], ctorParameters: () => [], propDecorators: { label: [{ type: Input, args: [{ required: true }] }], id: [{ type: Input, args: [{ required: true }] }], range: [{ type: Input, args: [{ transform: booleanAttribute }] }], disabled: [{ type: Input, args: [{ transform: booleanAttribute }] }], minDate: [{ type: Input }], maxDate: [{ type: Input }], placeholder: [{ type: Input }], hint: [{ type: Input }], type: [{ type: Input }], required: [{ type: Input, args: [{ transform: booleanAttribute }] }] } }); /** * Diretiva para estilizar botões com várias opções. * * @selector button[br-button], a[br-button] * @standalone true */ class ButtonDirective { /** * Cor do botão. * @type {'primary' | 'secondary' | 'tertiary'} * @default 'primary' */ color = 'primary'; /** * Tamanho do botão. * @type {SizeOptions} * @default 'medium' */ size = 'medium'; /** * Classe do ícone para o botão. * @type {string} */ icon = ''; /** * Conjunto de fontes para o ícone. * @type {string} * @default 'fas' */ fontSet = 'fas'; /** * Posição do ícone em relação ao texto do botão. * @type {'before' | 'after'} * @default 'before' */ positionIcon = 'before'; /** * Indica se o botão está desabilitado. * @type {boolean} * @default false */ disabled = false; /** * Indica se o botão deve ser exibido como um elemento de bloco. * @type {boolean} * @default false */ block = false; /** * Indica se o botão está em estado de carregamento. * @type {boolean} * @default false */ loading = false; /** * Indica se o botão está ativo. * @type {boolean} * @default false */ active = false; /** * Indica se o botão deve ser exibido como um círculo. * @type {boolean} * @default false */ circle = false; /** * Indica se o botão deve ser exibido no modo escuro. * @type {boolean} * @default false */ inverted = false; el = inject(ElementRef); renderer = inject(Renderer2); constructor() { } ngOnInit() { this.setIcon(); } setIcon() { if (!this.icon) return; const icon = this.createIcon(); if (this.positionIcon === 'after') { this.renderer.appendChild(this.el.nativeElement, icon); } else { this.renderer.insertBefore(this.el.nativeElement, icon, this.el.nativeElement.firstChild); } } createIcon() { const icon = this.renderer.createElement('i'); this.renderer.addClass(icon, this.fontSet); this.renderer.addClass(icon, this.icon); this.renderer.setAttribute(icon, 'aria-hidden', 'true'); return icon; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ButtonDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "19.2.6", type: ButtonDirective, isStandalone: true, selector: "button[br-button], a[br-button]", inputs: { color: "color", size: "size", disabled: ["disabled", "disabled", booleanAttribute], block: ["block", "block", booleanAttribute], loading: ["loading", "loading", booleanAttribute], active: ["active", "active", booleanAttribute], circle: ["circle", "circle", booleanAttribute], inverted: ["inverted", "inverted", booleanAttribute], icon: "icon", fontSet: "fontSet", positionIcon: "positionIcon" }, host: { attributes: { "role": "button" }, properties: { "class.primary": "color === \"primary\"", "class.secondary": "color === \"secondary\"", "class.tertiary": "color === \"tertiary\"", "class.small": "size === \"small\"", "class.medium": "size === \"medium\"", "class.large": "size === \"large\"", "class.disabled": "disabled", "class.block": "block", "class.loading": "loading", "class.active": "active", "class.circle": "circle", "class.dark-mode": "inverted", "disabled": "disabled", "class.br-button": "true" } }, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ButtonDirective, decorators: [{ type: Directive, args: [{ selector: 'button[br-button], a[br-button]', host: { '[class.primary]': 'color === "primary"', '[class.secondary]': 'color === "secondary"', '[class.tertiary]': 'color === "tertiary"', '[class.small]': 'size === "small"', '[class.medium]': 'size === "medium"', '[class.large]': 'size === "large"', '[class.disabled]': 'disabled', '[class.block]': 'block', '[class.loading]': 'loading', '[class.active]': 'active', '[class.circle]': 'circle', '[class.dark-mode]': 'inverted', '[disabled]': 'disabled', '[class.br-button]': 'true', role: 'button', }, inputs: ['color', 'size', 'disabled', 'block', 'loading', 'active', 'circle', 'inverted'], standalone: true, }] }], ctorParameters: () => [], propDecorators: { color: [{ type: Input }], size: [{ type: Input }], icon: [{ type: Input }], fontSet: [{ type: Input }], positionIcon: [{ type: Input }], disabled: [{ type: Input, args: [{ transform: booleanAttribute }] }], block: [{ type: Input, args: [{ transform: booleanAttribute }] }], loading: [{ type: Input, args: [{ transform: booleanAttribute }] }], active: [{ type: Input, args: [{ transform: booleanAttribute }] }], circle: [{ type: Input, args: [{ transform: booleanAttribute }] }], inverted: [{ type: Input, args: [{ transform: booleanAttribute }] }] } }); /** * Diretiva FeedbackDirective é responsável por exibir um feedback visual de estado. * @example * <span br-feedback state="success">Mensagem de sucesso</span> * @public * {@link https://www.gov.br/ds/components/feedback?tab=desenvolvedor|Documentação o