ngx-opalbytes-components 1.29.0 → 1.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +138 -0
  2. package/fesm2022/ngx-opalbytes-components.mjs +338 -5
  3. package/fesm2022/ngx-opalbytes-components.mjs.map +1 -1
  4. package/package.json +1 -1
  5. package/src/lib/shared/components/index.ts +4 -1
  6. package/src/lib/shared/components/popover/index.ts +3 -0
  7. package/src/lib/shared/components/popover/popover.css +149 -0
  8. package/src/lib/shared/components/popover/popover.html +44 -0
  9. package/src/lib/shared/components/popover/popover.model.ts +19 -0
  10. package/src/lib/shared/components/popover/popover.spec.ts +22 -0
  11. package/src/lib/shared/components/popover/popover.stories.ts +0 -0
  12. package/src/lib/shared/components/popover/popover.ts +312 -0
  13. package/src/lib/shared/components/progress-bar/index.ts +2 -0
  14. package/src/lib/shared/components/progress-bar/progress-bar.css +141 -0
  15. package/src/lib/shared/components/progress-bar/progress-bar.html +39 -0
  16. package/src/lib/shared/components/progress-bar/progress-bar.model.ts +8 -0
  17. package/src/lib/shared/components/progress-bar/progress-bar.spec.ts +94 -0
  18. package/src/lib/shared/components/progress-bar/progress-bar.stories.ts +53 -0
  19. package/src/lib/shared/components/progress-bar/progress-bar.ts +50 -0
  20. package/src/lib/shared/components/progress-spinner/index.ts +2 -0
  21. package/src/lib/shared/components/progress-spinner/progress-spinner.css +90 -0
  22. package/src/lib/shared/components/progress-spinner/progress-spinner.html +50 -0
  23. package/src/lib/shared/components/progress-spinner/progress-spinner.model.ts +8 -0
  24. package/src/lib/shared/components/progress-spinner/progress-spinner.spec.ts +85 -0
  25. package/src/lib/shared/components/progress-spinner/progress-spinner.stories.ts +73 -0
  26. package/src/lib/shared/components/progress-spinner/progress-spinner.ts +71 -0
  27. package/types/ngx-opalbytes-components.d.ts +181 -2
package/README.md CHANGED
@@ -247,6 +247,8 @@ src/
247
247
  | ├── kpi/
248
248
  | ├── links-button/
249
249
  | ├── paginator/
250
+ | ├── progress-bar/
251
+ | ├── progress-spinner/
250
252
  | ├── radio/
251
253
  | ├── skeleton/
252
254
  | ├── slide-toggle/
@@ -2049,6 +2051,142 @@ Controle de paginação para tabelas ou listas.
2049
2051
  | --- | --- | --- |
2050
2052
  | `pageEvent` | `EventEmitter<PageEvent>` | Emitido em qualquer evento de paginação. |
2051
2053
 
2054
+ ---
2055
+ ### `CaoProgressBarComponent`
2056
+
2057
+ Barra de progresso baseada no `mat-progress-bar` do Angular Material, **sem depender do Material em runtime** (apenas `@angular/core`). Suporta os modos `determinate`, `indeterminate`, `buffer` e `query`, cores e altura configuráveis e exibição opcional do percentual.
2058
+
2059
+ **Seletor:** `<cao-progress-bar>`
2060
+
2061
+ **Tipo `CaoProgressBarMode`**
2062
+
2063
+ | Valor | Descrição |
2064
+ | --- | --- |
2065
+ | `'determinate'` | Progresso conhecido, controlado por `value` (padrão). |
2066
+ | `'indeterminate'` | Progresso desconhecido, animação contínua. |
2067
+ | `'buffer'` | Exibe `value` (progresso) e `bufferValue` (buffer), com pontos animados no restante. |
2068
+ | `'query'` | Indeterminado com a animação invertida (ex.: aguardando resposta antes de passar a `determinate`). |
2069
+
2070
+ **Atributos (Inputs)**
2071
+
2072
+ | Atributo | Tipo | Padrão | Descrição |
2073
+ | --- | --- | --- | --- |
2074
+ | `mode` | `CaoProgressBarMode` | `'determinate'` | Modo de exibição. |
2075
+ | `value` | `number` | `0` | Progresso de 0 a 100 (`determinate` e `buffer`). Valores fora do intervalo são limitados. |
2076
+ | `bufferValue` | `number` | `0` | Valor do buffer de 0 a 100 (`buffer`). |
2077
+ | `color` | `string` | `''` | Cor da barra (qualquer cor CSS). Padrão visual: `#4f46e5`. |
2078
+ | `trackColor` | `string` | `''` | Cor do trilho. Padrão visual: `#e5e7eb`. |
2079
+ | `bufferColor` | `string` | `''` | Cor do buffer. Padrão: `color` com 35% de opacidade. |
2080
+ | `height` | `string` | `'4px'` | Altura da barra. |
2081
+ | `borderRadius` | `string` | `''` | Raio da borda. Padrão: totalmente arredondada. |
2082
+ | `animationDuration` | `string` | `''` | Duração do ciclo nos modos indeterminado/query. Padrão visual: `2s`. |
2083
+ | `showValue` | `boolean` | `false` | Exibe o percentual ao lado da barra (`determinate` e `buffer`). |
2084
+ | `ariaLabel` | `string` | `''` | `aria-label` da barra. |
2085
+ | `ariaLabelledBy` | `string` | `''` | `aria-labelledby` da barra. |
2086
+ | `dataCy` | `string` | `''` | Atributo para testes E2E com Cypress. |
2087
+
2088
+ **CSS Custom Properties**
2089
+
2090
+ | Propriedade | Padrão | Descrição |
2091
+ | --- | --- | --- |
2092
+ | `--cao-progress-bar-color` | `#4f46e5` | Cor da barra. |
2093
+ | `--cao-progress-bar-track-color` | `#e5e7eb` | Cor do trilho. |
2094
+ | `--cao-progress-bar-buffer-color` | `color-mix(in srgb, <cor> 35%, transparent)` | Cor do buffer. |
2095
+ | `--cao-progress-bar-text-color` | `#374151` | Cor do percentual (`showValue`). |
2096
+ | `--cao-progress-bar-radius` | `999px` | Raio da borda. |
2097
+ | `--cao-progress-bar-duration` | `2s` | Duração do ciclo da animação. |
2098
+
2099
+ **Exemplos:**
2100
+
2101
+ ```html
2102
+ <!-- Determinate com percentual -->
2103
+ <cao-progress-bar [value]="progresso" [showValue]="true" ariaLabel="Upload do arquivo"></cao-progress-bar>
2104
+
2105
+ <!-- Indeterminate -->
2106
+ <cao-progress-bar mode="indeterminate" ariaLabel="Carregando"></cao-progress-bar>
2107
+
2108
+ <!-- Buffer -->
2109
+ <cao-progress-bar mode="buffer" [value]="30" [bufferValue]="65"></cao-progress-bar>
2110
+
2111
+ <!-- Query, cores e altura customizadas -->
2112
+ <cao-progress-bar mode="query" color="#16a34a" trackColor="#dcfce7" height="8px"></cao-progress-bar>
2113
+ ```
2114
+
2115
+ **Observações:**
2116
+
2117
+ - Usa `role="progressbar"` com `aria-valuemin`, `aria-valuemax` e `aria-valuenow` (omitido nos modos indeterminado e query). Informe `ariaLabel` ou `ariaLabelledBy` para leitores de tela.
2118
+ - `value` e `bufferValue` aceitam string (`value="50"`), convertida com `numberAttribute`.
2119
+ - Respeita `prefers-reduced-motion`: transições são removidas e a animação indeterminada fica mais lenta.
2120
+ - Não possui dependências externas.
2121
+ ---
2122
+ ### `CaoProgressSpinnerComponent`
2123
+
2124
+ Spinner de progresso circular baseado no `mat-progress-spinner` do Angular Material, **sem depender do Material em runtime** (apenas `@angular/core`; o visual é um SVG). Suporta os modos `determinate` e `indeterminate`, diâmetro, espessura, cores, trilho e percentual central configuráveis.
2125
+
2126
+ **Seletor:** `<cao-progress-spinner>`
2127
+
2128
+ **Tipos**
2129
+
2130
+ | Tipo | Valores |
2131
+ | --- | --- |
2132
+ | `CaoProgressSpinnerMode` | `'determinate'` \| `'indeterminate'` |
2133
+ | `CaoProgressSpinnerLinecap` | `'round'` \| `'butt'` \| `'square'` |
2134
+
2135
+ **Atributos (Inputs)**
2136
+
2137
+ | Atributo | Tipo | Padrão | Descrição |
2138
+ | --- | --- | --- | --- |
2139
+ | `mode` | `CaoProgressSpinnerMode` | `'indeterminate'` | Modo de exibição. |
2140
+ | `value` | `number` | `0` | Progresso de 0 a 100 (`determinate`). Valores fora do intervalo são limitados. |
2141
+ | `diameter` | `number` | `48` | Diâmetro em px (mínimo `8`). |
2142
+ | `strokeWidth` | `number` | `0` | Espessura do traço em px. `0` = automático (10% do diâmetro). |
2143
+ | `strokeLinecap` | `CaoProgressSpinnerLinecap` | `'round'` | Formato da ponta do traço. |
2144
+ | `color` | `string` | `''` | Cor do indicador (qualquer cor CSS). Padrão visual: `#4f46e5`. |
2145
+ | `trackColor` | `string` | `''` | Cor do trilho (círculo de fundo). Padrão: transparente. |
2146
+ | `animationDuration` | `string` | `''` | Duração de uma volta no modo indeterminado. Padrão visual: `1.4s`. |
2147
+ | `showValue` | `boolean` | `false` | Exibe o percentual no centro (`determinate`). |
2148
+ | `textColor` | `string` | `''` | Cor do percentual. Padrão visual: `#111827`. |
2149
+ | `ariaLabel` | `string` | `''` | `aria-label` do spinner. |
2150
+ | `ariaLabelledBy` | `string` | `''` | `aria-labelledby` do spinner. |
2151
+ | `dataCy` | `string` | `''` | Atributo para testes E2E com Cypress. |
2152
+
2153
+ **CSS Custom Properties**
2154
+
2155
+ | Propriedade | Padrão | Descrição |
2156
+ | --- | --- | --- |
2157
+ | `--cao-progress-spinner-color` | `#4f46e5` | Cor do indicador. |
2158
+ | `--cao-progress-spinner-track-color` | `transparent` | Cor do trilho. |
2159
+ | `--cao-progress-spinner-text-color` | `#111827` | Cor do percentual. |
2160
+ | `--cao-progress-spinner-duration` | `1.4s` | Duração de uma volta (indeterminado). |
2161
+
2162
+ **Exemplos:**
2163
+
2164
+ ```html
2165
+ <!-- Indeterminate -->
2166
+ <cao-progress-spinner ariaLabel="Carregando"></cao-progress-spinner>
2167
+
2168
+ <!-- Determinate com trilho e percentual -->
2169
+ <cao-progress-spinner
2170
+ mode="determinate"
2171
+ [value]="progresso"
2172
+ [diameter]="96"
2173
+ trackColor="#e5e7eb"
2174
+ [showValue]="true"
2175
+ ariaLabel="Progresso do envio">
2176
+ </cao-progress-spinner>
2177
+
2178
+ <!-- Tamanho, espessura e cor customizados -->
2179
+ <cao-progress-spinner [diameter]="24" [strokeWidth]="3" color="#16a34a"></cao-progress-spinner>
2180
+ ```
2181
+
2182
+ **Observações:**
2183
+
2184
+ - Usa `role="progressbar"` com `aria-valuemin`, `aria-valuemax` e `aria-valuenow` (omitido no modo indeterminado). Informe `ariaLabel` ou `ariaLabelledBy` para leitores de tela.
2185
+ - `value`, `diameter` e `strokeWidth` aceitam string (`diameter="64"`), convertida com `numberAttribute`.
2186
+ - O diâmetro padrão é `48` (o Material usa `100`); informe `[diameter]="100"` para o mesmo tamanho.
2187
+ - Respeita `prefers-reduced-motion`: transições são removidas e a rotação fica mais lenta.
2188
+ - Não possui dependências externas.
2189
+
2052
2190
  ---
