cfc-ds
Version:
Design System do Conselho Federal de Contabilidade baseado no govbr-ds
1 lines • 640 kB
Source Map (JSON)
{"version":3,"file":"cfc-ds.mjs","sources":["../../../projects/cfc-ds/src/lib/enums/avatar-density.enum.ts","../../../projects/cfc-ds/src/lib/enums/avatar-type.enum.ts","../../../projects/cfc-ds/src/lib/components/avatar/avatar.component.ts","../../../projects/cfc-ds/src/lib/components/avatar/avatar.component.html","../../../projects/cfc-ds/src/lib/components/breadcrumb/breadcrumb.component.ts","../../../projects/cfc-ds/src/lib/components/breadcrumb/breadcrumb.component.html","../../../projects/cfc-ds/src/lib/enums/button-type.enum.ts","../../../projects/cfc-ds/src/lib/enums/button-density.enum.ts","../../../projects/cfc-ds/src/lib/components/button/button.component.ts","../../../projects/cfc-ds/src/lib/components/button/button.component.html","../../../projects/cfc-ds/src/lib/components/card/components/card-content/card-content.component.ts","../../../projects/cfc-ds/src/lib/components/card/components/card-content/card-content.component.html","../../../projects/cfc-ds/src/lib/components/card/card.component.ts","../../../projects/cfc-ds/src/lib/components/card/card.component.html","../../../projects/cfc-ds/src/lib/components/carousel/carousel.component.ts","../../../projects/cfc-ds/src/lib/components/carousel/carousel.component.html","../../../projects/cfc-ds/src/lib/cfc-ds-root.component.ts","../../../projects/cfc-ds/src/lib/models/components.model.ts","../../../projects/cfc-ds/src/lib/pages/cfc-test-page/components-list/components-list.component.ts","../../../projects/cfc-ds/src/lib/pages/cfc-test-page/components-list/components-list.component.html","../../../projects/cfc-ds/src/lib/services/cookie-bar.service.ts","../../../projects/cfc-ds/src/lib/components/cookie-bar/cookie-bar.component.ts","../../../projects/cfc-ds/src/lib/components/cookie-bar/cookie-bar.component.html","../../../projects/cfc-ds/src/lib/enums/date-time-picker.enum.ts","../../../projects/cfc-ds/src/lib/components/icon/icon.component.ts","../../../projects/cfc-ds/src/lib/components/icon/icon.component.html","../../../projects/cfc-ds/src/lib/components/datetimer-picker/datetimer-picker.component.ts","../../../projects/cfc-ds/src/lib/components/datetimer-picker/datetimer-picker.component.html","../../../projects/cfc-ds/src/lib/enums/divider-mode.enum.ts","../../../projects/cfc-ds/src/lib/enums/divider-type.enum.ts","../../../projects/cfc-ds/src/lib/enums/divider-axis.enum.ts","../../../projects/cfc-ds/src/lib/enums/divider-density.enum.ts","../../../projects/cfc-ds/src/lib/components/divider/divider.component.ts","../../../projects/cfc-ds/src/lib/components/divider/divider.component.html","../../../projects/cfc-ds/src/lib/components/footer/footer.component.ts","../../../projects/cfc-ds/src/lib/components/footer/footer.component.html","../../../projects/cfc-ds/src/lib/enums/header-view-mode.enum.ts","../../../projects/cfc-ds/src/lib/enums/sign-in-type.enum.ts","../../../projects/cfc-ds/src/lib/enums/timer-type.enum.ts","../../../projects/cfc-ds/src/lib/enums/sign-in-mode.enum.ts","../../../projects/cfc-ds/src/lib/enums/sign-in-density.enum.ts","../../../projects/cfc-ds/src/lib/components/sign-in/sign-in.component.ts","../../../projects/cfc-ds/src/lib/components/sign-in/sign-in.component.html","../../../projects/cfc-ds/src/lib/services/timer.service.ts","../../../projects/cfc-ds/src/lib/components/timer/timer.component.ts","../../../projects/cfc-ds/src/lib/components/timer/timer.component.html","../../../projects/cfc-ds/src/lib/components/header/header.component.ts","../../../projects/cfc-ds/src/lib/components/header/header.component.html","../../../projects/cfc-ds/src/lib/enums/input-state.enum.ts","../../../projects/cfc-ds/src/lib/enums/input-density.enum.ts","../../../projects/cfc-ds/src/lib/components/input/input.component.ts","../../../projects/cfc-ds/src/lib/components/input/input.component.html","../../../projects/cfc-ds/src/lib/components/list/list.component.ts","../../../projects/cfc-ds/src/lib/components/list/list.component.html","../../../projects/cfc-ds/src/lib/enums/logo-view-mode.enum.ts","../../../projects/cfc-ds/src/lib/components/logo/logo.component.ts","../../../projects/cfc-ds/src/lib/components/logo/logo.component.html","../../../projects/cfc-ds/src/lib/components/magic-button/magic-button.component.ts","../../../projects/cfc-ds/src/lib/components/magic-button/magic-button.component.html","../../../projects/cfc-ds/src/lib/components/menu/menu.component.ts","../../../projects/cfc-ds/src/lib/components/menu/menu.component.html","../../../projects/cfc-ds/src/lib/enums/message-state.enum.ts","../../../projects/cfc-ds/src/lib/enums/message-type.enum.ts","../../../projects/cfc-ds/src/lib/components/message/message.component.ts","../../../projects/cfc-ds/src/lib/components/message/message.component.html","../../../projects/cfc-ds/src/lib/components/modal/modal.component.ts","../../../projects/cfc-ds/src/lib/components/modal/modal.component.html","../../../projects/cfc-ds/src/lib/components/tabItem/tab-item.component.ts","../../../projects/cfc-ds/src/lib/components/tabItem/tab-item.component.html","../../../projects/cfc-ds/src/lib/components/tabContent/tab-content.component.ts","../../../projects/cfc-ds/src/lib/components/tab/tab.component.ts","../../../projects/cfc-ds/src/lib/components/tab/tab.component.html","../../../projects/cfc-ds/src/lib/components/notification/notification.component.ts","../../../projects/cfc-ds/src/lib/components/notification/notification.component.html","../../../projects/cfc-ds/src/lib/components/notification-panel/notification-panel.component.ts","../../../projects/cfc-ds/src/lib/components/notification-panel/notification-panel.component.html","../../../projects/cfc-ds/src/lib/components/page-content/page-content.component.ts","../../../projects/cfc-ds/src/lib/components/page-content/page-content.component.html","../../../projects/cfc-ds/src/lib/enums/select-type.enum.ts","../../../projects/cfc-ds/src/lib/enums/pagination-type.enum.ts","../../../projects/cfc-ds/src/lib/components/select/select.component.ts","../../../projects/cfc-ds/src/lib/components/select/select.component.html","../../../projects/cfc-ds/src/lib/components/pagination/pagination.component.ts","../../../projects/cfc-ds/src/lib/components/pagination/pagination.component.html","../../../projects/cfc-ds/src/lib/components/radio/radio.component.ts","../../../projects/cfc-ds/src/lib/components/radio/radio.component.html","../../../projects/cfc-ds/src/lib/components/scrim/scrim.component.ts","../../../projects/cfc-ds/src/lib/components/scrim/scrim.component.html","../../../projects/cfc-ds/src/lib/components/skiplink/skiplink.component.ts","../../../projects/cfc-ds/src/lib/components/skiplink/skiplink.component.html","../../../projects/cfc-ds/src/lib/components/slider/slider.component.ts","../../../projects/cfc-ds/src/lib/components/slider/slider.component.html","../../../projects/cfc-ds/src/lib/components/switch/switch.component.ts","../../../projects/cfc-ds/src/lib/components/switch/switch.component.html","../../../projects/cfc-ds/src/lib/enums/illustration-type.enum.ts","../../../projects/cfc-ds/src/lib/components/illustration-state/illustration-state.component.ts","../../../projects/cfc-ds/src/lib/components/illustration-state/illustration-state.component.html","../../../projects/cfc-ds/src/lib/components/table/table.component.ts","../../../projects/cfc-ds/src/lib/components/table/table.component.html","../../../projects/cfc-ds/src/lib/components/tag/tag.component.ts","../../../projects/cfc-ds/src/lib/components/tag/tag.component.html","../../../projects/cfc-ds/src/lib/enums/tooltip-place.enum.ts","../../../projects/cfc-ds/src/lib/enums/checkbox-option-state.enum.ts","../../../projects/cfc-ds/src/lib/enums/checkbox-option-type.enum.ts","../../../projects/cfc-ds/src/lib/enums/loading-density.enum.ts","../../../projects/cfc-ds/src/lib/enums/item-type.enum.ts","../../../projects/cfc-ds/src/lib/components/collapse/collapse.component.ts","../../../projects/cfc-ds/src/lib/components/collapse/collapse.component.html","../../../projects/cfc-ds/src/lib/components/item/item.component.ts","../../../projects/cfc-ds/src/lib/components/item/item.component.html","../../../projects/cfc-ds/src/lib/services/loading.service.ts","../../../projects/cfc-ds/src/lib/components/loading/loading.component.ts","../../../projects/cfc-ds/src/lib/components/loading/loading.component.html","../../../projects/cfc-ds/src/lib/components/textarea/textarea.component.ts","../../../projects/cfc-ds/src/lib/components/textarea/textarea.component.html","../../../projects/cfc-ds/src/lib/components/tooltip/tooltip.component.ts","../../../projects/cfc-ds/src/lib/components/tooltip/tooltip.component.html","../../../projects/cfc-ds/src/lib/components/upload/upload.component.ts","../../../projects/cfc-ds/src/lib/components/upload/upload.component.html","../../../projects/cfc-ds/src/lib/components/wizard/wizardStep/wizard-step.component.ts","../../../projects/cfc-ds/src/lib/components/wizard/wizardStep/wizard-step.component.html","../../../projects/cfc-ds/src/lib/components/wizard/wizard.component.ts","../../../projects/cfc-ds/src/lib/components/wizard/wizard.component.html","../../../projects/cfc-ds/src/lib/pages/cfc-test-page/test-component/test-component.component.ts","../../../projects/cfc-ds/src/lib/pages/cfc-test-page/test-component/test-component.component.html","../../../projects/cfc-ds/src/lib/pages/cfc-test-page/test-page.component.ts","../../../projects/cfc-ds/src/lib/pages/cfc-test-page/test-page.component.html","../../../projects/cfc-ds/src/lib/components/wizard/wizardNavigation/wizard-navigation.component.ts","../../../projects/cfc-ds/src/lib/components/wizard/wizardNavigation/wizard-navigation.component.html","../../../projects/cfc-ds/src/lib/providers/daysjs-date-adapter.ts","../../../projects/cfc-ds/src/lib/directives/controller.directive.ts","../../../projects/cfc-ds/src/lib/components/card/components/card-header/card-header.component.ts","../../../projects/cfc-ds/src/lib/components/card/components/card-header/card-header.component.html","../../../projects/cfc-ds/src/lib/components/card/components/card-footer/card-footer.component.ts","../../../projects/cfc-ds/src/lib/components/card/components/card-footer/card-footer.component.html","../../../projects/cfc-ds/src/lib/directives/full-width.directive.ts","../../../projects/cfc-ds/src/lib/directives/click-outside.directive.ts","../../../projects/cfc-ds/src/lib/components/checkbox/checkbox.component.ts","../../../projects/cfc-ds/src/lib/components/checkbox/checkbox.component.html","../../../projects/cfc-ds/src/lib/components/step/step.component.ts","../../../projects/cfc-ds/src/lib/components/step/step.component.html","../../../projects/cfc-ds/src/lib/cfc-ds.module.ts","../../../projects/cfc-ds/src/lib/enums/menu-type.enum.ts","../../../projects/cfc-ds/src/lib/enums/menu-groupment.enum.ts","../../../projects/cfc-ds/src/public-api.ts","../../../projects/cfc-ds/src/cfc-ds.ts"],"sourcesContent":["export enum AvatarDensity {\r\n large = \"large\",\r\n medium = \"medium\",\r\n small = \"small\"\r\n}\r\n","export enum AvatarType {\r\n letter = \"letter\",\r\n icon = \"icon\",\r\n image = \"image\",\r\n dropdown = \"dropdown\",\r\n}\r\n","import { Component, Input } from '@angular/core';\r\nimport { AvatarDensity } from '../../enums/avatar-density.enum';\r\nimport { AvatarType } from '../../enums/avatar-type.enum';\r\n\r\nexport interface ListItems {\r\n name: string,\r\n url: string\r\n}\r\n@Component({\r\n selector: 'cfc-avatar',\r\n templateUrl: './avatar.component.html',\r\n styleUrl: './avatar.component.scss',\r\n})\r\nexport class AvatarComponent {\r\n @Input() type: AvatarType = AvatarType.icon;\r\n @Input() name!: string;\r\n @Input() density: AvatarDensity = AvatarDensity.medium;\r\n @Input() imageUrl?: string = '';\r\n @Input() listItems: ListItems[] = [];\r\n\r\n avatarTypes = AvatarType;\r\n avatarDensities = AvatarDensity;\r\n\r\n openDropdown = false;\r\n\r\n toggleDropdown() {\r\n this.openDropdown = !this.openDropdown;\r\n }\r\n}\r\n","<span\r\n class=\"br-avatar mr-3\"\r\n [title]=\"name\"\r\n [class.medium]=\"density === avatarDensities.medium\"\r\n [class.large]=\"density === avatarDensities.large\"\r\n>\r\n <span *ngIf=\"type === avatarTypes.icon\" class=\"content\">\r\n <i class=\"fas fa-user bg-blue-warn-20\" aria-hidden=\"true\"></i>\r\n </span>\r\n <span\r\n *ngIf=\"type === avatarTypes.letter\"\r\n class=\"content bg-violet-50 text-pure-0\"\r\n >\r\n {{ name[0] | uppercase }}\r\n </span>\r\n <span *ngIf=\"type === avatarTypes.image\" class=\"content\">\r\n <img [src]=\"imageUrl\" alt=\"Avatar\" />\r\n </span>\r\n <span *ngIf=\"type === avatarTypes.dropdown\" class=\"dropdown\">\r\n <button class=\"br-sign-in\" type=\"button\" (click)=\"toggleDropdown()\">\r\n <span class=\"br-avatar\" title=\"Fulano da Silva\"\r\n ><span class=\"content bg-orange-vivid-30 text-pure-0\">\r\n {{ name[0] | uppercase }}</span\r\n ></span\r\n ><span class=\"ml-2 text-gray-80 text-weight-regular\">{{ name }}</span\r\n ><i class=\"fas fa-caret-down\" aria-hidden=\"true\"></i>\r\n </button>\r\n <div *ngIf=\"openDropdown\" class=\"br-list\">\r\n <div *ngIf=\"listItems?.length !== 0\">\r\n <div *ngFor=\"let items of listItems\" class=\"br-item\"><p>{{items.name}}</p></div>\r\n </div>\r\n </div>\r\n </span>\r\n</span>\r\n","import { Component, OnDestroy, OnInit } from '@angular/core';\r\nimport { Router, ActivatedRoute, NavigationEnd, Data } from '@angular/router';\r\nimport { filter, Subscription } from 'rxjs';\r\nimport { BreadcrumbLink } from '../../models/breadcrumb.model';\r\n\r\n@Component({\r\n selector: 'cfc-breadcrumb',\r\n templateUrl: './breadcrumb.component.html',\r\n styleUrls: ['./breadcrumb.component.scss']\r\n})\r\nexport class BreadcrumbComponent implements OnInit, OnDestroy {\r\n /** Lista de breadcrumbs gerados */\r\n links: BreadcrumbLink[] = [];\r\n\r\n /** Limite de caracteres para truncamento */\r\n readonly maxLength = 25;\r\n\r\n /** Inscrição para monitorar mudanças na rota */\r\n private routeSubscription?: Subscription;\r\n\r\n constructor(\r\n private router: Router,\r\n private activatedRoute: ActivatedRoute\r\n ) {}\r\n\r\n /** Inicializa o componente e observa mudanças de rota */\r\n ngOnInit(): void {\r\n this.updateBreadcrumbs();\r\n\r\n this.routeSubscription = this.router.events.pipe(\r\n filter(event => event instanceof NavigationEnd)\r\n ).subscribe(() => {\r\n this.updateBreadcrumbs();\r\n });\r\n }\r\n\r\n /** Atualiza os breadcrumbs com base na rota ativa */\r\n private updateBreadcrumbs(): void {\r\n const breadcrumbs = this.buildBreadcrumbs(this.router.routerState.root);\r\n this.removeLastBreadcrumbUrl(breadcrumbs);\r\n this.links = breadcrumbs;\r\n }\r\n\r\n /**\r\n * Constrói os breadcrumbs recursivamente com base nas rotas ativadas.\r\n * @param route Rota ativa.\r\n * @param breadcrumbs Lista de breadcrumbs acumulada.\r\n * @returns Lista de BreadcrumbLink atualizada.\r\n */\r\n private buildBreadcrumbs(route: ActivatedRoute, breadcrumbs: BreadcrumbLink[] = []): BreadcrumbLink[] {\r\n route.children.forEach((child) => {\r\n const routeSegment = this.getRouteURL(child);\r\n const label = this.getBreadcrumbLabel(child.snapshot.data);\r\n const fullPath = this.buildFullPath(routeSegment, breadcrumbs);\r\n\r\n if (label && !this.isDuplicateBreadcrumb(breadcrumbs, label)) {\r\n const truncated = this.shouldTruncate(label) ? this.truncateText(label) : label;\r\n \r\n const breadcrumb: BreadcrumbLink = { \r\n label: truncated, \r\n url: fullPath, \r\n target: '_self',\r\n };\r\n \r\n // Adicionar tooltip apenas se o texto foi truncado\r\n if (truncated !== label) {\r\n breadcrumb.tooltipText = label;\r\n breadcrumb.tooltipPlace = 'top';\r\n breadcrumb.tooltipType = 'info';\r\n }\r\n \r\n breadcrumbs.push(breadcrumb);\r\n }\r\n\r\n this.buildBreadcrumbs(child, breadcrumbs);\r\n });\r\n\r\n return breadcrumbs;\r\n }\r\n\r\n /**\r\n * Verifica se o texto deve ser truncado\r\n * @param text Texto para verificar\r\n * @returns true se o texto deve ser truncado\r\n */\r\n shouldTruncate(text: string): boolean {\r\n return text.length > this.maxLength;\r\n }\r\n\r\n /**\r\n * Trunca o texto para o tamanho máximo definido\r\n * @param text Texto para truncar\r\n * @returns Texto truncado\r\n */\r\n truncateText(text: string): string {\r\n return text.substring(0, this.maxLength - 3) + '...';\r\n }\r\n\r\n /**\r\n * Obtém o texto original para exibição no tooltip\r\n * @param link Item do breadcrumb\r\n * @returns Texto original ou undefined se não houver tooltip\r\n */\r\n getOriginalText(link: BreadcrumbLink): string | undefined {\r\n return link.tooltipText;\r\n }\r\n\r\n /**\r\n * Obtém o segmento da URL da rota atual.\r\n * @param route Rota atual.\r\n * @returns Segmento da URL ou string vazia.\r\n */\r\n private getRouteURL(route: ActivatedRoute): string {\r\n return route.snapshot.url.length > 0\r\n ? route.snapshot.url.map(segment => segment.path).join('/')\r\n : '';\r\n }\r\n\r\n /**\r\n * Constrói o caminho completo concatenando segmentos anteriores.\r\n * @param routeSegment Segmento atual da rota.\r\n * @param breadcrumbs Lista de breadcrumbs acumulada.\r\n * @returns Caminho completo da URL.\r\n */\r\n private buildFullPath(routeSegment: string, breadcrumbs: BreadcrumbLink[]): string {\r\n if (!routeSegment) return '';\r\n const previousPath = breadcrumbs.length > 0 ? breadcrumbs[breadcrumbs.length - 1].url : '';\r\n return previousPath ? `${previousPath}/${routeSegment}` : `/${routeSegment}`;\r\n }\r\n\r\n /**\r\n * Obtém o rótulo do breadcrumb a partir dos dados da rota.\r\n * @param data Dados da rota.\r\n * @returns Rótulo do breadcrumb ou null.\r\n */\r\n private getBreadcrumbLabel(data: Data): string | null {\r\n const label = data['breadcrumb'];\r\n return label && typeof label === 'string' && label.trim() ? label.trim() : null;\r\n }\r\n\r\n /**\r\n * Remove a URL do último breadcrumb para evitar que seja clicável.\r\n * @param breadcrumbs Lista de breadcrumbs.\r\n */\r\n private removeLastBreadcrumbUrl(breadcrumbs: BreadcrumbLink[]): void {\r\n if (breadcrumbs.length > 0) {\r\n breadcrumbs[breadcrumbs.length - 1].url = undefined;\r\n breadcrumbs[breadcrumbs.length - 1].active = true;\r\n }\r\n }\r\n\r\n /**\r\n * Verifica se um breadcrumb já existe na lista para evitar duplicatas.\r\n * @param breadcrumbs Lista de breadcrumbs acumulada.\r\n * @param label Nome do breadcrumb a verificar.\r\n * @returns Verdadeiro se o breadcrumb já existir, falso caso contrário.\r\n */\r\n private isDuplicateBreadcrumb(breadcrumbs: BreadcrumbLink[], label: string): boolean {\r\n return breadcrumbs.some(bc => bc.tooltipText === label || bc.label === label);\r\n }\r\n\r\n /** Cancela a inscrição ao destruir o componente */\r\n ngOnDestroy(): void {\r\n this.routeSubscription?.unsubscribe();\r\n }\r\n}","<nav\r\n class=\"br-breadcrumb\"\r\n aria-label=\"Breadcrumbs\">\r\n <ul\r\n class=\"crumb-list\"\r\n style=\"padding-left: 0;\"\r\n role=\"list\">\r\n <li\r\n class=\"crumb\">\r\n <a\r\n class=\"br-button circle\"\r\n href=\"/\"\r\n target=\"_self\">\r\n <i class=\"fas fa-home\"></i>\r\n </a>\r\n </li>\r\n\r\n <li\r\n class=\"crumb\"\r\n *ngFor=\"let link of links; let last = last\">\r\n <i\r\n class=\"icon fas fa-chevron-right\">\r\n </i>\r\n\r\n <a\r\n *ngIf=\"!last\"\r\n [href]=\"link.url\"\r\n [target]=\"link.target\"\r\n [title]=\"link.tooltipText || ''\"\r\n [attr.data-tooltip]=\"link.tooltipText || null\"\r\n [attr.data-tooltip-place]=\"link.tooltipPlace || null\"\r\n [attr.data-tooltip-type]=\"link.tooltipType || null\"\r\n [attr.data-tooltip-timer]=\"link.tooltipTimer || null\">\r\n <span>\r\n {{ link.label | titlecase }}\r\n </span>\r\n </a>\r\n\r\n <span\r\n *ngIf=\"last\"\r\n tabindex=\"0\"\r\n aria-current=\"page\"\r\n [title]=\"link.tooltipText || ''\"\r\n [attr.data-tooltip]=\"link.tooltipText || null\"\r\n [attr.data-tooltip-place]=\"link.tooltipPlace || null\"\r\n [attr.data-tooltip-type]=\"link.tooltipType || null\"\r\n [attr.data-tooltip-timer]=\"link.tooltipTimer || null\">\r\n {{ link.label | titlecase }}\r\n </span>\r\n\r\n </li>\r\n </ul>\r\n</nav>","export enum ButtonType {\r\n primary = \"primary\",\r\n secondary = \"secondary\",\r\n tertiary = \"tertiary\",\r\n danger = 'danger'\r\n}\r\n","export enum ButtonDensity {\r\n large = \"large\",\r\n middle = \"middle\",\r\n small = \"small\",\r\n}\r\n","import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';\r\nimport { ButtonType } from '../../enums/button-type.enum';\r\nimport { ButtonDensity } from '../../enums/button-density.enum';\r\n\r\n@Component({\r\n selector: 'cfc-button',\r\n templateUrl: './button.component.html',\r\n styleUrl: './button.component.scss'\r\n})\r\nexport class ButtonComponent implements OnChanges {\r\n\r\n @Input() label = 'button';\r\n @Input() type: ButtonType = ButtonType.primary;\r\n @Input() submit = false;\r\n @Input() circle = false;\r\n @Input() density: ButtonDensity = ButtonDensity.middle;\r\n @Input() disabled = false;\r\n @Input() block = false;\r\n @Input() icon = '';\r\n @Input() active = false ;\r\n @Input() inverted = false;\r\n @Input() loading = false;\r\n\r\n @Output() onClick: EventEmitter<any> = new EventEmitter<any>();\r\n\r\n readonly buttonTypes: typeof ButtonType = ButtonType;\r\n readonly buttonDensity: typeof ButtonDensity = ButtonDensity;\r\n\r\n constructor(\r\n private cdr: ChangeDetectorRef\r\n ) { }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['type']) {\r\n this.cdr.detectChanges();\r\n }\r\n }\r\n\r\n}\r\n","<button\r\n class=\"br-button\"\r\n [ngClass]=\"{\r\n 'primary': type === buttonTypes.primary,\r\n 'secondary': type === buttonTypes.secondary,\r\n 'tertiary': type === buttonTypes.tertiary,\r\n 'danger': type === buttonTypes.danger,\r\n 'circle': circle,\r\n 'block': block,\r\n 'loading': loading,\r\n 'active': active,\r\n 'dark-mode': inverted,\r\n 'small': density === buttonDensity.small,\r\n 'lager': density === buttonDensity.large,\r\n 'middle': density === buttonDensity.middle,\r\n }\"\r\n [disabled]=\"disabled\"\r\n [attr.aria-label]=\"icon ? label : null\"\r\n [type]=\"submit ? 'submit' : 'button'\"\r\n fxLayoutGap=\"0.3rem\"\r\n (click)=\"onClick.emit()\"\r\n>\r\n <i *ngIf=\"icon\" [class]=\"'fas fa-' + icon\" aria-hidden=\"true\"></i>\r\n <span *ngIf=\"!circle\">\r\n {{ label }}\r\n </span>\r\n</button>\r\n","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'cfc-card-content',\r\n templateUrl: './card-content.component.html',\r\n styleUrl: './card-content.component.scss'\r\n})\r\nexport class CardContentComponent {\r\n\r\n}\r\n","<div class=\"card-content\">\r\n <ng-content></ng-content>\r\n</div>\r\n","import { Component, Input } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'cfc-card',\r\n templateUrl: './card.component.html',\r\n styleUrl: './card.component.scss'\r\n})\r\nexport class CardComponent {\r\n\r\n @Input() hover = false;\r\n @Input() disabled = false;\r\n @Input() hFixed = false\r\n\r\n}\r\n"," <div class=\"br-card\"\r\n [class.hover]=\"hover\"\r\n [class.disabled]=\"disabled\"\r\n [class.h-fixed]=\"hFixed\">\r\n <ng-content select=\"[cfc-card-header]\"></ng-content>\r\n <cfc-card-content>\r\n <ng-content select=\"[cfc-card-content]\">\r\n\r\n </ng-content>\r\n </cfc-card-content>\r\n <ng-content select=\"[cfc-card-footer]\"></ng-content>\r\n </div>\r\n","import {\r\n Component,\r\n ContentChild,\r\n ElementRef,\r\n EventEmitter,\r\n Input,\r\n OnDestroy,\r\n OnInit,\r\n Output,\r\n TemplateRef,\r\n ViewChild,\r\n AfterViewInit\r\n} from '@angular/core';\r\nimport { CarouselItem } from '../../models/carousel-item.model';\r\nimport { fromEvent, interval, Subscription } from 'rxjs';\r\nimport { tap } from 'rxjs/operators';\r\nimport { CarouselConfig } from '../../models/carousel-config.model';\r\n\r\n@Component({\r\n selector: 'cfc-carousel',\r\n templateUrl: './carousel.component.html',\r\n styleUrls: ['./carousel.component.scss']\r\n})\r\nexport class CarouselComponent implements OnInit, OnDestroy, AfterViewInit {\r\n @Input() items: CarouselItem[] = [];\r\n @Input() config: CarouselConfig = {\r\n loop: false,\r\n autoPlay: false,\r\n autoPlayInterval: 5000,\r\n showNavigationButtons: true,\r\n showPlayButtons: false,\r\n showIndicator: true,\r\n navigationButtonsPosition: 'outside', // 'inside' ou 'outside'\r\n indicatorPosition: 'inside', // 'inside' ou 'outside'\r\n indicatorType: 'simple',\r\n itemsPerPage: 1,\r\n navigationType: 'page',\r\n transitionDuration: 300,\r\n transitionType: 'slide',\r\n enableTouch: true\r\n };\r\n\r\n @Output() pageChange = new EventEmitter<number>();\r\n @Output() itemClick = new EventEmitter<CarouselItem>();\r\n\r\n @ViewChild('carouselStage') carouselStage?: ElementRef;\r\n @ViewChild('carouselContent') carouselContent?: ElementRef;\r\n @ContentChild(TemplateRef) contentTemplate?: TemplateRef<any>;\r\n\r\n currentPageIndex = 0;\r\n totalPages = 0;\r\n isPlaying = false;\r\n isPaused = false;\r\n isHovering = false;\r\n isDragging = false;\r\n dragStartX = 0;\r\n dragCurrentX = 0;\r\n initialTransform = 0;\r\n currentTransform = 0;\r\n loadedImages: Set<string> = new Set();\r\n adjacentImagesLoaded = false;\r\n\r\n private autoPlaySubscription?: Subscription;\r\n private touchStartX = 0;\r\n private touchEndX = 0;\r\n private touchStartY = 0;\r\n private touchStartTime = 0;\r\n private swipeSubscriptions: Subscription[] = [];\r\n private mousedownSubscription?: Subscription;\r\n private mousemoveSubscription?: Subscription;\r\n private mouseupSubscription?: Subscription;\r\n private mouseleaveSubscription?: Subscription;\r\n\r\n get currentPage(): number {\r\n return this.currentPageIndex + 1;\r\n }\r\n\r\n get pages(): number[] {\r\n return Array.from({ length: this.totalPages }, (_, i) => i);\r\n }\r\n\r\n get blocks(): number[] {\r\n const blocksCount = Math.ceil(this.items.length / (this.config.itemsPerPage ?? 1));\r\n return Array.from({ length: blocksCount }, (_, i) => i);\r\n }\r\n\r\n ngOnInit() {\r\n // Verificar e ajustar config para indicador textual\r\n if (this.config.indicatorType === 'text') {\r\n this.config.indicatorPosition = 'outside';\r\n }\r\n\r\n this.calculateTotalPages();\r\n this.initializeCarousel();\r\n \r\n // Pré-carregar a primeira imagem e as adjacentes\r\n if (this.items.length > 0) {\r\n this.preloadAdjacentImages(0);\r\n }\r\n\r\n if (this.config.autoPlay) {\r\n this.play();\r\n }\r\n }\r\n\r\n ngAfterViewInit() {\r\n if (this.config.enableTouch) {\r\n this.setupTouchEvents();\r\n this.setupMouseEvents();\r\n }\r\n }\r\n\r\n ngOnDestroy() {\r\n this.stopAutoPlay();\r\n this.cleanupTouchEvents();\r\n this.cleanupMouseEvents();\r\n }\r\n\r\n onMouseEnter() {\r\n this.isHovering = true;\r\n if (this.config.autoPlay && this.isPlaying) {\r\n this.pauseAutoPlay();\r\n }\r\n }\r\n\r\n onMouseLeave() {\r\n this.isHovering = false;\r\n if (this.config.autoPlay && this.isPaused) {\r\n this.resumeAutoPlay();\r\n }\r\n }\r\n\r\n private calculateTotalPages(): void {\r\n if (this.config.navigationType === 'block') {\r\n this.totalPages = Math.ceil(this.items.length / (this.config.itemsPerPage ?? 1));\r\n } else {\r\n this.totalPages = this.items.length;\r\n }\r\n }\r\n\r\n private initializeCarousel(): void {\r\n if (this.items.length > 0) {\r\n this.items.forEach((item, index) => {\r\n item.active = index === 0;\r\n });\r\n }\r\n }\r\n\r\n goToPage(pageIndex: number): void {\r\n if (pageIndex < 0 || pageIndex >= this.totalPages) {\r\n if (this.config.loop) {\r\n pageIndex = pageIndex < 0 ? this.totalPages - 1 : 0;\r\n } else {\r\n return;\r\n }\r\n }\r\n \r\n // Pré-carregar imagens adjacentes antes da transição\r\n this.preloadAdjacentImages(pageIndex);\r\n \r\n this.currentPageIndex = pageIndex;\r\n\r\n // Atualizar estado de ativo para os itens\r\n if (this.config.navigationType === 'block') {\r\n const startIndex = this.currentPageIndex * (this.config.itemsPerPage ?? 1);\r\n this.items.forEach((item, index) => {\r\n item.active = index >= startIndex && index < startIndex + (this.config.itemsPerPage ?? 1);\r\n });\r\n } else {\r\n this.items.forEach((item, index) => {\r\n item.active = index === this.currentPageIndex;\r\n });\r\n }\r\n\r\n this.updateContentTransform(this.currentPageIndex);\r\n this.pageChange.emit(this.currentPageIndex);\r\n }\r\n\r\n // Método para pré-carregar imagens adjacentes\r\n private preloadAdjacentImages(currentIndex: number): void {\r\n // Determinar quais imagens devem ser pré-carregadas (atual, anterior e próxima)\r\n const indicesToPreload = [\r\n currentIndex,\r\n Math.max(0, currentIndex - 1),\r\n Math.min(this.totalPages - 1, currentIndex + 1)\r\n ];\r\n \r\n // Filtrar índices únicos\r\n const uniqueIndices = [...new Set(indicesToPreload)];\r\n \r\n // Pré-carregar cada imagem\r\n uniqueIndices.forEach(index => {\r\n if (index >= 0 && index < this.items.length) {\r\n const item = this.items[index];\r\n if (item.imageUrl && !this.loadedImages.has(item.imageUrl)) {\r\n this.preloadImage(item.imageUrl);\r\n }\r\n }\r\n });\r\n }\r\n\r\n // Método para pré-carregar uma única imagem\r\n private preloadImage(imageUrl: string): void {\r\n if (!imageUrl || this.loadedImages.has(imageUrl)) return;\r\n \r\n const img = new Image();\r\n img.onload = () => {\r\n this.loadedImages.add(imageUrl);\r\n };\r\n img.src = imageUrl;\r\n }\r\n\r\n // Método para aplicar a transformação ao conteúdo\r\n private updateContentTransform(pageIndex: number, animationOverride: string = ''): void {\r\n if (!this.carouselContent || !this.carouselContent.nativeElement) return;\r\n \r\n const element = this.carouselContent.nativeElement;\r\n const translateX = -pageIndex * 100;\r\n \r\n // Aplicar a transição antes de mudar a transformação\r\n element.style.transition = animationOverride || `transform ${this.config.transitionDuration}ms ease-in-out`;\r\n \r\n // Pequeno delay antes de aplicar a transformação para garantir que a transição seja registrada\r\n setTimeout(() => {\r\n element.style.transform = `translateX(${translateX}%)`;\r\n this.currentTransform = translateX;\r\n }, 10);\r\n }\r\n\r\n next(): void {\r\n this.goToPage(this.currentPageIndex + 1);\r\n }\r\n\r\n prev(): void {\r\n this.goToPage(this.currentPageIndex - 1);\r\n }\r\n\r\n play(): void {\r\n if (this.isPlaying) {\r\n return;\r\n }\r\n\r\n this.isPlaying = true;\r\n this.isPaused = false;\r\n\r\n this.autoPlaySubscription = interval(this.config.autoPlayInterval)\r\n .pipe(\r\n tap(() => {\r\n if (!this.isHovering && !this.isDragging) {\r\n if (this.currentPageIndex === this.totalPages - 1 && !this.config.loop) {\r\n this.stopAutoPlay();\r\n } else {\r\n this.next();\r\n }\r\n }\r\n })\r\n )\r\n .subscribe();\r\n }\r\n\r\n pauseAutoPlay(): void {\r\n this.isPaused = true;\r\n this.stopAutoPlay();\r\n }\r\n\r\n resumeAutoPlay(): void {\r\n if (this.isPaused) {\r\n this.play();\r\n }\r\n }\r\n\r\n pause(): void {\r\n this.pauseAutoPlay();\r\n }\r\n\r\n togglePlay(): void {\r\n if (this.isPlaying) {\r\n this.pause();\r\n } else {\r\n this.play();\r\n }\r\n }\r\n\r\n private stopAutoPlay(): void {\r\n if (this.autoPlaySubscription) {\r\n this.autoPlaySubscription.unsubscribe();\r\n this.autoPlaySubscription = undefined;\r\n this.isPlaying = false;\r\n }\r\n }\r\n\r\n private setupTouchEvents(): void {\r\n if (!this.carouselStage || !this.carouselStage.nativeElement) {\r\n return;\r\n }\r\n\r\n const element = this.carouselStage.nativeElement;\r\n\r\n // Usando eventos nativos para melhor desempenho\r\n element.addEventListener('touchstart', this.handleTouchStart.bind(this), { passive: true });\r\n element.addEventListener('touchmove', this.handleTouchMove.bind(this), { passive: false });\r\n element.addEventListener('touchend', this.handleTouchEnd.bind(this), { passive: true });\r\n }\r\n\r\n private handleTouchStart(event: TouchEvent): void {\r\n if (this.isPlaying) {\r\n this.pauseAutoPlay();\r\n }\r\n \r\n this.touchStartX = event.touches[0].clientX;\r\n this.touchStartY = event.touches[0].clientY;\r\n this.touchStartTime = Date.now();\r\n this.isDragging = true;\r\n \r\n if (this.carouselContent && this.carouselContent.nativeElement) {\r\n const style = window.getComputedStyle(this.carouselContent.nativeElement);\r\n const matrix = new WebKitCSSMatrix(style.transform);\r\n this.initialTransform = matrix.m41 / this.carouselContent.nativeElement.offsetWidth * 100;\r\n this.currentTransform = this.initialTransform;\r\n \r\n // Remover transição para movimento suave durante o arrasto\r\n this.carouselContent.nativeElement.style.transition = 'none';\r\n }\r\n }\r\n\r\n private handleTouchMove(event: TouchEvent): void {\r\n if (!this.isDragging) return;\r\n \r\n const touch = event.touches[0];\r\n const deltaX = touch.clientX - this.touchStartX;\r\n const deltaY = touch.clientY - this.touchStartY;\r\n \r\n // Verificar se o deslizamento é horizontal antes de prevenir comportamento padrão\r\n if (Math.abs(deltaX) > Math.abs(deltaY)) {\r\n event.preventDefault();\r\n }\r\n \r\n if (this.carouselContent && this.carouselContent.nativeElement) {\r\n const containerWidth = this.carouselContent.nativeElement.offsetWidth;\r\n const movePercentage = (deltaX / containerWidth) * 100;\r\n \r\n // Adicionar resistência nas bordas quando não estiver em loop\r\n let newTransform = this.initialTransform + movePercentage;\r\n \r\n if (!this.config.loop) {\r\n if (this.currentPageIndex === 0 && movePercentage > 0) {\r\n newTransform = this.initialTransform + (movePercentage / 3); // Resistência no início\r\n } else if (this.currentPageIndex === this.totalPages - 1 && movePercentage < 0) {\r\n newTransform = this.initialTransform + (movePercentage / 3); // Resistência no final\r\n }\r\n }\r\n \r\n this.carouselContent.nativeElement.style.transform = `translateX(${newTransform}%)`;\r\n this.currentTransform = newTransform;\r\n }\r\n }\r\n\r\n private handleTouchEnd(event: TouchEvent): void {\r\n if (!this.isDragging) return;\r\n \r\n const touchEndTime = Date.now();\r\n const touchDuration = touchEndTime - this.touchStartTime;\r\n this.touchEndX = event.changedTouches[0].clientX;\r\n const deltaX = this.touchEndX - this.touchStartX;\r\n \r\n // Calcular velocidade do movimento para determinar swipe\r\n const velocity = Math.abs(deltaX) / touchDuration;\r\n \r\n // Determinar o comportamento com base no movimento e velocidade\r\n let newPage = this.currentPageIndex;\r\n \r\n if (Math.abs(deltaX) > 100 || velocity > 0.5) {\r\n // Movimento significativo ou swipe rápido\r\n newPage = deltaX > 0 ? this.currentPageIndex - 1 : this.currentPageIndex + 1;\r\n } else {\r\n // Baseado na porcentagem de movimento\r\n const movedPercentage = Math.abs(deltaX) / (this.carouselStage?.nativeElement.offsetWidth || 1);\r\n if (movedPercentage > 0.2) {\r\n newPage = deltaX > 0 ? this.currentPageIndex - 1 : this.currentPageIndex + 1;\r\n }\r\n }\r\n \r\n this.isDragging = false;\r\n \r\n // Voltar para o slide atual ou ir para o próximo/anterior\r\n if (this.carouselContent && this.carouselContent.nativeElement) {\r\n this.carouselContent.nativeElement.style.transition = `transform ${this.config.transitionDuration}ms var(--animation-ease-in-out)`;\r\n this.goToPage(newPage);\r\n }\r\n \r\n // Restaurar autoplay se necessário\r\n if (this.isPaused) {\r\n this.resumeAutoPlay();\r\n }\r\n }\r\n\r\n // Adicionar suporte a eventos de mouse para desktop\r\n private setupMouseEvents(): void {\r\n if (!this.carouselStage || !this.carouselStage.nativeElement) return;\r\n \r\n const element = this.carouselStage.nativeElement;\r\n \r\n this.mousedownSubscription = fromEvent<MouseEvent>(element, 'mousedown')\r\n .subscribe(this.handleMouseDown.bind(this));\r\n \r\n this.mousemoveSubscription = fromEvent<MouseEvent>(document, 'mousemove')\r\n .subscribe(this.handleMouseMove.bind(this));\r\n \r\n this.mouseupSubscription = fromEvent<MouseEvent>(document, 'mouseup')\r\n .subscribe(this.handleMouseUp.bind(this));\r\n \r\n this.mouseleaveSubscription = fromEvent<MouseEvent>(document, 'mouseleave')\r\n .subscribe(this.handleMouseUp.bind(this));\r\n }\r\n \r\n private handleMouseDown(event: MouseEvent): void {\r\n // Só capturar cliques com botão esquerdo\r\n if (event.button !== 0) return;\r\n \r\n // Prevenir comportamento padrão (seleção de texto)\r\n event.preventDefault();\r\n \r\n if (this.isPlaying) {\r\n this.pauseAutoPlay();\r\n }\r\n \r\n this.dragStartX = event.clientX;\r\n this.isDragging = true;\r\n \r\n if (this.carouselContent && this.carouselContent.nativeElement) {\r\n const style = window.getComputedStyle(this.carouselContent.nativeElement);\r\n const matrix = new WebKitCSSMatrix(style.transform);\r\n this.initialTransform = matrix.m41 / this.carouselContent.nativeElement.offsetWidth * 100;\r\n this.currentTransform = this.initialTransform;\r\n \r\n this.carouselContent.nativeElement.style.transition = 'none';\r\n // Cursor de arrasto\r\n document.body.style.cursor = 'grabbing';\r\n }\r\n }\r\n \r\n private handleMouseMove(event: MouseEvent): void {\r\n if (!this.isDragging) return;\r\n \r\n this.dragCurrentX = event.clientX;\r\n const deltaX = this.dragCurrentX - this.dragStartX;\r\n \r\n if (this.carouselContent && this.carouselContent.nativeElement) {\r\n const containerWidth = this.carouselContent.nativeElement.offsetWidth;\r\n const movePercentage = (deltaX / containerWidth) * 100;\r\n \r\n // Adicionar resistência nas bordas quando não estiver em loop\r\n let newTransform = this.initialTransform + movePercentage;\r\n \r\n if (!this.config.loop) {\r\n if (this.currentPageIndex === 0 && movePercentage > 0) {\r\n newTransform = this.initialTransform + (movePercentage / 3);\r\n } else if (this.currentPageIndex === this.totalPages - 1 && movePercentage < 0) {\r\n newTransform = this.initialTransform + (movePercentage / 3);\r\n }\r\n }\r\n \r\n this.carouselContent.nativeElement.style.transform = `translateX(${newTransform}%)`;\r\n this.currentTransform = newTransform;\r\n }\r\n }\r\n \r\n private handleMouseUp(event: MouseEvent): void {\r\n if (!this.isDragging) return;\r\n \r\n document.body.style.cursor = '';\r\n this.isDragging = false;\r\n \r\n if (this.dragStartX !== 0 && this.dragCurrentX !== 0) {\r\n const deltaX = this.dragCurrentX - this.dragStartX;\r\n let newPage = this.currentPageIndex;\r\n \r\n // Determinar se deve mudar de slide com base na distância do movimento\r\n if (Math.abs(deltaX) > 100) {\r\n newPage = deltaX > 0 ? this.currentPageIndex - 1 : this.currentPageIndex + 1;\r\n } else {\r\n const movedPercentage = Math.abs(deltaX) / (this.carouselStage?.nativeElement.offsetWidth || 1);\r\n if (movedPercentage > 0.2) {\r\n newPage = deltaX > 0 ? this.currentPageIndex - 1 : this.currentPageIndex + 1;\r\n }\r\n }\r\n \r\n if (this.carouselContent && this.carouselContent.nativeElement) {\r\n this.carouselContent.nativeElement.style.transition = `transform ${this.config.transitionDuration}ms var(--animation-ease-in-out)`;\r\n this.goToPage(newPage);\r\n }\r\n }\r\n \r\n this.dragStartX = 0;\r\n this.dragCurrentX = 0;\r\n \r\n // Restaurar autoplay se necessário\r\n if (this.isPaused) {\r\n this.resumeAutoPlay();\r\n }\r\n }\r\n\r\n private cleanupTouchEvents(): void {\r\n if (this.carouselStage && this.carouselStage.nativeElement) {\r\n const element = this.carouselStage.nativeElement;\r\n element.removeEventListener('touchstart', this.handleTouchStart.bind(this));\r\n element.removeEventListener('touchmove', this.handleTouchMove.bind(this));\r\n element.removeEventListener('touchend', this.handleTouchEnd.bind(this));\r\n }\r\n \r\n this.swipeSubscriptions.forEach(sub => sub.unsubscribe());\r\n this.swipeSubscriptions = [];\r\n }\r\n\r\n private cleanupMouseEvents(): void {\r\n this.mousedownSubscription?.unsubscribe();\r\n this.mousemoveSubscription?.unsubscribe();\r\n this.mouseupSubscription?.unsubscribe();\r\n this.mouseleaveSubscription?.unsubscribe();\r\n }\r\n\r\n isFirstPage(): boolean {\r\n return this.currentPageIndex === 0;\r\n }\r\n\r\n isLastPage(): boolean {\r\n return this.currentPageIndex === this.totalPages - 1;\r\n }\r\n\r\n shouldDisableNavButton(direction: 'prev' | 'next'): boolean {\r\n if (this.config.loop) {\r\n return false;\r\n }\r\n\r\n return direction === 'prev' ? this.isFirstPage() : this.isLastPage();\r\n }\r\n\r\n trackByFn(index: number, item: CarouselItem): string | number {\r\n return item.id || index;\r\n }\r\n}","<div class=\"carousel-wrapper\">\r\n <!-- Botão de navegação (anterior) outside -->\r\n <button *ngIf=\"config.showNavigationButtons && config.navigationButtonsPosition === 'outside'\"\r\n class=\"carousel-nav-button carousel-prev-button outside\"\r\n [disabled]=\"shouldDisableNavButton('prev')\"\r\n (click)=\"prev()\">\r\n <i class=\"fas fa-angle-left\"></i>\r\n </button>\r\n <div class=\"carousel-container\"\r\n (mouseenter)=\"onMouseEnter()\"\r\n (mouseleave)=\"onMouseLeave()\">\r\n <!-- Botão de navegação (anterior) inside -->\r\n <button *ngIf=\"config.showNavigationButtons && config.navigationButtonsPosition === 'inside'\"\r\n class=\"carousel-nav-button carousel-prev-button inside\"\r\n [disabled]=\"shouldDisableNavButton('prev')\"\r\n (click)=\"prev()\">\r\n <i class=\"fas fa-angle-left\"></i>\r\n </button>\r\n <!-- Palco (área de conteúdo) -->\r\n <div class=\"carousel-stage\" #carouselStage\r\n [class.is-dragging]=\"isDragging\">\r\n <!-- Modificação no carousel-content -->\r\n <div class=\"carousel-content\" #carouselContent>\r\n <ng-container *ngFor=\"let item of items; let i = index; trackBy: trackByFn\">\r\n <div class=\"carousel-item\"\r\n [class.active]=\"item.active\"\r\n [class.dragging]=\"isDragging\"\r\n (click)=\"!isDragging && itemClick.emit(item)\">\r\n <!-- Renderização de imagem com tratamento para pré-carregamento -->\r\n <div *ngIf=\"item.imageUrl\" class=\"carousel-image-container\">\r\n <!-- Modificado para carregar imagem diretamente, mas usar opacity para o efeito de fade -->\r\n <img \r\n [src]=\"item.imageUrl\" \r\n [alt]=\"item.imageAlt || item.title || ''\" \r\n class=\"carousel-image\"\r\n [ngClass]=\"{'lazyloaded': loadedImages.has(item.imageUrl)}\"\r\n (load)=\"loadedImages.add(item.imageUrl)\">\r\n \r\n <!-- Imagem de placeholder enquanto carrega -->\r\n <div *ngIf=\"!loadedImages.has(item.imageUrl)\" class=\"carousel-image-placeholder\"></div>\r\n </div>\r\n\r\n <!-- Resto do conteúdo permanece igual -->\r\n <ng-container *ngIf=\"!item.imageUrl || contentTemplate\">\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: {$implicit: item}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n \r\n <!-- Botão de navegação (próximo) inside -->\r\n <button *ngIf=\"config.showNavigationButtons && config.navigationButtonsPosition === 'inside'\"\r\n class=\"carousel-nav-button carousel-next-button inside\"\r\n [disabled]=\"shouldDisableNavButton('next')\"\r\n (click)=\"next()\">\r\n <i class=\"fas fa-angle-right\"></i>\r\n </button>\r\n\r\n <!-- Botão de reprodução (interno ao palco) -->\r\n <div *ngIf=\"config.showPlayButtons && config.navigationButtonsPosition === 'inside'\"\r\n class=\"carousel-play-button-container\">\r\n <button class=\"carousel-play-button\" (click)=\"togglePlay()\">\r\n <i [class]=\"isPlaying ? 'fas fa-pause' : 'fas fa-play'\"></i>\r\n </button>\r\n </div>\r\n\r\n <!-- Indicador de páginas (interno ao palco) -->\r\n <div *ngIf=\"config.showIndicator && config.indicatorPosition === 'inside'\"\r\n class=\"carousel-indicator-container inside\">\r\n <div *ngIf=\"config.indicatorType === 'simple'\" class=\"carousel-indicator\">\r\n <span *ngFor=\"let page of pages\"\r\n class=\"indicator-dot\"\r\n [class.active]=\"page === currentPageIndex\"\r\n (click)=\"goToPage(page)\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Botão de navegação (próximo) outside -->\r\n <button *ngIf=\"config.showNavigationButtons && config.navigationButtonsPosition === 'outside'\"\r\n class=\"carousel-nav-button carousel-next-button outside\"\r\n [disabled]=\"shouldDisableNavButton('next')\"\r\n (click)=\"next()\">\r\n <i class=\"fas fa-angle-right\"></i>\r\n </button>\r\n</div>\r\n\r\n<!-- Botão de reprodução (externo ao palco) -->\r\n<div *ngIf=\"config.showPlayButtons && config.navigationButtonsPosition === 'outside'\"\r\n class=\"carousel-play-button-container outside\">\r\n <button class=\"carousel-play-button\" (click)=\"togglePlay()\">\r\n <i [class]=\"isPlaying ? 'fas fa-pause' : 'fas fa-play'\"></i>\r\n </button>\r\n</div>\r\n\r\n<!-- Indicador de páginas (externo ao palco) -->\r\n<div *ngIf=\"config.showIndicator && config.indicatorPosition === 'outside'\"\r\n class=\"carousel-indicator-container outside\">\r\n <div *ngIf=\"config.indicatorType === 'simple'\" class=\"carousel-indicator\">\r\n <span *ngFor=\"let page of pages\"\r\n class=\"indicator-dot\"\r\n [class.active]=\"page === currentPageIndex\"\r\n (click)=\"goToPage(page)\"></span>\r\n </div>\r\n <div *ngIf=\"config.indicatorType === 'text'\" class=\"carousel-indicator-text\">\r\n {{ currentPage }}/{{ totalPages }}\r\n </div>\r\n</div>\r\n\r\n<!-- Template para o conteúdo -->\r\n<ng-template #itemTemplate let-item>\r\n <ng-content *ngIf=\"!contentTemplate\"></ng-content>\r\n <ng-container *ngIf=\"contentTemplate\">\r\n <ng-container *ngTemplateOutlet=\"contentTemplate; context: {$implicit: item}\"></ng-container>\r\n </ng-container>\r\n</ng-template>\r\n<ng-content select=\"[carouselContent]\"></ng-content>","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'cfc-ds-root',\r\n template: `\r\n <router-outlet></router-outlet>\r\n `,\r\n styles: ``\r\n})\r\nexport class CfcDsRootComponent { }\r\n","export interface ComponentType {\r\n id: number;\r\n name: string;\r\n clickEventName: string;\r\n isAlready?: boolean;\r\n}\r\n\r\nexport const components: ComponentType[] = [\r\n{ id: 1, name: 'avatar', clickEventName: 'setComponent', isAlready: true },\r\n{ id: 2, name: 'breadcrumb', clickEventName: 'setComponent', isAlready: true },\r\n{ id: 3, name: 'button', clickEventName: 'setComponent', isAlready: true },\r\n{ id: 4, name: 'card', clickEventName: 'setComponent', isAlready: false },\r\n{ id: 5, name: 'carousel', clickEventName: 'setComponent', isAlready: false },\r\n{ id: 7, name: 'checkbox', clickEventName: 'setComponent', isAlready: true },\r\n{ id: 8, name: 'collapse', clickEventName: 'setComponent', isAlready: false },\r\n{ id: 9, name: 'cookie-bar', clickEventName: 'setComponent', isAlready: false },\r\n{ id: 10, name: 'datetimer-picker', clickEventName: 'setComponent', isAlready: false },\r\n{ id: 11, name: 'divider', clickEventName: 'setCom