2053
2191
 
2054
2192
  ### `CaoSkeleton`
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, ElementRef, input, computed, forwardRef, HostListener, HostBinding, ChangeDetectionStrategy, Component, DestroyRef, model, output, effect, untracked, EventEmitter, Input, Output, ViewChild, ChangeDetectorRef, Renderer2, ViewContainerRef, ViewEncapsulation, NgModule, ContentChildren, Directive, TemplateRef, ContentChild, signal, PLATFORM_ID, ViewChildren, Optional, Inject, Injectable } from '@angular/core';
2
+ import { InjectionToken, inject, ElementRef, input, computed, forwardRef, HostListener, HostBinding, ChangeDetectionStrategy, Component, DestroyRef, model, output, effect, untracked, EventEmitter, Input, Output, ViewChild, ChangeDetectorRef, Renderer2, ViewContainerRef, ViewEncapsulation, NgModule, ContentChildren, Directive, TemplateRef, ContentChild, signal, PLATFORM_ID, ViewChildren, Optional, Inject, numberAttribute, viewChild, booleanAttribute, Injectable } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
4
  import { CommonModule, isPlatformBrowser, NgTemplateOutlet, NgOptimizedImage } from '@angular/common';
5
5
  import * as i3 from '@angular/material/tooltip';
@@ -226,7 +226,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
226
226
  args: ['keydown', ['$event']]
227
227
  }] } });
228
228
 
229
- let nextId = 0;
229
+ let nextId$1 = 0;
230
230
  /**
231
231
  * Item do accordion. Pode ser usado dentro de `<cao-accordion>` ou isolado (como um cartão expansível).
232
232
  * Os inputs de cor/posição, quando informados, sobrescrevem os valores definidos no accordion.
@@ -235,8 +235,8 @@ class CaoAccordionItemComponent {
235
235
  accordion = inject(CAO_ACCORDION, { optional: true });
236
236
  destroyRef = inject(DestroyRef);
237
237
  previousExpanded = null;
238
- headerId = `cao-accordion-header-${nextId}`;
239
- panelId = `cao-accordion-panel-${nextId++}`;
238
+ headerId = `cao-accordion-header-${nextId$1}`;
239
+ panelId = `cao-accordion-panel-${nextId$1++}`;
240
240
  // ----- Conteúdo -----
241
241
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
242
242
  description = input('', ...(ngDevMode ? [{ debugName: "description" }] : []));
@@ -3556,6 +3556,339 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
3556
3556
  args: [{ selector: 'cao-breadcrumb', imports: [NgTemplateOutlet, RouterLink, CaoBaseIcon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #content let-item let-index=\"index\">\n @if (item.icon && iconPosition(item) === 'left') {\n <ng-container *ngTemplateOutlet=\"icon; context: { $implicit: item }\" />\n }\n @if (item.label) {\n <span class=\"cao-breadcrumb__label\">{{ item.label }}</span>\n }\n @if (item.icon && iconPosition(item) === 'right') {\n <ng-container *ngTemplateOutlet=\"icon; context: { $implicit: item }\" />\n }\n @if (item.badge !== undefined && item.badge !== null && item.badge !== '') {\n <span\n class=\"cao-breadcrumb__badge\"\n [style.color]=\"item.badgeColor || null\"\n [style.background-color]=\"item.badgeBgColor || null\"\n [attr.data-cy]=\"item.dataCy ? item.dataCy + '-badge' : null\">\n {{ item.badge }}\n </span>\n }\n</ng-template>\n\n<ng-template #icon let-item>\n <span class=\"cao-breadcrumb__icon\" aria-hidden=\"true\">\n <cao-base-icon\n [imgSource]=\"item.icon\"\n [isLucideIcon]=\"isLucide(item)\"\n [iconColor]=\"item.iconColor ?? ''\"\n [strokeWidthIcon]=\"item.iconStrokeWidth ?? 1.5\"\n [size]=\"item.iconSize ?? 16\" />\n </span>\n</ng-template>\n\n@if (allItems().length) {\n <nav\n class=\"cao-breadcrumb\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.data-cy]=\"dataCy() || null\"\n [style.--cao-breadcrumb-link-color]=\"linkColor() || null\"\n [style.--cao-breadcrumb-link-hover-color]=\"linkHoverColor() || null\"\n [style.--cao-breadcrumb-current-color]=\"currentColor() || null\"\n [style.--cao-breadcrumb-separator-color]=\"separatorColor() || null\"\n [style.--cao-breadcrumb-font-size]=\"fontSize() || null\"\n [style.--cao-breadcrumb-gap]=\"gap() || null\">\n <ol class=\"cao-breadcrumb__list\">\n @for (item of allItems(); track $index; let i = $index; let last = $last) {\n <li\n class=\"cao-breadcrumb__item\"\n [class.cao-breadcrumb__item--current]=\"last\"\n [class.cao-breadcrumb__item--disabled]=\"item.disabled\"\n [attr.data-cy]=\"item.dataCy || null\">\n @if (isInteractive(item, last)) {\n @if (hasLink(item)) {\n <a\n class=\"cao-breadcrumb__action\"\n [routerLink]=\"item.link\"\n [queryParams]=\"item.queryParams\"\n [target]=\"item.target ?? '_self'\"\n [attr.aria-label]=\"item.ariaLabel || null\"\n (click)=\"onItemClick(item, i, $event)\">\n <ng-container *ngTemplateOutlet=\"content; context: { $implicit: item, index: i }\" />\n </a>\n } @else if (item.href) {\n <a\n class=\"cao-breadcrumb__action\"\n [attr.href]=\"item.href\"\n [attr.target]=\"item.target || null\"\n [attr.rel]=\"item.target === '_blank' ? 'noopener noreferrer' : null\"\n [attr.aria-label]=\"item.ariaLabel || null\"\n (click)=\"onItemClick(item, i, $event)\">\n <ng-container *ngTemplateOutlet=\"content; context: { $implicit: item, index: i }\" />\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"cao-breadcrumb__action\"\n [attr.aria-label]=\"item.ariaLabel || null\"\n (click)=\"onItemClick(item, i, $event)\">\n <ng-container *ngTemplateOutlet=\"content; context: { $implicit: item, index: i }\" />\n </button>\n }\n } @else {\n <span\n class=\"cao-breadcrumb__text\"\n [attr.aria-current]=\"last ? 'page' : null\"\n [attr.aria-disabled]=\"item.disabled ? 'true' : null\"\n [attr.aria-label]=\"item.ariaLabel || null\">\n <ng-container *ngTemplateOutlet=\"content; context: { $implicit: item, index: i }\" />\n </span>\n }\n </li>\n\n @if (!last) {\n <li class=\"cao-breadcrumb__separator\" role=\"presentation\" aria-hidden=\"true\">\n @if (separatorIcon()) {\n <cao-base-icon\n [imgSource]=\"separatorIcon()\"\n [isLucideIcon]=\"isLucideSeparatorIcon()\"\n [strokeWidthIcon]=\"separatorIconStrokeWidth()\"\n [size]=\"separatorIconSize()\" />\n } @else {\n {{ separator() }}\n }\n </li>\n }\n }\n </ol>\n </nav>\n}", styles: [":host{display:block}.cao-breadcrumb{--_link: var(--cao-breadcrumb-link-color, #6b7280);--_link-hover: var(--cao-breadcrumb-link-hover-color, #4f46e5);--_current: var(--cao-breadcrumb-current-color, #111827);--_separator: var(--cao-breadcrumb-separator-color, #9ca3af);--_disabled: var(--cao-breadcrumb-disabled-color, #d1d5db);--_focus: var(--cao-breadcrumb-focus-ring, rgba(79, 70, 229, .35));--_badge-bg: var(--cao-breadcrumb-badge-bg, #eef2ff);--_badge-text: var(--cao-breadcrumb-badge-text, #4338ca);--_gap: var(--cao-breadcrumb-gap, 8px);--_size: var(--cao-breadcrumb-font-size, .875rem)}.cao-breadcrumb__list{display:flex;flex-wrap:wrap;align-items:center;gap:var(--_gap);margin:0;padding:0;list-style:none;font-size:var(--_size);line-height:1.25}.cao-breadcrumb__item,.cao-breadcrumb__separator{display:inline-flex;align-items:center}.cao-breadcrumb__separator{color:var(--_separator);-webkit-user-select:none;user-select:none}.cao-breadcrumb__action,.cao-breadcrumb__text{display:inline-flex;align-items:center;gap:6px;padding:2px 4px;border:0;border-radius:4px;background:none;color:var(--_link);font:inherit;text-decoration:none}.cao-breadcrumb__action{cursor:pointer;transition:color .15s ease}.cao-breadcrumb__action:hover{color:var(--_link-hover);text-decoration:underline;text-underline-offset:3px}.cao-breadcrumb__action:focus-visible{outline:2px solid var(--_focus);outline-offset:1px}.cao-breadcrumb__item--current .cao-breadcrumb__text{color:var(--_current);font-weight:600}.cao-breadcrumb__item--disabled .cao-breadcrumb__text{color:var(--_disabled);cursor:not-allowed}.cao-breadcrumb__icon{display:inline-flex;align-items:center;line-height:0}.cao-breadcrumb__badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;padding:1px 6px;border-radius:999px;background:var(--_badge-bg);color:var(--_badge-text);font-size:.75em;font-weight:600;line-height:1.4}@media(prefers-reduced-motion:reduce){.cao-breadcrumb__action{transition:none}}\n"] }]
3557
3557
  }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], home: [{ type: i0.Input, args: [{ isSignal: true, alias: "home", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], separatorIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "separatorIcon", required: false }] }], isLucideSeparatorIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLucideSeparatorIcon", required: false }] }], separatorIconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "separatorIconSize", required: false }] }], separatorIconStrokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "separatorIconStrokeWidth", required: false }] }], linkColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "linkColor", required: false }] }], linkHoverColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "linkHoverColor", required: false }] }], currentColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentColor", required: false }] }], separatorColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "separatorColor", required: false }] }], fontSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fontSize", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], dataCy: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataCy", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
3558
3558
 
3559
+ const clampPercent$1 = (value) => Math.min(100, Math.max(0, Number.isFinite(value) ? value : 0));
3560
+ class CaoProgressBarComponent {
3561
+ /** Modo de exibição. Padrão: `'determinate'`. */
3562
+ mode = input('determinate', ...(ngDevMode ? [{ debugName: "mode" }] : []));
3563
+ /** Progresso de 0 a 100 (modos `determinate` e `buffer`). */
3564
+ value = input(0, { ...(ngDevMode ? { debugName: "value" } : {}), transform: numberAttribute });
3565
+ /** Valor do buffer de 0 a 100 (modo `buffer`). */
3566
+ bufferValue = input(0, { ...(ngDevMode ? { debugName: "bufferValue" } : {}), transform: numberAttribute });
3567
+ /** Cor da barra de progresso (qualquer cor CSS). */
3568
+ color = input('', ...(ngDevMode ? [{ debugName: "color" }] : []));
3569
+ /** Cor do trilho. */
3570
+ trackColor = input('', ...(ngDevMode ? [{ debugName: "trackColor" }] : []));
3571
+ /** Cor do buffer (modo `buffer`). */
3572
+ bufferColor = input('', ...(ngDevMode ? [{ debugName: "bufferColor" }] : []));
3573
+ /** Altura da barra. */
3574
+ height = input('4px', ...(ngDevMode ? [{ debugName: "height" }] : []));
3575
+ /** Raio da borda. Padrão: totalmente arredondada. */
3576
+ borderRadius = input('', ...(ngDevMode ? [{ debugName: "borderRadius" }] : []));
3577
+ /** Duração do ciclo da animação nos modos indeterminado/query/buffer. */
3578
+ animationDuration = input('', ...(ngDevMode ? [{ debugName: "animationDuration" }] : []));
3579
+ /** Exibe o percentual ao lado da barra (modos `determinate` e `buffer`). */
3580
+ showValue = input(false, ...(ngDevMode ? [{ debugName: "showValue" }] : []));
3581
+ ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
3582
+ ariaLabelledBy = input('', ...(ngDevMode ? [{ debugName: "ariaLabelledBy" }] : []));
3583
+ dataCy = input('', ...(ngDevMode ? [{ debugName: "dataCy" }] : []));
3584
+ clampedValue = computed(() => clampPercent$1(this.value()), ...(ngDevMode ? [{ debugName: "clampedValue" }] : []));
3585
+ clampedBuffer = computed(() => clampPercent$1(this.bufferValue()), ...(ngDevMode ? [{ debugName: "clampedBuffer" }] : []));
3586
+ hasValue = computed(() => this.mode() === 'determinate' || this.mode() === 'buffer', ...(ngDevMode ? [{ debugName: "hasValue" }] : []));
3587
+ ariaValueNow = computed(() => this.hasValue() ? Math.round(this.clampedValue()) : null, ...(ngDevMode ? [{ debugName: "ariaValueNow" }] : []));
3588
+ valueLabel = computed(() => `${Math.round(this.clampedValue())}%`, ...(ngDevMode ? [{ debugName: "valueLabel" }] : []));
3589
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3590
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CaoProgressBarComponent, isStandalone: true, selector: "cao-progress-bar", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, bufferValue: { classPropertyName: "bufferValue", publicName: "bufferValue", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, trackColor: { classPropertyName: "trackColor", publicName: "trackColor", isSignal: true, isRequired: false, transformFunction: null }, bufferColor: { classPropertyName: "bufferColor", publicName: "bufferColor", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, borderRadius: { classPropertyName: "borderRadius", publicName: "borderRadius", isSignal: true, isRequired: false, transformFunction: null }, animationDuration: { classPropertyName: "animationDuration", publicName: "animationDuration", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "ariaLabelledBy", isSignal: true, isRequired: false, transformFunction: null }, dataCy: { classPropertyName: "dataCy", publicName: "dataCy", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"cao-progress-bar\"\n [style.--cao-progress-bar-color]=\"color() || null\"\n [style.--cao-progress-bar-track-color]=\"trackColor() || null\"\n [style.--cao-progress-bar-buffer-color]=\"bufferColor() || null\"\n [style.--cao-progress-bar-duration]=\"animationDuration() || null\">\n <div\n class=\"cao-progress-bar__track\"\n role=\"progressbar\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-valuenow]=\"ariaValueNow()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.data-cy]=\"dataCy() || null\"\n [style.height]=\"height()\"\n [style.border-radius]=\"borderRadius() || null\">\n @switch (mode()) {\n @case ('determinate') {\n <div class=\"cao-progress-bar__fill\" [style.width.%]=\"clampedValue()\"></div>\n }\n @case ('buffer') {\n <div class=\"cao-progress-bar__dots\" [style.left.%]=\"clampedBuffer()\"></div>\n <div class=\"cao-progress-bar__buffer\" [style.width.%]=\"clampedBuffer()\"></div>\n <div class=\"cao-progress-bar__fill\" [style.width.%]=\"clampedValue()\"></div>\n }\n @default {\n <div class=\"cao-progress-bar__inner\" [class.cao-progress-bar__inner--query]=\"mode() === 'query'\">\n <div class=\"cao-progress-bar__bar cao-progress-bar__bar--primary\"></div>\n <div class=\"cao-progress-bar__bar cao-progress-bar__bar--secondary\"></div>\n </div>\n }\n }\n </div>\n\n @if (showValue() && hasValue()) {\n <span class=\"cao-progress-bar__value\" aria-hidden=\"true\">{{ valueLabel() }}</span>\n }\n</div>", styles: [":host{display:block;width:100%}.cao-progress-bar{--_color: var(--cao-progress-bar-color, #4f46e5);--_track: var(--cao-progress-bar-track-color, #e5e7eb);--_buffer: var(--cao-progress-bar-buffer-color, color-mix(in srgb, var(--_color) 35%, transparent));--_duration: var(--cao-progress-bar-duration, 2s);--_text: var(--cao-progress-bar-text-color, #374151);display:flex;align-items:center;gap:8px}.cao-progress-bar__track{position:relative;flex:1 1 auto;min-width:0;overflow:hidden;border-radius:var(--cao-progress-bar-radius, 999px);background-color:var(--_track)}.cao-progress-bar__fill,.cao-progress-bar__buffer{position:absolute;top:0;bottom:0;left:0;border-radius:inherit;transition:width .25s ease}.cao-progress-bar__fill{z-index:1;background-color:var(--_color)}.cao-progress-bar__buffer{background-color:var(--_buffer)}.cao-progress-bar__dots{position:absolute;top:0;right:0;bottom:0;background-image:radial-gradient(circle closest-side,var(--_buffer) 0 70%,transparent 75%);background-size:8px 100%;animation:cao-progress-bar-dots .6s linear infinite}.cao-progress-bar__inner{position:absolute;inset:0}.cao-progress-bar__inner--query{transform:scaleX(-1)}.cao-progress-bar__bar{position:absolute;top:0;bottom:0;left:0;width:100%;background-color:var(--_color);transform-origin:left center;will-change:transform}.cao-progress-bar__bar--primary{animation:cao-progress-bar-primary var(--_duration) cubic-bezier(.4,0,.2,1) infinite}.cao-progress-bar__bar--secondary{animation:cao-progress-bar-secondary var(--_duration) cubic-bezier(.4,0,.2,1) infinite}.cao-progress-bar__value{flex:0 0 auto;min-width:2.75em;color:var(--_text);font-size:.75rem;font-variant-numeric:tabular-nums;line-height:1;text-align:right}@keyframes cao-progress-bar-primary{0%{transform:translate(-100%) scaleX(.2)}40%{transform:translate(10%) scaleX(.6)}to{transform:translate(100%) scaleX(.2)}}@keyframes cao-progress-bar-secondary{0%{transform:translate(-100%) scaleX(.1)}50%{transform:translate(-100%) scaleX(.1)}80%{transform:translate(40%) scaleX(.4)}to{transform:translate(100%) scaleX(.1)}}@keyframes cao-progress-bar-dots{to{background-position-x:-8px}}@media(prefers-reduced-motion:reduce){.cao-progress-bar__fill,.cao-progress-bar__buffer{transition:none}.cao-progress-bar__bar--primary,.cao-progress-bar__bar--secondary{animation-duration:calc(var(--_duration) * 3)}.cao-progress-bar__dots{animation:none}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3591
+ }
3592
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoProgressBarComponent, decorators: [{
3593
+ type: Component,
3594
+ args: [{ selector: 'cao-progress-bar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"cao-progress-bar\"\n [style.--cao-progress-bar-color]=\"color() || null\"\n [style.--cao-progress-bar-track-color]=\"trackColor() || null\"\n [style.--cao-progress-bar-buffer-color]=\"bufferColor() || null\"\n [style.--cao-progress-bar-duration]=\"animationDuration() || null\">\n <div\n class=\"cao-progress-bar__track\"\n role=\"progressbar\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-valuenow]=\"ariaValueNow()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.data-cy]=\"dataCy() || null\"\n [style.height]=\"height()\"\n [style.border-radius]=\"borderRadius() || null\">\n @switch (mode()) {\n @case ('determinate') {\n <div class=\"cao-progress-bar__fill\" [style.width.%]=\"clampedValue()\"></div>\n }\n @case ('buffer') {\n <div class=\"cao-progress-bar__dots\" [style.left.%]=\"clampedBuffer()\"></div>\n <div class=\"cao-progress-bar__buffer\" [style.width.%]=\"clampedBuffer()\"></div>\n <div class=\"cao-progress-bar__fill\" [style.width.%]=\"clampedValue()\"></div>\n }\n @default {\n <div class=\"cao-progress-bar__inner\" [class.cao-progress-bar__inner--query]=\"mode() === 'query'\">\n <div class=\"cao-progress-bar__bar cao-progress-bar__bar--primary\"></div>\n <div class=\"cao-progress-bar__bar cao-progress-bar__bar--secondary\"></div>\n </div>\n }\n }\n </div>\n\n @if (showValue() && hasValue()) {\n <span class=\"cao-progress-bar__value\" aria-hidden=\"true\">{{ valueLabel() }}</span>\n }\n</div>", styles: [":host{display:block;width:100%}.cao-progress-bar{--_color: var(--cao-progress-bar-color, #4f46e5);--_track: var(--cao-progress-bar-track-color, #e5e7eb);--_buffer: var(--cao-progress-bar-buffer-color, color-mix(in srgb, var(--_color) 35%, transparent));--_duration: var(--cao-progress-bar-duration, 2s);--_text: var(--cao-progress-bar-text-color, #374151);display:flex;align-items:center;gap:8px}.cao-progress-bar__track{position:relative;flex:1 1 auto;min-width:0;overflow:hidden;border-radius:var(--cao-progress-bar-radius, 999px);background-color:var(--_track)}.cao-progress-bar__fill,.cao-progress-bar__buffer{position:absolute;top:0;bottom:0;left:0;border-radius:inherit;transition:width .25s ease}.cao-progress-bar__fill{z-index:1;background-color:var(--_color)}.cao-progress-bar__buffer{background-color:var(--_buffer)}.cao-progress-bar__dots{position:absolute;top:0;right:0;bottom:0;background-image:radial-gradient(circle closest-side,var(--_buffer) 0 70%,transparent 75%);background-size:8px 100%;animation:cao-progress-bar-dots .6s linear infinite}.cao-progress-bar__inner{position:absolute;inset:0}.cao-progress-bar__inner--query{transform:scaleX(-1)}.cao-progress-bar__bar{position:absolute;top:0;bottom:0;left:0;width:100%;background-color:var(--_color);transform-origin:left center;will-change:transform}.cao-progress-bar__bar--primary{animation:cao-progress-bar-primary var(--_duration) cubic-bezier(.4,0,.2,1) infinite}.cao-progress-bar__bar--secondary{animation:cao-progress-bar-secondary var(--_duration) cubic-bezier(.4,0,.2,1) infinite}.cao-progress-bar__value{flex:0 0 auto;min-width:2.75em;color:var(--_text);font-size:.75rem;font-variant-numeric:tabular-nums;line-height:1;text-align:right}@keyframes cao-progress-bar-primary{0%{transform:translate(-100%) scaleX(.2)}40%{transform:translate(10%) scaleX(.6)}to{transform:translate(100%) scaleX(.2)}}@keyframes cao-progress-bar-secondary{0%{transform:translate(-100%) scaleX(.1)}50%{transform:translate(-100%) scaleX(.1)}80%{transform:translate(40%) scaleX(.4)}to{transform:translate(100%) scaleX(.1)}}@keyframes cao-progress-bar-dots{to{background-position-x:-8px}}@media(prefers-reduced-motion:reduce){.cao-progress-bar__fill,.cao-progress-bar__buffer{transition:none}.cao-progress-bar__bar--primary,.cao-progress-bar__bar--secondary{animation-duration:calc(var(--_duration) * 3)}.cao-progress-bar__dots{animation:none}}\n"] }]
3595
+ }], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], bufferValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "bufferValue", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], bufferColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "bufferColor", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], animationDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "animationDuration", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledBy", required: false }] }], dataCy: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataCy", required: false }] }] } });
3596
+
3597
+ const MIN_DIAMETER = 8;
3598
+ const clampPercent = (value) => Math.min(100, Math.max(0, Number.isFinite(value) ? value : 0));
3599
+ class CaoProgressSpinnerComponent {
3600
+ /** Modo de exibição. Padrão: `'indeterminate'`. */
3601
+ mode = input('indeterminate', ...(ngDevMode ? [{ debugName: "mode" }] : []));
3602
+ /** Progresso de 0 a 100 (modo `determinate`). */
3603
+ value = input(0, { ...(ngDevMode ? { debugName: "value" } : {}), transform: numberAttribute });
3604
+ /** Diâmetro em px. */
3605
+ diameter = input(48, { ...(ngDevMode ? { debugName: "diameter" } : {}), transform: numberAttribute });
3606
+ /** Espessura do traço em px. `0` = automático (10% do diâmetro). */
3607
+ strokeWidth = input(0, { ...(ngDevMode ? { debugName: "strokeWidth" } : {}), transform: numberAttribute });
3608
+ /** Formato da ponta do traço. */
3609
+ strokeLinecap = input('round', ...(ngDevMode ? [{ debugName: "strokeLinecap" }] : []));
3610
+ /** Cor do indicador (qualquer cor CSS). */
3611
+ color = input('', ...(ngDevMode ? [{ debugName: "color" }] : []));
3612
+ /** Cor do trilho (círculo de fundo). Padrão: transparente. */
3613
+ trackColor = input('', ...(ngDevMode ? [{ debugName: "trackColor" }] : []));
3614
+ /** Duração de uma volta completa no modo indeterminado. */
3615
+ animationDuration = input('', ...(ngDevMode ? [{ debugName: "animationDuration" }] : []));
3616
+ /** Exibe o percentual no centro (modo `determinate`). */
3617
+ showValue = input(false, ...(ngDevMode ? [{ debugName: "showValue" }] : []));
3618
+ /** Cor do percentual. */
3619
+ textColor = input('', ...(ngDevMode ? [{ debugName: "textColor" }] : []));
3620
+ ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
3621
+ ariaLabelledBy = input('', ...(ngDevMode ? [{ debugName: "ariaLabelledBy" }] : []));
3622
+ dataCy = input('', ...(ngDevMode ? [{ debugName: "dataCy" }] : []));
3623
+ isDeterminate = computed(() => this.mode() === 'determinate', ...(ngDevMode ? [{ debugName: "isDeterminate" }] : []));
3624
+ size = computed(() => {
3625
+ const diameter = this.diameter();
3626
+ return Number.isFinite(diameter) ? Math.max(MIN_DIAMETER, diameter) : 48;
3627
+ }, ...(ngDevMode ? [{ debugName: "size" }] : []));
3628
+ stroke = computed(() => {
3629
+ const width = this.strokeWidth();
3630
+ const raw = width > 0 ? width : this.size() * 0.1;
3631
+ return Math.min(Math.max(raw, 1), this.size() / 2);
3632
+ }, ...(ngDevMode ? [{ debugName: "stroke" }] : []));
3633
+ center = computed(() => this.size() / 2, ...(ngDevMode ? [{ debugName: "center" }] : []));
3634
+ radius = computed(() => (this.size() - this.stroke()) / 2, ...(ngDevMode ? [{ debugName: "radius" }] : []));
3635
+ circumference = computed(() => 2 * Math.PI * this.radius(), ...(ngDevMode ? [{ debugName: "circumference" }] : []));
3636
+ clampedValue = computed(() => clampPercent(this.value()), ...(ngDevMode ? [{ debugName: "clampedValue" }] : []));
3637
+ dashOffset = computed(() => this.isDeterminate() ? this.circumference() * (1 - this.clampedValue() / 100) : null, ...(ngDevMode ? [{ debugName: "dashOffset" }] : []));
3638
+ ariaValueNow = computed(() => this.isDeterminate() ? Math.round(this.clampedValue()) : null, ...(ngDevMode ? [{ debugName: "ariaValueNow" }] : []));
3639
+ valueLabel = computed(() => `${Math.round(this.clampedValue())}%`, ...(ngDevMode ? [{ debugName: "valueLabel" }] : []));
3640
+ fontSize = computed(() => Math.max(8, Math.round(this.size() * 0.24)), ...(ngDevMode ? [{ debugName: "fontSize" }] : []));
3641
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoProgressSpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3642
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CaoProgressSpinnerComponent, isStandalone: true, selector: "cao-progress-spinner", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, diameter: { classPropertyName: "diameter", publicName: "diameter", isSignal: true, isRequired: false, transformFunction: null }, strokeWidth: { classPropertyName: "strokeWidth", publicName: "strokeWidth", isSignal: true, isRequired: false, transformFunction: null }, strokeLinecap: { classPropertyName: "strokeLinecap", publicName: "strokeLinecap", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, trackColor: { classPropertyName: "trackColor", publicName: "trackColor", isSignal: true, isRequired: false, transformFunction: null }, animationDuration: { classPropertyName: "animationDuration", publicName: "animationDuration", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, textColor: { classPropertyName: "textColor", publicName: "textColor", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "ariaLabelledBy", isSignal: true, isRequired: false, transformFunction: null }, dataCy: { classPropertyName: "dataCy", publicName: "dataCy", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"cao-progress-spinner\"\n role=\"progressbar\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [class.cao-progress-spinner--determinate]=\"isDeterminate()\"\n [class.cao-progress-spinner--indeterminate]=\"!isDeterminate()\"\n [attr.aria-valuenow]=\"ariaValueNow()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.data-cy]=\"dataCy() || null\"\n [style.width.px]=\"size()\"\n [style.height.px]=\"size()\"\n [style.--cao-progress-spinner-color]=\"color() || null\"\n [style.--cao-progress-spinner-track-color]=\"trackColor() || null\"\n [style.--cao-progress-spinner-duration]=\"animationDuration() || null\"\n [style.--cao-progress-spinner-text-color]=\"textColor() || null\"\n [style.--cao-progress-spinner-circumference]=\"circumference() + 'px'\">\n <svg\n class=\"cao-progress-spinner__svg\"\n focusable=\"false\"\n aria-hidden=\"true\"\n [attr.width]=\"size()\"\n [attr.height]=\"size()\"\n [attr.viewBox]=\"'0 0 ' + size() + ' ' + size()\">\n <circle\n class=\"cao-progress-spinner__track\"\n fill=\"none\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"stroke()\" />\n <circle\n class=\"cao-progress-spinner__indicator\"\n fill=\"none\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"stroke()\"\n [attr.stroke-linecap]=\"strokeLinecap()\"\n [attr.stroke-dasharray]=\"circumference()\"\n [attr.stroke-dashoffset]=\"dashOffset()\" />\n </svg>\n\n @if (showValue() && isDeterminate()) {\n <span class=\"cao-progress-spinner__value\" aria-hidden=\"true\" [style.font-size.px]=\"fontSize()\">\n {{ valueLabel() }}\n </span>\n }\n</div>", styles: [":host{display:inline-block;line-height:0}.cao-progress-spinner{--_color: var(--cao-progress-spinner-color, #4f46e5);--_track: var(--cao-progress-spinner-track-color, transparent);--_duration: var(--cao-progress-spinner-duration, 1.4s);--_text: var(--cao-progress-spinner-text-color, #111827);--_circ: var(--cao-progress-spinner-circumference, 0px);position:relative;display:inline-flex;align-items:center;justify-content:center}.cao-progress-spinner__svg{display:block;width:100%;height:100%}.cao-progress-spinner__track{stroke:var(--_track)}.cao-progress-spinner__indicator{stroke:var(--_color);transform:rotate(-90deg);transform-origin:50% 50%;transition:stroke-dashoffset .3s ease}.cao-progress-spinner__value{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--_text);font-variant-numeric:tabular-nums;font-weight:600;line-height:1}.cao-progress-spinner--indeterminate .cao-progress-spinner__svg{animation:cao-progress-spinner-rotate var(--_duration) linear infinite}.cao-progress-spinner--indeterminate .cao-progress-spinner__indicator{animation:cao-progress-spinner-dash calc(var(--_duration) * 1.4) ease-in-out infinite;transition:none}@keyframes cao-progress-spinner-rotate{to{transform:rotate(360deg)}}@keyframes cao-progress-spinner-dash{0%{stroke-dashoffset:calc(var(--_circ) * .95);transform:rotate(-90deg)}50%{stroke-dashoffset:calc(var(--_circ) * .25);transform:rotate(45deg)}to{stroke-dashoffset:calc(var(--_circ) * .95);transform:rotate(270deg)}}@media(prefers-reduced-motion:reduce){.cao-progress-spinner__indicator{transition:none}.cao-progress-spinner--indeterminate .cao-progress-spinner__svg{animation-duration:calc(var(--_duration) * 3)}.cao-progress-spinner--indeterminate .cao-progress-spinner__indicator{animation-duration:calc(var(--_duration) * 4.2)}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3643
+ }
3644
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoProgressSpinnerComponent, decorators: [{
3645
+ type: Component,
3646
+ args: [{ selector: 'cao-progress-spinner', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"cao-progress-spinner\"\n role=\"progressbar\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [class.cao-progress-spinner--determinate]=\"isDeterminate()\"\n [class.cao-progress-spinner--indeterminate]=\"!isDeterminate()\"\n [attr.aria-valuenow]=\"ariaValueNow()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.data-cy]=\"dataCy() || null\"\n [style.width.px]=\"size()\"\n [style.height.px]=\"size()\"\n [style.--cao-progress-spinner-color]=\"color() || null\"\n [style.--cao-progress-spinner-track-color]=\"trackColor() || null\"\n [style.--cao-progress-spinner-duration]=\"animationDuration() || null\"\n [style.--cao-progress-spinner-text-color]=\"textColor() || null\"\n [style.--cao-progress-spinner-circumference]=\"circumference() + 'px'\">\n <svg\n class=\"cao-progress-spinner__svg\"\n focusable=\"false\"\n aria-hidden=\"true\"\n [attr.width]=\"size()\"\n [attr.height]=\"size()\"\n [attr.viewBox]=\"'0 0 ' + size() + ' ' + size()\">\n <circle\n class=\"cao-progress-spinner__track\"\n fill=\"none\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"stroke()\" />\n <circle\n class=\"cao-progress-spinner__indicator\"\n fill=\"none\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"stroke()\"\n [attr.stroke-linecap]=\"strokeLinecap()\"\n [attr.stroke-dasharray]=\"circumference()\"\n [attr.stroke-dashoffset]=\"dashOffset()\" />\n </svg>\n\n @if (showValue() && isDeterminate()) {\n <span class=\"cao-progress-spinner__value\" aria-hidden=\"true\" [style.font-size.px]=\"fontSize()\">\n {{ valueLabel() }}\n </span>\n }\n</div>", styles: [":host{display:inline-block;line-height:0}.cao-progress-spinner{--_color: var(--cao-progress-spinner-color, #4f46e5);--_track: var(--cao-progress-spinner-track-color, transparent);--_duration: var(--cao-progress-spinner-duration, 1.4s);--_text: var(--cao-progress-spinner-text-color, #111827);--_circ: var(--cao-progress-spinner-circumference, 0px);position:relative;display:inline-flex;align-items:center;justify-content:center}.cao-progress-spinner__svg{display:block;width:100%;height:100%}.cao-progress-spinner__track{stroke:var(--_track)}.cao-progress-spinner__indicator{stroke:var(--_color);transform:rotate(-90deg);transform-origin:50% 50%;transition:stroke-dashoffset .3s ease}.cao-progress-spinner__value{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--_text);font-variant-numeric:tabular-nums;font-weight:600;line-height:1}.cao-progress-spinner--indeterminate .cao-progress-spinner__svg{animation:cao-progress-spinner-rotate var(--_duration) linear infinite}.cao-progress-spinner--indeterminate .cao-progress-spinner__indicator{animation:cao-progress-spinner-dash calc(var(--_duration) * 1.4) ease-in-out infinite;transition:none}@keyframes cao-progress-spinner-rotate{to{transform:rotate(360deg)}}@keyframes cao-progress-spinner-dash{0%{stroke-dashoffset:calc(var(--_circ) * .95);transform:rotate(-90deg)}50%{stroke-dashoffset:calc(var(--_circ) * .25);transform:rotate(45deg)}to{stroke-dashoffset:calc(var(--_circ) * .95);transform:rotate(270deg)}}@media(prefers-reduced-motion:reduce){.cao-progress-spinner__indicator{transition:none}.cao-progress-spinner--indeterminate .cao-progress-spinner__svg{animation-duration:calc(var(--_duration) * 3)}.cao-progress-spinner--indeterminate .cao-progress-spinner__indicator{animation-duration:calc(var(--_duration) * 4.2)}}\n"] }]
3647
+ }], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], diameter: [{ type: i0.Input, args: [{ isSignal: true, alias: "diameter", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], strokeLinecap: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeLinecap", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], trackColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackColor", required: false }] }], animationDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "animationDuration", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], textColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "textColor", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledBy", required: false }] }], dataCy: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataCy", required: false }] }] } });
3648
+
3649
+ const CAO_POPOVER_POSITION_PREFIX = 'cao-popover-pos-';
3650
+ const OPPOSITE = {
3651
+ top: 'bottom',
3652
+ bottom: 'top',
3653
+ left: 'right',
3654
+ right: 'left',
3655
+ };
3656
+ const PERPENDICULAR = {
3657
+ top: ['right', 'left'],
3658
+ bottom: ['right', 'left'],
3659
+ left: ['bottom', 'top'],
3660
+ right: ['bottom', 'top'],
3661
+ };
3662
+ function toConnectedPosition(position, align, offset) {
3663
+ const panelClass = `${CAO_POPOVER_POSITION_PREFIX}${position}`;
3664
+ if (position === 'top' || position === 'bottom') {
3665
+ return {
3666
+ originX: align,
3667
+ originY: position === 'bottom' ? 'bottom' : 'top',
3668
+ overlayX: align,
3669
+ overlayY: position === 'bottom' ? 'top' : 'bottom',
3670
+ offsetY: position === 'bottom' ? offset : -offset,
3671
+ panelClass,
3672
+ };
3673
+ }
3674
+ const vertical = align === 'start' ? 'top' : align === 'end' ? 'bottom' : 'center';
3675
+ return {
3676
+ originX: position === 'right' ? 'end' : 'start',
3677
+ originY: vertical,
3678
+ overlayX: position === 'right' ? 'start' : 'end',
3679
+ overlayY: vertical,
3680
+ offsetX: position === 'right' ? offset : -offset,
3681
+ panelClass,
3682
+ };
3683
+ }
3684
+ /** Posição preferida seguida das alternativas (oposta e perpendiculares) usadas quando não há espaço. */
3685
+ function buildPopoverPositions(position, align, offset) {
3686
+ const order = [position, OPPOSITE[position], ...PERPENDICULAR[position]];
3687
+ return order.map((item) => toConnectedPosition(item, align, offset));
3688
+ }
3689
+ const FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
3690
+ let nextId = 0;
3691
+ class CaoPopoverComponent {
3692
+ overlay = inject(Overlay);
3693
+ viewContainerRef = inject(ViewContainerRef);
3694
+ destroyRef = inject(DestroyRef);
3695
+ panelTemplate = viewChild.required('panelTemplate');
3696
+ overlayRef = null;
3697
+ origin = null;
3698
+ subscriptions = new Subscription();
3699
+ focusMoved = false;
3700
+ openState = signal(false, ...(ngDevMode ? [{ debugName: "openState" }] : []));
3701
+ panelId = `cao-popover-${nextId++}`;
3702
+ placement = signal('bottom', ...(ngDevMode ? [{ debugName: "placement" }] : []));
3703
+ /** Lado do elemento de origem em que o popover aparece. Se não houver espaço, o CDK escolhe outro lado. */
3704
+ position = input('bottom', ...(ngDevMode ? [{ debugName: "position" }] : []));
3705
+ /** Alinhamento em relação ao elemento de origem. */
3706
+ align = input('center', ...(ngDevMode ? [{ debugName: "align" }] : []));
3707
+ /** Distância (px) entre a origem e o popover. */
3708
+ offset = input(10, { ...(ngDevMode ? { debugName: "offset" } : {}), transform: numberAttribute });
3709
+ /** Exibe a seta apontando para a origem. */
3710
+ showArrow = input(true, { ...(ngDevMode ? { debugName: "showArrow" } : {}), transform: booleanAttribute });
3711
+ /** Fecha ao clicar fora do popover. */
3712
+ dismissable = input(true, { ...(ngDevMode ? { debugName: "dismissable" } : {}), transform: booleanAttribute });
3713
+ /** Fecha ao pressionar `Esc`. */
3714
+ closeOnEscape = input(true, { ...(ngDevMode ? { debugName: "closeOnEscape" } : {}), transform: booleanAttribute });
3715
+ /** Exibe o botão de fechar no canto superior direito. */
3716
+ showCloseIcon = input(false, { ...(ngDevMode ? { debugName: "showCloseIcon" } : {}), transform: booleanAttribute });
3717
+ /** Move o foco para o primeiro elemento focável do popover ao abrir (e devolve à origem ao fechar). */
3718
+ focusOnShow = input(true, { ...(ngDevMode ? { debugName: "focusOnShow" } : {}), transform: booleanAttribute });
3719
+ /** Largura fixa do popover (ex.: `'320px'`). */
3720
+ width = input('', ...(ngDevMode ? [{ debugName: "width" }] : []));
3721
+ /** Largura máxima. */
3722
+ maxWidth = input('360px', ...(ngDevMode ? [{ debugName: "maxWidth" }] : []));
3723
+ bgColor = input('', ...(ngDevMode ? [{ debugName: "bgColor" }] : []));
3724
+ textColor = input('', ...(ngDevMode ? [{ debugName: "textColor" }] : []));
3725
+ borderColor = input('', ...(ngDevMode ? [{ debugName: "borderColor" }] : []));
3726
+ borderRadius = input('', ...(ngDevMode ? [{ debugName: "borderRadius" }] : []));
3727
+ padding = input('', ...(ngDevMode ? [{ debugName: "padding" }] : []));
3728
+ /** Classe(s) CSS adicionais aplicadas ao painel do popover. */
3729
+ styleClass = input('', ...(ngDevMode ? [{ debugName: "styleClass" }] : []));
3730
+ /** Classe(s) CSS adicionais aplicadas ao painel do overlay (CDK). */
3731
+ panelClass = input('', ...(ngDevMode ? [{ debugName: "panelClass" }] : []));
3732
+ role = input('dialog', ...(ngDevMode ? [{ debugName: "role" }] : []));
3733
+ ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : []));
3734
+ ariaLabelledBy = input('', ...(ngDevMode ? [{ debugName: "ariaLabelledBy" }] : []));
3735
+ closeAriaLabel = input('Fechar', ...(ngDevMode ? [{ debugName: "closeAriaLabel" }] : []));
3736
+ dataCy = input('', ...(ngDevMode ? [{ debugName: "dataCy" }] : []));
3737
+ /** Emitido após o popover ser aberto. */
3738
+ shown = output();
3739
+ /** Emitido após o popover ser fechado. */
3740
+ hidden = output();
3741
+ /** Emitido quando o ponteiro entra/sai do painel (usado pelo gatilho `hover`). */
3742
+ panelHoverChange = output();
3743
+ /** `true` enquanto o popover está aberto. */
3744
+ isOpen = this.openState.asReadonly();
3745
+ constructor() {
3746
+ this.destroyRef.onDestroy(() => this.dispose());
3747
+ }
3748
+ /** Abre o popover se estiver fechado (ou aberto em outra origem); fecha se já estiver aberto na mesma origem. */
3749
+ toggle(event, target, options = {}) {
3750
+ const origin = this.resolveOrigin(event, target);
3751
+ if (!origin) {
3752
+ return;
3753
+ }
3754
+ if (this.openState() && this.origin === origin) {
3755
+ this.hide();
3756
+ return;
3757
+ }
3758
+ this.show(event, origin, options);
3759
+ }
3760
+ /** Abre o popover ancorado em `target` (ou em `event.currentTarget`). */
3761
+ show(event, target, options = {}) {
3762
+ const origin = this.resolveOrigin(event, target);
3763
+ if (!origin) {
3764
+ return;
3765
+ }
3766
+ if (this.openState()) {
3767
+ if (this.origin === origin) {
3768
+ return;
3769
+ }
3770
+ this.close(false);
3771
+ }
3772
+ this.origin = origin;
3773
+ this.placement.set(this.position());
3774
+ const positionStrategy = this.overlay
3775
+ .position()
3776
+ .flexibleConnectedTo(origin)
3777
+ .withPositions(buildPopoverPositions(this.position(), this.align(), this.offset()))
3778
+ .withFlexibleDimensions(false)
3779
+ .withPush(false)
3780
+ .withViewportMargin(8);
3781
+ const overlayRef = this.overlay.create({
3782
+ positionStrategy,
3783
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
3784
+ panelClass: this.panelClass(),
3785
+ });
3786
+ this.overlayRef = overlayRef;
3787
+ this.subscriptions.add(positionStrategy.positionChanges.subscribe((change) => this.onPositionChange(change)));
3788
+ this.subscriptions.add(overlayRef.outsidePointerEvents().subscribe((event) => {
3789
+ if (this.dismissable() && !this.origin?.contains(event.target)) {
3790
+ this.close(false);
3791
+ }
3792
+ }));
3793
+ this.subscriptions.add(overlayRef.keydownEvents().subscribe((event) => {
3794
+ if (event.key === 'Escape' && this.closeOnEscape()) {
3795
+ event.preventDefault();
3796
+ this.close(true);
3797
+ }
3798
+ }));
3799
+ overlayRef.attach(new TemplatePortal(this.panelTemplate(), this.viewContainerRef));
3800
+ this.openState.set(true);
3801
+ this.setOriginAria(origin, true);
3802
+ if (options.focus ?? this.focusOnShow()) {
3803
+ this.focusPanel(overlayRef.overlayElement);
3804
+ }
3805
+ this.shown.emit();
3806
+ }
3807
+ /** Fecha o popover. */
3808
+ hide() {
3809
+ this.close(true);
3810
+ }
3811
+ /** Recalcula a posição (útil se a origem mudou de lugar ou o conteúdo mudou de tamanho). */
3812
+ reposition() {
3813
+ this.overlayRef?.updatePosition();
3814
+ }
3815
+ /** Indica se o nó está dentro do painel do popover aberto. */
3816
+ containsNode(node) {
3817
+ return !!node && !!this.overlayRef?.overlayElement.contains(node);
3818
+ }
3819
+ onCloseClick() {
3820
+ this.close(true);
3821
+ }
3822
+ close(restoreFocus) {
3823
+ const overlayRef = this.overlayRef;
3824
+ if (!overlayRef) {
3825
+ return;
3826
+ }
3827
+ const origin = this.origin;
3828
+ const shouldRestoreFocus = restoreFocus && this.focusMoved;
3829
+ this.overlayRef = null;
3830
+ this.origin = null;
3831
+ this.focusMoved = false;
3832
+ this.subscriptions.unsubscribe();
3833
+ this.subscriptions = new Subscription();
3834
+ overlayRef.dispose();
3835
+ this.openState.set(false);
3836
+ this.setOriginAria(origin, false);
3837
+ if (shouldRestoreFocus) {
3838
+ origin?.focus({ preventScroll: true });
3839
+ }
3840
+ this.hidden.emit();
3841
+ }
3842
+ dispose() {
3843
+ this.subscriptions.unsubscribe();
3844
+ this.overlayRef?.dispose();
3845
+ this.overlayRef = null;
3846
+ this.origin = null;
3847
+ }
3848
+ onPositionChange(change) {
3849
+ const panelClass = change.connectionPair.panelClass;
3850
+ const value = Array.isArray(panelClass) ? panelClass[0] : panelClass;
3851
+ if (typeof value === 'string' && value.startsWith(CAO_POPOVER_POSITION_PREFIX)) {
3852
+ this.placement.set(value.slice(CAO_POPOVER_POSITION_PREFIX.length));
3853
+ }
3854
+ }
3855
+ resolveOrigin(event, target) {
3856
+ if (target) {
3857
+ return target instanceof ElementRef ? target.nativeElement : target;
3858
+ }
3859
+ return (event?.currentTarget ?? event?.target ?? null);
3860
+ }
3861
+ focusPanel(overlayElement) {
3862
+ const panel = overlayElement.querySelector('.cao-popover');
3863
+ const target = panel?.querySelector(`.cao-popover__content ${FOCUSABLE_SELECTOR}`) ?? panel;
3864
+ if (target) {
3865
+ target.focus({ preventScroll: true });
3866
+ this.focusMoved = true;
3867
+ }
3868
+ }
3869
+ setOriginAria(origin, open) {
3870
+ if (!origin) {
3871
+ return;
3872
+ }
3873
+ origin.setAttribute('aria-expanded', String(open));
3874
+ if (open) {
3875
+ if (this.role() === 'dialog') {
3876
+ origin.setAttribute('aria-haspopup', 'dialog');
3877
+ }
3878
+ origin.setAttribute('aria-controls', this.panelId);
3879
+ }
3880
+ else {
3881
+ origin.removeAttribute('aria-controls');
3882
+ }
3883
+ }
3884
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3885
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CaoPopoverComponent, isStandalone: true, selector: "cao-popover", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, showArrow: { classPropertyName: "showArrow", publicName: "showArrow", isSignal: true, isRequired: false, transformFunction: null }, dismissable: { classPropertyName: "dismissable", publicName: "dismissable", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, showCloseIcon: { classPropertyName: "showCloseIcon", publicName: "showCloseIcon", isSignal: true, isRequired: false, transformFunction: null }, focusOnShow: { classPropertyName: "focusOnShow", publicName: "focusOnShow", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, maxWidth: { classPropertyName: "maxWidth", publicName: "maxWidth", isSignal: true, isRequired: false, transformFunction: null }, bgColor: { classPropertyName: "bgColor", publicName: "bgColor", isSignal: true, isRequired: false, transformFunction: null }, textColor: { classPropertyName: "textColor", publicName: "textColor", isSignal: true, isRequired: false, transformFunction: null }, borderColor: { classPropertyName: "borderColor", publicName: "borderColor", isSignal: true, isRequired: false, transformFunction: null }, borderRadius: { classPropertyName: "borderRadius", publicName: "borderRadius", isSignal: true, isRequired: false, transformFunction: null }, padding: { classPropertyName: "padding", publicName: "padding", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, role: { classPropertyName: "role", publicName: "role", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledBy: { classPropertyName: "ariaLabelledBy", publicName: "ariaLabelledBy", isSignal: true, isRequired: false, transformFunction: null }, closeAriaLabel: { classPropertyName: "closeAriaLabel", publicName: "closeAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, dataCy: { classPropertyName: "dataCy", publicName: "dataCy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { shown: "shown", hidden: "hidden", panelHoverChange: "panelHoverChange" }, viewQueries: [{ propertyName: "panelTemplate", first: true, predicate: ["panelTemplate"], descendants: true, isSignal: true }], exportAs: ["caoPopover"], ngImport: i0, template: "<ng-template #panelTemplate>\n <div\n [ngClass]=\"'cao-popover'\"\n tabindex=\"-1\"\n [id]=\"panelId\"\n [class]=\"styleClass()\"\n [class.cao-popover--top]=\"placement() === 'top'\"\n [class.cao-popover--bottom]=\"placement() === 'bottom'\"\n [class.cao-popover--left]=\"placement() === 'left'\"\n [class.cao-popover--right]=\"placement() === 'right'\"\n [class.cao-popover--align-start]=\"align() === 'start'\"\n [class.cao-popover--align-center]=\"align() === 'center'\"\n [class.cao-popover--align-end]=\"align() === 'end'\"\n [class.cao-popover--no-arrow]=\"!showArrow()\"\n [attr.role]=\"role() || null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.data-cy]=\"dataCy() || null\"\n [style.width]=\"width() || null\"\n [style.max-width]=\"maxWidth() || null\"\n [style.--cao-popover-bg]=\"bgColor() || null\"\n [style.--cao-popover-text]=\"textColor() || null\"\n [style.--cao-popover-border-color]=\"borderColor() || null\"\n [style.--cao-popover-radius]=\"borderRadius() || null\"\n [style.--cao-popover-padding]=\"padding() || null\"\n (mouseenter)=\"panelHoverChange.emit(true)\"\n (mouseleave)=\"panelHoverChange.emit(false)\">\n @if (showArrow()) {\n <span class=\"cao-popover__arrow\" aria-hidden=\"true\"></span>\n }\n\n <div class=\"cao-popover__content\" [class.cao-popover__content--with-close]=\"showCloseIcon()\">\n <ng-content />\n </div>\n\n @if (showCloseIcon()) {\n <button type=\"button\" class=\"cao-popover__close\" [attr.aria-label]=\"closeAriaLabel()\" (click)=\"onCloseClick()\">\n <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M6 6l12 12M18 6L6 18\" />\n </svg>\n </button>\n }\n </div>\n</ng-template>", styles: [":host{display:contents}.cao-popover{--_bg: var(--cao-popover-bg, #ffffff);--_text: var(--cao-popover-text, #111827);--_border: var(--cao-popover-border-color, #e5e7eb);--_radius: var(--cao-popover-radius, 8px);--_padding: var(--cao-popover-padding, 12px 16px);--_shadow: var(--cao-popover-shadow, 0 10px 25px -5px rgba(17, 24, 39, .15), 0 4px 10px -6px rgba(17, 24, 39, .12));--_focus: var(--cao-popover-focus-ring, rgba(79, 70, 229, .35));--_arrow-size: 10px;--_arrow-offset: 16px;position:relative;box-sizing:border-box;border:1px solid var(--_border);border-radius:var(--_radius);background-color:var(--_bg);box-shadow:var(--_shadow);color:var(--_text);font-size:.875rem;line-height:1.5;outline:none;animation:cao-popover-in .15s ease-out}.cao-popover:focus-visible{box-shadow:var(--_shadow),0 0 0 3px var(--_focus)}.cao-popover__content{padding:var(--_padding);overflow-wrap:anywhere}.cao-popover__content--with-close{padding-right:40px}.cao-popover__close{position:absolute;top:8px;right:8px;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:0;border-radius:4px;background:none;color:#6b7280;cursor:pointer}.cao-popover__close:hover{background-color:#f3f4f6;color:#111827}.cao-popover__close:focus-visible{outline:2px solid var(--_focus);outline-offset:1px}.cao-popover__arrow{position:absolute;width:var(--_arrow-size);height:var(--_arrow-size);background-color:var(--_bg);transform:rotate(45deg)}.cao-popover--bottom .cao-popover__arrow{top:calc(var(--_arrow-size) / -2 - 1px);border-top:1px solid var(--_border);border-left:1px solid var(--_border)}.cao-popover--top .cao-popover__arrow{bottom:calc(var(--_arrow-size) / -2 - 1px);border-right:1px solid var(--_border);border-bottom:1px solid var(--_border)}.cao-popover--right .cao-popover__arrow{left:calc(var(--_arrow-size) / -2 - 1px);border-bottom:1px solid var(--_border);border-left:1px solid var(--_border)}.cao-popover--left .cao-popover__arrow{right:calc(var(--_arrow-size) / -2 - 1px);border-top:1px solid var(--_border);border-right:1px solid var(--_border)}.cao-popover--top.cao-popover--align-center .cao-popover__arrow,.cao-popover--bottom.cao-popover--align-center .cao-popover__arrow{left:calc(50% - var(--_arrow-size) / 2)}.cao-popover--top.cao-popover--align-start .cao-popover__arrow,.cao-popover--bottom.cao-popover--align-start .cao-popover__arrow{left:var(--_arrow-offset)}.cao-popover--top.cao-popover--align-end .cao-popover__arrow,.cao-popover--bottom.cao-popover--align-end .cao-popover__arrow{right:var(--_arrow-offset)}.cao-popover--left.cao-popover--align-center .cao-popover__arrow,.cao-popover--right.cao-popover--align-center .cao-popover__arrow{top:calc(50% - var(--_arrow-size) / 2)}.cao-popover--left.cao-popover--align-start .cao-popover__arrow,.cao-popover--right.cao-popover--align-start .cao-popover__arrow{top:var(--_arrow-offset)}.cao-popover--left.cao-popover--align-end .cao-popover__arrow,.cao-popover--right.cao-popover--align-end .cao-popover__arrow{bottom:var(--_arrow-offset)}@keyframes cao-popover-in{0%{opacity:0;transform:scale(.97)}to{opacity:1;transform:scale(1)}}@media(prefers-reduced-motion:reduce){.cao-popover{animation:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3886
+ }
3887
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoPopoverComponent, decorators: [{
3888
+ type: Component,
3889
+ args: [{ selector: 'cao-popover', imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, exportAs: 'caoPopover', template: "<ng-template #panelTemplate>\n <div\n [ngClass]=\"'cao-popover'\"\n tabindex=\"-1\"\n [id]=\"panelId\"\n [class]=\"styleClass()\"\n [class.cao-popover--top]=\"placement() === 'top'\"\n [class.cao-popover--bottom]=\"placement() === 'bottom'\"\n [class.cao-popover--left]=\"placement() === 'left'\"\n [class.cao-popover--right]=\"placement() === 'right'\"\n [class.cao-popover--align-start]=\"align() === 'start'\"\n [class.cao-popover--align-center]=\"align() === 'center'\"\n [class.cao-popover--align-end]=\"align() === 'end'\"\n [class.cao-popover--no-arrow]=\"!showArrow()\"\n [attr.role]=\"role() || null\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-labelledby]=\"ariaLabelledBy() || null\"\n [attr.data-cy]=\"dataCy() || null\"\n [style.width]=\"width() || null\"\n [style.max-width]=\"maxWidth() || null\"\n [style.--cao-popover-bg]=\"bgColor() || null\"\n [style.--cao-popover-text]=\"textColor() || null\"\n [style.--cao-popover-border-color]=\"borderColor() || null\"\n [style.--cao-popover-radius]=\"borderRadius() || null\"\n [style.--cao-popover-padding]=\"padding() || null\"\n (mouseenter)=\"panelHoverChange.emit(true)\"\n (mouseleave)=\"panelHoverChange.emit(false)\">\n @if (showArrow()) {\n <span class=\"cao-popover__arrow\" aria-hidden=\"true\"></span>\n }\n\n <div class=\"cao-popover__content\" [class.cao-popover__content--with-close]=\"showCloseIcon()\">\n <ng-content />\n </div>\n\n @if (showCloseIcon()) {\n <button type=\"button\" class=\"cao-popover__close\" [attr.aria-label]=\"closeAriaLabel()\" (click)=\"onCloseClick()\">\n <svg viewBox=\"0 0 24 24\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M6 6l12 12M18 6L6 18\" />\n </svg>\n </button>\n }\n </div>\n</ng-template>", styles: [":host{display:contents}.cao-popover{--_bg: var(--cao-popover-bg, #ffffff);--_text: var(--cao-popover-text, #111827);--_border: var(--cao-popover-border-color, #e5e7eb);--_radius: var(--cao-popover-radius, 8px);--_padding: var(--cao-popover-padding, 12px 16px);--_shadow: var(--cao-popover-shadow, 0 10px 25px -5px rgba(17, 24, 39, .15), 0 4px 10px -6px rgba(17, 24, 39, .12));--_focus: var(--cao-popover-focus-ring, rgba(79, 70, 229, .35));--_arrow-size: 10px;--_arrow-offset: 16px;position:relative;box-sizing:border-box;border:1px solid var(--_border);border-radius:var(--_radius);background-color:var(--_bg);box-shadow:var(--_shadow);color:var(--_text);font-size:.875rem;line-height:1.5;outline:none;animation:cao-popover-in .15s ease-out}.cao-popover:focus-visible{box-shadow:var(--_shadow),0 0 0 3px var(--_focus)}.cao-popover__content{padding:var(--_padding);overflow-wrap:anywhere}.cao-popover__content--with-close{padding-right:40px}.cao-popover__close{position:absolute;top:8px;right:8px;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:0;border-radius:4px;background:none;color:#6b7280;cursor:pointer}.cao-popover__close:hover{background-color:#f3f4f6;color:#111827}.cao-popover__close:focus-visible{outline:2px solid var(--_focus);outline-offset:1px}.cao-popover__arrow{position:absolute;width:var(--_arrow-size);height:var(--_arrow-size);background-color:var(--_bg);transform:rotate(45deg)}.cao-popover--bottom .cao-popover__arrow{top:calc(var(--_arrow-size) / -2 - 1px);border-top:1px solid var(--_border);border-left:1px solid var(--_border)}.cao-popover--top .cao-popover__arrow{bottom:calc(var(--_arrow-size) / -2 - 1px);border-right:1px solid var(--_border);border-bottom:1px solid var(--_border)}.cao-popover--right .cao-popover__arrow{left:calc(var(--_arrow-size) / -2 - 1px);border-bottom:1px solid var(--_border);border-left:1px solid var(--_border)}.cao-popover--left .cao-popover__arrow{right:calc(var(--_arrow-size) / -2 - 1px);border-top:1px solid var(--_border);border-right:1px solid var(--_border)}.cao-popover--top.cao-popover--align-center .cao-popover__arrow,.cao-popover--bottom.cao-popover--align-center .cao-popover__arrow{left:calc(50% - var(--_arrow-size) / 2)}.cao-popover--top.cao-popover--align-start .cao-popover__arrow,.cao-popover--bottom.cao-popover--align-start .cao-popover__arrow{left:var(--_arrow-offset)}.cao-popover--top.cao-popover--align-end .cao-popover__arrow,.cao-popover--bottom.cao-popover--align-end .cao-popover__arrow{right:var(--_arrow-offset)}.cao-popover--left.cao-popover--align-center .cao-popover__arrow,.cao-popover--right.cao-popover--align-center .cao-popover__arrow{top:calc(50% - var(--_arrow-size) / 2)}.cao-popover--left.cao-popover--align-start .cao-popover__arrow,.cao-popover--right.cao-popover--align-start .cao-popover__arrow{top:var(--_arrow-offset)}.cao-popover--left.cao-popover--align-end .cao-popover__arrow,.cao-popover--right.cao-popover--align-end .cao-popover__arrow{bottom:var(--_arrow-offset)}@keyframes cao-popover-in{0%{opacity:0;transform:scale(.97)}to{opacity:1;transform:scale(1)}}@media(prefers-reduced-motion:reduce){.cao-popover{animation:none}}\n"] }]
3890
+ }], ctorParameters: () => [], propDecorators: { panelTemplate: [{ type: i0.ViewChild, args: ['panelTemplate', { isSignal: true }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "offset", required: false }] }], showArrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "showArrow", required: false }] }], dismissable: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissable", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], showCloseIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCloseIcon", required: false }] }], focusOnShow: [{ type: i0.Input, args: [{ isSignal: true, alias: "focusOnShow", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], maxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxWidth", required: false }] }], bgColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "bgColor", required: false }] }], textColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "textColor", required: false }] }], borderColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderColor", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], padding: [{ type: i0.Input, args: [{ isSignal: true, alias: "padding", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledBy", required: false }] }], closeAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeAriaLabel", required: false }] }], dataCy: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataCy", required: false }] }], shown: [{ type: i0.Output, args: ["shown"] }], hidden: [{ type: i0.Output, args: ["hidden"] }], panelHoverChange: [{ type: i0.Output, args: ["panelHoverChange"] }] } });
3891
+
3559
3892
  class BaseModalService {
3560
3893
  constructor() { }
3561
3894
  toggleModalEvent = new EventEmitter();
@@ -4857,5 +5190,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
4857
5190
  * Generated bundle index. Do not edit.
4858
5191
  */
4859
5192
 
4860
- export { BaseAlert, BaseAlertService, BaseDialog, BaseDialogService, BaseFilterTablePaginatedService, BaseFilterTableService, BaseModal, BaseModalService, BasePaginationService, BaseTable, BaseTablePaginated, BaseTableService, BaseTimeRange, CAO_ACCORDION, CaoAccordionComponent, CaoAccordionItemComponent, CaoAutocompleteComponent, CaoBaseButtonComponent, CaoBaseIcon, CaoBaseInput, CaoBaseToggleComponent, CaoBaseWidgetComponent, CaoBreadcrumbComponent, CaoCardComponent, CaoCheckboxComponent, CaoDropDownComponent, CaoError, CaoFormField, CaoHint, CaoKpi, CaoRadioButtonComponent, CaoRadioGroupComponent, CaoSkeletonComponent, CaoSlideToggleComponent, CaoTabGroup, CaoTabPanel, CaoWidgetService, DEFAULT_ERROR_STATE_MATCHER, ErrorStateMatcher, Footer, LinksButton, Paginator, ShowOnDirtyErrorStateMatcher, StepComponent, StepperComponent, TablePaginatedService, TimePicker, getPtBrPaginatorIntlBasePaginated, getPtBrPaginatorIntlBaseTable };
5193
+ export { BaseAlert, BaseAlertService, BaseDialog, BaseDialogService, BaseFilterTablePaginatedService, BaseFilterTableService, BaseModal, BaseModalService, BasePaginationService, BaseTable, BaseTablePaginated, BaseTableService, BaseTimeRange, CAO_ACCORDION, CAO_POPOVER_POSITION_PREFIX, CaoAccordionComponent, CaoAccordionItemComponent, CaoAutocompleteComponent, CaoBaseButtonComponent, CaoBaseIcon, CaoBaseInput, CaoBaseToggleComponent, CaoBaseWidgetComponent, CaoBreadcrumbComponent, CaoCardComponent, CaoCheckboxComponent, CaoDropDownComponent, CaoError, CaoFormField, CaoHint, CaoKpi, CaoPopoverComponent, CaoProgressBarComponent, CaoProgressSpinnerComponent, CaoRadioButtonComponent, CaoRadioGroupComponent, CaoSkeletonComponent, CaoSlideToggleComponent, CaoTabGroup, CaoTabPanel, CaoWidgetService, DEFAULT_ERROR_STATE_MATCHER, ErrorStateMatcher, Footer, LinksButton, Paginator, ShowOnDirtyErrorStateMatcher, StepComponent, StepperComponent, TablePaginatedService, TimePicker, buildPopoverPositions, getPtBrPaginatorIntlBasePaginated, getPtBrPaginatorIntlBaseTable };
4861
5194
  //# sourceMappingURL=ngx-opalbytes-components.mjs.map