ngx-opalbytes-components 1.22.0 → 1.23.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.
- package/README.md +98 -0
- package/fesm2022/ngx-opalbytes-components.mjs +174 -2
- package/fesm2022/ngx-opalbytes-components.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/shared/components/error/error.css +10 -0
- package/src/lib/shared/components/error/error.html +5 -0
- package/src/lib/shared/components/error/error.spec.ts +76 -0
- package/src/lib/shared/components/error/error.stories.ts +61 -0
- package/src/lib/shared/components/error/error.ts +33 -0
- package/src/lib/shared/components/form-field/error-state-matcher.ts +41 -0
- package/src/lib/shared/components/form-field/form-field-control.ts +10 -0
- package/src/lib/shared/components/form-field/form-field.css +154 -0
- package/src/lib/shared/components/form-field/form-field.html +51 -0
- package/src/lib/shared/components/form-field/form-field.spec.ts +114 -0
- package/src/lib/shared/components/form-field/form-field.stories.ts +177 -0
- package/src/lib/shared/components/form-field/form-field.ts +118 -0
- package/src/lib/shared/components/hint/hint.css +10 -0
- package/src/lib/shared/components/hint/hint.html +1 -0
- package/src/lib/shared/components/hint/hint.spec.ts +22 -0
- package/src/lib/shared/components/hint/hint.stories.ts +53 -0
- package/src/lib/shared/components/hint/hint.ts +9 -0
- package/src/lib/shared/components/index.ts +6 -0
- package/types/ngx-opalbytes-components.d.ts +70 -2
package/README.md
CHANGED
|
@@ -125,6 +125,104 @@ cao-comp --list
|
|
|
125
125
|
|
|
126
126
|
---
|
|
127
127
|
|
|
128
|
+
## Quando usar `cao-comp` vs. a biblioteca (`npm install`)
|
|
129
|
+
|
|
130
|
+
A `ngx-opalbytes-components` pode ser consumida de duas formas distintas, e cada uma atende a necessidades diferentes:
|
|
131
|
+
|
|
132
|
+
- **Usar o pacote (`npm install ngx-opalbytes-components`)** — você consome a **API pública** dos componentes, como qualquer dependência externa. O código vive dentro do `node_modules`, é versionado e atualizado por você (ou pela própria biblioteca). A biblioteca funciona como uma "caixa preta": você usa os `@Input`s, `@Output`s e métodos que ela expõe, mas não altera o comportamento interno.
|
|
133
|
+
- **Copiar o código-fonte (`cao-comp`)** — você copia o fonte de um componente para dentro do **seu próprio projeto**. A partir daí o componente deixa de ser gerenciado pela biblioteca e se torna **seu código**, com total liberdade de edição (template, estilos, lógica e eventos). A biblioteca funciona como uma "caixa aberta": você passa a ter a posse daquele componente.
|
|
134
|
+
|
|
135
|
+
A escolha entre uma abordagem e outra não é sobre "qual é melhor", mas sobre **o quanto você precisa de controle sobre o componente**.
|
|
136
|
+
|
|
137
|
+
### Tabela comparativa
|
|
138
|
+
|
|
139
|
+
| Critério | `cao-comp` (copiar o código) | `npm install` (usar a lib) |
|
|
140
|
+
| --- | --- | --- |
|
|
141
|
+
| **Explorar/visualizar componentes e inputs** | Ideal — gera o setup de **Storybook** para navegar os componentes e seus `@Input`s/`@Output`s. | Não oferece isso diretamente — a visualização depende de documentação ou de você montar Storybook por conta própria. |
|
|
142
|
+
| **Grau de customização** | Total — você edita template, CSS e lógica internos. | Limitado à API pública (`@Input`/`@Output`/métodos expostos). |
|
|
143
|
+
| **Estratégia de extensão** | Modificar o comportamento interno do componente (fork). | Compor/envolver o componente com a estrutura da lib (ex.: estender `AlertService`/`DialogService` via `generateComponentPortal()`). |
|
|
144
|
+
| **Volume de inputs/eventos para repassar** | Baixo — você edita onde precisa, sem re-expor dezenas de `@Input`s de um wrapper. | Alto em wrappers — cada `@Input`/`@Output` que você quiser repassar precisa ser declarado e repassado manualmente no componente que envolve o da lib. |
|
|
145
|
+
| **Atualização / manutenção** | **Não** acompanha a lib — o código vira seu; correções e novas versões precisam ser reaplicadas à mão. | Acompanha a lib — `npm update`/`npm install` entrega fixes, features e novas versões automaticamente. |
|
|
146
|
+
| **Consistência entre projetos** | Divisão de risco — cada projeto pode divergir do padrão visual/lógico da lib. | Alta consistência — todos os projetos usam a mesma versão publicada. |
|
|
147
|
+
| **Testes, acessibilidade e qualidade** | Ficam sob responsabilidade do time local após o fork. | Já prontos e centralizados (testes, a11y e convenções da lib). |
|
|
148
|
+
| **Ownership do código** | Seu projeto assume a posse e a responsabilidade do componente. | A biblioteca mantém a responsabilidade da manutenção. |
|
|
149
|
+
|
|
150
|
+
### Use `cao-comp` quando:
|
|
151
|
+
|
|
152
|
+
- **Precisar visualizar** os componentes existentes e seus inputs **antes** de usá-los — o `cao-comp storybook` gera o setup mínimo para explorar tudo visualmente.
|
|
153
|
+
- A customização **escapa da API pública** — por exemplo, alterar estilização, atributos, funcionalidades ou eventos que só existem no código-fonte do componente (ex.: um **tooltip customizável** que o componente base não expõe como input).
|
|
154
|
+
- Você **não quer estender** um componente a partir do componente da lib (isso costuma gerar wrappers frágeis), mas sim **modificar o componente em si**.
|
|
155
|
+
- Quer **reduzir o trabalho de repassar todos os `@Input`s e `@Output`s** de um componente pai para um componente da lib — em vez de declarar e propagar dezenas de entradas/saídas, você edita o componente diretamente.
|
|
156
|
+
- O componente funcionará como um **fork**: você quer posse total do código e **não precisa** acompanhar as versões da biblioteca (seja por questão de isolamento, build offline ou regra de não instalar a dependência).
|
|
157
|
+
- Um componente da lib já expõe boa parte, **mas** atende a um caso tão específico do seu domínio que a manutenção local é mais simples do que manter um wrapper enorme.
|
|
158
|
+
|
|
159
|
+
### Use `npm install` (a lib) quando:
|
|
160
|
+
|
|
161
|
+
- Quiser ter **sempre a versão mais atualizada** da biblioteca, com fixes e melhorias centralizados.
|
|
162
|
+
- **Não precisar visualizar** os componentes existentes em detalhe — a API pública e a documentação já são suficientes.
|
|
163
|
+
- Pretender usar **somente os eventos e atributos** expostos, **criando componentes que estendem/compoem a estrutura da lib** — por exemplo `AlertService`/`DialogService` (veja a seção "Como estender o `AlertService`" e "Como estender o `DialogService`" abaixo), que permitem customizar a aparência mantendo o consumo via npm, sem precisar copiar fonte nenhum.
|
|
164
|
+
- O componente pronto (com a API atual) já atende ao caso, e você valoriza testes, acessibilidade e padrão visual já validados.
|
|
165
|
+
- Precisar de **consistência visual e de comportamento entre múltiplos projetos** — todos passam a usar a mesma versão publicada e atualizada.
|
|
166
|
+
|
|
167
|
+
### Prós e contras
|
|
168
|
+
|
|
169
|
+
**`cao-comp` (copiar o código)**
|
|
170
|
+
|
|
171
|
+
- ✅ Liberdade total de edição (template, estilos, lógica, eventos).
|
|
172
|
+
- ✅ Sem custo de repasse de dezenas de `@Input`s/`@Output`s.
|
|
173
|
+
- ✅ Visualização imediata via Storybook.
|
|
174
|
+
- ❌ O código vira seu: **não** recebe atualizações/fixes da lib automaticamente.
|
|
175
|
+
- ❌ Código duplicado: a cópia pode divergir da lib com o tempo.
|
|
176
|
+
- ❌ Testes, a11y e manutenção passam a ser responsabilidade do seu time.
|
|
177
|
+
|
|
178
|
+
**`npm install` (a lib)**
|
|
179
|
+
|
|
180
|
+
- ✅ Sempre atualizado (`npm update`/`npm install`).
|
|
181
|
+
- ✅ Testes, acessibilidade e convenções já prontas e centralizadas.
|
|
182
|
+
- ✅ Consistência entre projetos e equipas.
|
|
183
|
+
- ❌ Limitado à API pública (sem alterar comportamento interno).
|
|
184
|
+
- ❌ Wrappers para mais inputs/eventos podem crescer muito.
|
|
185
|
+
- ❌ Sem visualização direta dos componentes (depende de docs/Storybook próprio).
|
|
186
|
+
|
|
187
|
+
### Exemplo prático — quando vale usar `cao-comp`
|
|
188
|
+
|
|
189
|
+
Suponha que sua aplicação precise de um `<cao-input>` com um **tooltip mais elaborado** e um **layout interno específico** que a API pública do `BaseInput` não expõe. A API atual só oferece `tooltip` (texto simples), mas você precisa de tooltip customizada (com título, conteúdo rico e ícone) e de uma estrutura interna diferente.
|
|
190
|
+
|
|
191
|
+
**Abordagem ruim (com a lib):** você cria um wrapper `AppInputComponent` que envolve `<cao-input>` e tenta "empacotar" todos os `@Input`s/`@Output`s do `BaseInput`, além de tentar replicar uma tooltip customizada que o componente interno nem sequer aceita. Resultado: muito código de repasse, frágil, e ainda assim sem atingir o layout interno desejado.
|
|
192
|
+
|
|
193
|
+
**Abordagem boa (com `cao-comp`):**
|
|
194
|
+
|
|
195
|
+
1. Explore os componentes disponíveis:
|
|
196
|
+
```bash
|
|
197
|
+
cao-comp --list
|
|
198
|
+
```
|
|
199
|
+
2. Copie o fonte do componente para o seu projeto:
|
|
200
|
+
```bash
|
|
201
|
+
cao-comp base-input ./src/app/components/base-input-custom
|
|
202
|
+
```
|
|
203
|
+
3. Gere o Storybook para visualizar e validar:
|
|
204
|
+
```bash
|
|
205
|
+
cao-comp base-input ./src/app/components/base-input-custom
|
|
206
|
+
cao-comp storybook .
|
|
207
|
+
```
|
|
208
|
+
4. Edite diretamente o `template` e os estilos do componente copiado para incluir o novo layout e a tooltip customizada, e adicione os novos `@Input`s/`@Output`s que o seu caso precisa — sem repassar nada de um wrapper.
|
|
209
|
+
|
|
210
|
+
Agora o componente copiado é seu, atende exatamente ao domínio da aplicação, e você validou visualmente via Storybook.
|
|
211
|
+
|
|
212
|
+
### Checklist de decisão rápida
|
|
213
|
+
|
|
214
|
+
- Preciso explorar os componentes e seus inputs (Storybook)? → **`cao-comp`**
|
|
215
|
+
- A customização que preciso (estilo/comportamento/eventos) **não** está na API pública? → **`cao-comp`**
|
|
216
|
+
- Quero modificar o componente em si, não apenas compor/estender? → **`cao-comp`**
|
|
217
|
+
- Estou disposto a assumir a manutenção do código (sem updates automáticos)? → **`cao-comp`**
|
|
218
|
+
- Prefiro sempre a versão mais atualizada e manutenção centralizada? → **`npm install`**
|
|
219
|
+
- A API pública já atende (só uso eventos/atributos) e vou compor/extender a estrutura da lib? → **`npm install`**
|
|
220
|
+
- Preciso de consistência visual/qualidade (testes, a11y) entre projetos? → **`npm install`**
|
|
221
|
+
|
|
222
|
+
> **Importante quanto ao `cao-comp`:** ao copiar componentes, observe as **dependências internas**. Alguns componentes dependem de outros que precisam ser copiados juntos (ex.: `tab-group` depende de `tab-panel`, `stepper` depende de `step`; serviços que usam `ComponentPortal`, como `AlertService`/`DialogService`, precisam do componente correspondente). Além disso, o projeto de destino precisa ter as **peer dependencies** instaladas (`@angular/material`, `ngx-mask`, `@lucide/angular`, `@angular/cdk`) — o setup de Storybook gerado já orienta essa instalação.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
128
226
|
## Organização de Pastas
|
|
129
227
|
|
|
130
228
|
Dentro da pasta `src/lib/`, os componentes são organizados em `shared/components/` e cada componente reside em sua própria pasta, contendo seus arquivos (`.ts`, `.html`, `.css`, `.spec.ts`).
|
|
@@ -6,7 +6,7 @@ import * as i3 from '@angular/material/tooltip';
|
|
|
6
6
|
import { MatTooltipModule, MatTooltip } from '@angular/material/tooltip';
|
|
7
7
|
import { LucideDynamicIcon } from '@lucide/angular';
|
|
8
8
|
import * as i2 from '@angular/forms';
|
|
9
|
-
import { FormsModule, NG_VALUE_ACCESSOR, FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
9
|
+
import { FormsModule, NG_VALUE_ACCESSOR, FormControl, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
10
10
|
import { NgxMaskDirective, provideNgxMask } from 'ngx-mask';
|
|
11
11
|
import * as i2$1 from '@angular/material/datepicker';
|
|
12
12
|
import { MatDatepickerModule, MatDateRangeInput } from '@angular/material/datepicker';
|
|
@@ -1914,6 +1914,178 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
1914
1914
|
args: [{ selector: 'cao-skeleton', imports: [CommonModule], template: "<span class=\"cao-skeleton\" [ngClass]=\"'cao-skeleton--' + variant()\" [style]=\"skeletonStyles()\">\n <span class=\"cao-skeleton__shimmer\"></span>\n</span>", styles: [":host{--skeleton-width: 100%;--skeleton-height: 100%;--skeleton-bg: #e2e8f0;--skeleton-shine: #f8fafc;--skeleton-radius: 14px;--skeleton-speed: 2s;--skeleton-animation-deg: 90deg;display:contents}.cao-skeleton{position:relative;display:block;overflow:hidden;width:var(--skeleton-width);height:var(--skeleton-height);background-color:var(--skeleton-bg);border-radius:var(--skeleton-radius);color:transparent;-webkit-user-select:none;user-select:none;pointer-events:none}@media(prefers-reduced-motion:no-preference){.cao-skeleton{will-change:transform}}.cao-skeleton--circle{--skeleton-radius: 50%;aspect-ratio:1 / 1}.cao-skeleton--text{--skeleton-radius: 4px;height:1em;width:var(--skeleton-width)}.cao-skeleton__shimmer{position:absolute;inset:0;background:linear-gradient(var(--skeleton-animation-deg),transparent 30%,var(--skeleton-shine) 50%,transparent 70%);background-size:200% 100%}@media(prefers-reduced-motion:no-preference){.cao-skeleton__shimmer{animation:skeleton-shimmer var(--skeleton-speed) ease-in-out infinite}}@keyframes skeleton-shimmer{0%{background-position:200% center}to{background-position:-200% center}}\n"] }]
|
|
1915
1915
|
}], propDecorators: { borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], bgColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "bgColor", required: false }] }], shine: [{ type: i0.Input, args: [{ isSignal: true, alias: "shine", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], speed: [{ type: i0.Input, args: [{ isSignal: true, alias: "speed", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], animationDeg: [{ type: i0.Input, args: [{ isSignal: true, alias: "animationDeg", required: false }] }] } });
|
|
1916
1916
|
|
|
1917
|
+
class CaoFormField extends CaoBaseIcon {
|
|
1918
|
+
inputBackground = input(...(ngDevMode ? [undefined, { debugName: "inputBackground" }] : []));
|
|
1919
|
+
borderColor = input(...(ngDevMode ? [undefined, { debugName: "borderColor" }] : []));
|
|
1920
|
+
borderWidth = input(...(ngDevMode ? [undefined, { debugName: "borderWidth" }] : []));
|
|
1921
|
+
borderRadius = input(...(ngDevMode ? [undefined, { debugName: "borderRadius" }] : []));
|
|
1922
|
+
errorColor = input(...(ngDevMode ? [undefined, { debugName: "errorColor" }] : []));
|
|
1923
|
+
labelColor = input(...(ngDevMode ? [undefined, { debugName: "labelColor" }] : []));
|
|
1924
|
+
hintColor = input(...(ngDevMode ? [undefined, { debugName: "hintColor" }] : []));
|
|
1925
|
+
textColor = input(...(ngDevMode ? [undefined, { debugName: "textColor" }] : []));
|
|
1926
|
+
focusBorderColor = input(...(ngDevMode ? [undefined, { debugName: "focusBorderColor" }] : []));
|
|
1927
|
+
successBorderColor = input(...(ngDevMode ? [undefined, { debugName: "successBorderColor" }] : []));
|
|
1928
|
+
formFieldStyles = computed(() => {
|
|
1929
|
+
const styles = {};
|
|
1930
|
+
if (this.inputBackground()) {
|
|
1931
|
+
styles['--cao-form-field-bg-background'] = this.inputBackground();
|
|
1932
|
+
}
|
|
1933
|
+
if (this.borderColor()) {
|
|
1934
|
+
styles['--cao-form-field-border-color'] = this.borderColor();
|
|
1935
|
+
}
|
|
1936
|
+
if (this.borderWidth()) {
|
|
1937
|
+
styles['--cao-form-field-border-width'] = this.borderWidth();
|
|
1938
|
+
}
|
|
1939
|
+
if (this.borderRadius()) {
|
|
1940
|
+
styles['--cao-form-field-border-radius'] = this.borderRadius();
|
|
1941
|
+
}
|
|
1942
|
+
if (this.errorColor()) {
|
|
1943
|
+
styles['--cao-form-field-color-error'] = this.errorColor();
|
|
1944
|
+
}
|
|
1945
|
+
if (this.labelColor()) {
|
|
1946
|
+
styles['--cao-form-field-color-label'] = this.labelColor();
|
|
1947
|
+
}
|
|
1948
|
+
if (this.hintColor()) {
|
|
1949
|
+
styles['--cao-form-field-color-hint'] = this.hintColor();
|
|
1950
|
+
}
|
|
1951
|
+
if (this.textColor()) {
|
|
1952
|
+
styles['--cao-form-field-color-text'] = this.textColor();
|
|
1953
|
+
}
|
|
1954
|
+
if (this.focusBorderColor()) {
|
|
1955
|
+
styles['--cao-form-field-focus-border'] = this.focusBorderColor();
|
|
1956
|
+
}
|
|
1957
|
+
if (this.successBorderColor()) {
|
|
1958
|
+
styles['--cao-form-field-success-border'] = this.successBorderColor();
|
|
1959
|
+
}
|
|
1960
|
+
return styles;
|
|
1961
|
+
}, ...(ngDevMode ? [{ debugName: "formFieldStyles" }] : []));
|
|
1962
|
+
label = '';
|
|
1963
|
+
labelInside = false;
|
|
1964
|
+
hintLabel = '';
|
|
1965
|
+
control = null;
|
|
1966
|
+
forId = '';
|
|
1967
|
+
errorStateMatcher;
|
|
1968
|
+
leadingIcon;
|
|
1969
|
+
trailingIcon;
|
|
1970
|
+
_isSubmitted = false;
|
|
1971
|
+
_focused = false;
|
|
1972
|
+
get id() {
|
|
1973
|
+
return this.forId;
|
|
1974
|
+
}
|
|
1975
|
+
get disabled() {
|
|
1976
|
+
return !!this.control?.disabled;
|
|
1977
|
+
}
|
|
1978
|
+
get required() {
|
|
1979
|
+
if (!this.control) {
|
|
1980
|
+
return false;
|
|
1981
|
+
}
|
|
1982
|
+
const hasValidator = typeof this.control.hasValidator === 'function'
|
|
1983
|
+
? this.control.hasValidator(Validators.required)
|
|
1984
|
+
: false;
|
|
1985
|
+
return hasValidator;
|
|
1986
|
+
}
|
|
1987
|
+
get floating() {
|
|
1988
|
+
return this._focused || !!this.control?.value;
|
|
1989
|
+
}
|
|
1990
|
+
get errorStateActive() {
|
|
1991
|
+
const control = this.control;
|
|
1992
|
+
if (!control) {
|
|
1993
|
+
return false;
|
|
1994
|
+
}
|
|
1995
|
+
const matcher = this.errorStateMatcher;
|
|
1996
|
+
return matcher
|
|
1997
|
+
? matcher.isErrorState(control, this)
|
|
1998
|
+
: !!(control.invalid && (control.touched || control.dirty || this._isSubmitted));
|
|
1999
|
+
}
|
|
2000
|
+
onFocusIn() {
|
|
2001
|
+
this._focused = true;
|
|
2002
|
+
if (this.control && !this._isSubmitted) {
|
|
2003
|
+
this.control.markAsTouched();
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
onFocusOut() {
|
|
2007
|
+
this._focused = false;
|
|
2008
|
+
}
|
|
2009
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoFormField, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2010
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CaoFormField, isStandalone: true, selector: "cao-form-field", inputs: { inputBackground: { classPropertyName: "inputBackground", publicName: "inputBackground", isSignal: true, isRequired: false, transformFunction: null }, borderColor: { classPropertyName: "borderColor", publicName: "borderColor", isSignal: true, isRequired: false, transformFunction: null }, borderWidth: { classPropertyName: "borderWidth", publicName: "borderWidth", isSignal: true, isRequired: false, transformFunction: null }, borderRadius: { classPropertyName: "borderRadius", publicName: "borderRadius", isSignal: true, isRequired: false, transformFunction: null }, errorColor: { classPropertyName: "errorColor", publicName: "errorColor", isSignal: true, isRequired: false, transformFunction: null }, labelColor: { classPropertyName: "labelColor", publicName: "labelColor", isSignal: true, isRequired: false, transformFunction: null }, hintColor: { classPropertyName: "hintColor", publicName: "hintColor", isSignal: true, isRequired: false, transformFunction: null }, textColor: { classPropertyName: "textColor", publicName: "textColor", isSignal: true, isRequired: false, transformFunction: null }, focusBorderColor: { classPropertyName: "focusBorderColor", publicName: "focusBorderColor", isSignal: true, isRequired: false, transformFunction: null }, successBorderColor: { classPropertyName: "successBorderColor", publicName: "successBorderColor", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: false, isRequired: false, transformFunction: null }, labelInside: { classPropertyName: "labelInside", publicName: "labelInside", isSignal: false, isRequired: false, transformFunction: null }, hintLabel: { classPropertyName: "hintLabel", publicName: "hintLabel", isSignal: false, isRequired: false, transformFunction: null }, control: { classPropertyName: "control", publicName: "control", isSignal: false, isRequired: false, transformFunction: null }, forId: { classPropertyName: "forId", publicName: "forId", isSignal: false, isRequired: false, transformFunction: null }, errorStateMatcher: { classPropertyName: "errorStateMatcher", publicName: "errorStateMatcher", isSignal: false, isRequired: false, transformFunction: null }, leadingIcon: { classPropertyName: "leadingIcon", publicName: "leadingIcon", isSignal: false, isRequired: false, transformFunction: null }, trailingIcon: { classPropertyName: "trailingIcon", publicName: "trailingIcon", isSignal: false, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div\n class=\"cao-form-field\"\n [class.label-inside]=\"labelInside\"\n [class.error-state]=\"errorStateActive\"\n [class.disabled]=\"disabled\"\n [class.required]=\"required\"\n [style]=\"formFieldStyles()\">\n @if (label && !labelInside) {\n <label class=\"cao-form-field__label\" [for]=\"forId\">{{ label }}</label>\n }\n <div class=\"input-field\" (focusin)=\"onFocusIn()\" (focusout)=\"onFocusOut()\">\n @if (leadingIcon) {\n <cao-base-icon\n [isLucideIcon]=\"isLucideIcon\"\n [strokeWidthIcon]=\"strokeWidthIcon\"\n [imgSource]=\"leadingIcon\"\n [iconColor]=\"iconColor\"\n [size]=\"size\" />\n }\n <div class=\"input-slot\">\n @if (label && labelInside) {\n <label\n class=\"cao-form-field__label cao-form-field__label--float\"\n [class.cao-form-field__label--floated]=\"floating\"\n [for]=\"forId\">{{ label }}</label>\n }\n <ng-content select=\"[caoInput]\" />\n <ng-content select=\"cao-input\" />\n <ng-content select=\"input\" />\n <ng-content select=\"select\" />\n <ng-content select=\"textarea\" />\n <ng-content select=\"h2\" />\n <ng-content />\n </div>\n @if (trailingIcon) {\n <cao-base-icon\n [isLucideIcon]=\"isLucideIcon\"\n [iconColor]=\"iconColor\"\n [size]=\"size\"\n [imgSource]=\"trailingIcon\"\n [strokeWidthIcon]=\"strokeWidthIcon\" />\n }\n </div>\n <div class=\"subscript-wrapper\">\n @if (hintLabel) {\n <small class=\"cao-form-field__hint\">{{ hintLabel }}</small>\n }\n <ng-content select=\"cao-hint\" />\n <ng-content select=\"cao-error\" />\n </div>\n</div>", styles: [":host{--cao-form-field-bg-background: var(--input-background, #ffffff);--cao-form-field-border-color: var(--line-color, #e5e7eb);--cao-form-field-border-width: 1px;--cao-form-field-border-radius: 8px;--cao-form-field-color-error: var(--error, #dc2626);--cao-form-field-color-label: var(--primary, #111827);--cao-form-field-color-hint: var(--input-text, #9ca3af);--cao-form-field-color-text: var(--text-color-input, #111827);--cao-form-field-focus-border: var(--primary, #111827);--cao-form-field-success-border: var(--success, #16a34a);display:block;width:100%}.cao-form-field{display:flex;flex-direction:column;gap:4px;width:100%;font-family:inherit}.cao-form-field__label{display:block;font-size:.75rem;font-weight:700;line-height:1.25rem;color:var(--cao-form-field-color-label);text-transform:uppercase;letter-spacing:.02em;white-space:nowrap}.cao-form-field__label--float{position:absolute;top:50%;left:12px;transform:translateY(-50%);font-weight:500;text-transform:none;letter-spacing:0;color:var(--cao-form-field-color-hint);pointer-events:none;transition:transform .15s cubic-bezier(.4,0,.2,1),font-size .15s cubic-bezier(.4,0,.2,1),color .15s cubic-bezier(.4,0,.2,1);max-width:calc(100% - 24px);overflow:hidden;text-overflow:ellipsis}.cao-form-field__label--floated{transform:translateY(calc(-50% - 14px)) scale(.75);transform-origin:left top;color:var(--cao-form-field-color-label);font-weight:700}.input-field{position:relative;display:flex;align-items:center;width:100%;min-height:44px;background-color:var(--cao-form-field-bg-background);border:var(--cao-form-field-border-width) solid var(--cao-form-field-border-color);border-radius:var(--cao-form-field-border-radius);transition:border-color .15s cubic-bezier(.4,0,.2,1),background-color .15s cubic-bezier(.4,0,.2,1)}.input-field:focus-within{border-color:var(--cao-form-field-focus-border)}.cao-form-field.error-state .input-field{border-color:var(--cao-form-field-color-error)}.cao-form-field.disabled .input-field{opacity:.7}.input-slot{position:relative;flex:1;display:flex;align-items:center;width:100%;height:100%}.input-slot ::ng-deep input,.input-slot ::ng-deep textarea,.input-slot ::ng-deep select{width:100%;min-height:40px;border:none;outline:none;background:transparent;color:var(--cao-form-field-color-text);font-family:inherit;font-size:.875rem;padding:6px 12px;box-sizing:border-box}.input-slot ::ng-deep cao-input,.input-slot ::ng-deep .cao-input{width:100%}.input-slot ::ng-deep cao-input .input-component,.input-slot ::ng-deep cao-input .input-wrapper{width:100%;background:transparent}.input-slot ::ng-deep cao-input input,.input-slot ::ng-deep cao-input textarea{background:transparent;border:none;color:var(--cao-form-field-color-text)}.label-inside .input-slot ::ng-deep input,.label-inside .input-slot ::ng-deep textarea,.label-inside .input-slot ::ng-deep select{padding-top:16px;padding-bottom:8px}.subscript-wrapper{display:flex;flex-direction:column;gap:2px}.cao-form-field__hint{font-size:.75rem;line-height:1.25rem;color:var(--cao-form-field-color-hint)}.cao-form-field__hint+.subscript-wrapper{margin-top:0}.cao-form-field.required .cao-form-field__label:after{content:\" *\";color:var(--cao-form-field-color-error)}\n"], dependencies: [{ kind: "component", type: CaoBaseIcon, selector: "cao-base-icon", inputs: ["imgSource", "isLucideIcon", "strokeWidthIcon", "iconColor", "size"] }] });
|
|
2011
|
+
}
|
|
2012
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoFormField, decorators: [{
|
|
2013
|
+
type: Component,
|
|
2014
|
+
args: [{ selector: 'cao-form-field', imports: [CaoBaseIcon], template: "<div\n class=\"cao-form-field\"\n [class.label-inside]=\"labelInside\"\n [class.error-state]=\"errorStateActive\"\n [class.disabled]=\"disabled\"\n [class.required]=\"required\"\n [style]=\"formFieldStyles()\">\n @if (label && !labelInside) {\n <label class=\"cao-form-field__label\" [for]=\"forId\">{{ label }}</label>\n }\n <div class=\"input-field\" (focusin)=\"onFocusIn()\" (focusout)=\"onFocusOut()\">\n @if (leadingIcon) {\n <cao-base-icon\n [isLucideIcon]=\"isLucideIcon\"\n [strokeWidthIcon]=\"strokeWidthIcon\"\n [imgSource]=\"leadingIcon\"\n [iconColor]=\"iconColor\"\n [size]=\"size\" />\n }\n <div class=\"input-slot\">\n @if (label && labelInside) {\n <label\n class=\"cao-form-field__label cao-form-field__label--float\"\n [class.cao-form-field__label--floated]=\"floating\"\n [for]=\"forId\">{{ label }}</label>\n }\n <ng-content select=\"[caoInput]\" />\n <ng-content select=\"cao-input\" />\n <ng-content select=\"input\" />\n <ng-content select=\"select\" />\n <ng-content select=\"textarea\" />\n <ng-content select=\"h2\" />\n <ng-content />\n </div>\n @if (trailingIcon) {\n <cao-base-icon\n [isLucideIcon]=\"isLucideIcon\"\n [iconColor]=\"iconColor\"\n [size]=\"size\"\n [imgSource]=\"trailingIcon\"\n [strokeWidthIcon]=\"strokeWidthIcon\" />\n }\n </div>\n <div class=\"subscript-wrapper\">\n @if (hintLabel) {\n <small class=\"cao-form-field__hint\">{{ hintLabel }}</small>\n }\n <ng-content select=\"cao-hint\" />\n <ng-content select=\"cao-error\" />\n </div>\n</div>", styles: [":host{--cao-form-field-bg-background: var(--input-background, #ffffff);--cao-form-field-border-color: var(--line-color, #e5e7eb);--cao-form-field-border-width: 1px;--cao-form-field-border-radius: 8px;--cao-form-field-color-error: var(--error, #dc2626);--cao-form-field-color-label: var(--primary, #111827);--cao-form-field-color-hint: var(--input-text, #9ca3af);--cao-form-field-color-text: var(--text-color-input, #111827);--cao-form-field-focus-border: var(--primary, #111827);--cao-form-field-success-border: var(--success, #16a34a);display:block;width:100%}.cao-form-field{display:flex;flex-direction:column;gap:4px;width:100%;font-family:inherit}.cao-form-field__label{display:block;font-size:.75rem;font-weight:700;line-height:1.25rem;color:var(--cao-form-field-color-label);text-transform:uppercase;letter-spacing:.02em;white-space:nowrap}.cao-form-field__label--float{position:absolute;top:50%;left:12px;transform:translateY(-50%);font-weight:500;text-transform:none;letter-spacing:0;color:var(--cao-form-field-color-hint);pointer-events:none;transition:transform .15s cubic-bezier(.4,0,.2,1),font-size .15s cubic-bezier(.4,0,.2,1),color .15s cubic-bezier(.4,0,.2,1);max-width:calc(100% - 24px);overflow:hidden;text-overflow:ellipsis}.cao-form-field__label--floated{transform:translateY(calc(-50% - 14px)) scale(.75);transform-origin:left top;color:var(--cao-form-field-color-label);font-weight:700}.input-field{position:relative;display:flex;align-items:center;width:100%;min-height:44px;background-color:var(--cao-form-field-bg-background);border:var(--cao-form-field-border-width) solid var(--cao-form-field-border-color);border-radius:var(--cao-form-field-border-radius);transition:border-color .15s cubic-bezier(.4,0,.2,1),background-color .15s cubic-bezier(.4,0,.2,1)}.input-field:focus-within{border-color:var(--cao-form-field-focus-border)}.cao-form-field.error-state .input-field{border-color:var(--cao-form-field-color-error)}.cao-form-field.disabled .input-field{opacity:.7}.input-slot{position:relative;flex:1;display:flex;align-items:center;width:100%;height:100%}.input-slot ::ng-deep input,.input-slot ::ng-deep textarea,.input-slot ::ng-deep select{width:100%;min-height:40px;border:none;outline:none;background:transparent;color:var(--cao-form-field-color-text);font-family:inherit;font-size:.875rem;padding:6px 12px;box-sizing:border-box}.input-slot ::ng-deep cao-input,.input-slot ::ng-deep .cao-input{width:100%}.input-slot ::ng-deep cao-input .input-component,.input-slot ::ng-deep cao-input .input-wrapper{width:100%;background:transparent}.input-slot ::ng-deep cao-input input,.input-slot ::ng-deep cao-input textarea{background:transparent;border:none;color:var(--cao-form-field-color-text)}.label-inside .input-slot ::ng-deep input,.label-inside .input-slot ::ng-deep textarea,.label-inside .input-slot ::ng-deep select{padding-top:16px;padding-bottom:8px}.subscript-wrapper{display:flex;flex-direction:column;gap:2px}.cao-form-field__hint{font-size:.75rem;line-height:1.25rem;color:var(--cao-form-field-color-hint)}.cao-form-field__hint+.subscript-wrapper{margin-top:0}.cao-form-field.required .cao-form-field__label:after{content:\" *\";color:var(--cao-form-field-color-error)}\n"] }]
|
|
2015
|
+
}], propDecorators: { inputBackground: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputBackground", required: false }] }], borderColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderColor", required: false }] }], borderWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderWidth", required: false }] }], borderRadius: [{ type: i0.Input, args: [{ isSignal: true, alias: "borderRadius", required: false }] }], errorColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorColor", required: false }] }], labelColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelColor", required: false }] }], hintColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintColor", required: false }] }], textColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "textColor", required: false }] }], focusBorderColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "focusBorderColor", required: false }] }], successBorderColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "successBorderColor", required: false }] }], label: [{
|
|
2016
|
+
type: Input
|
|
2017
|
+
}], labelInside: [{
|
|
2018
|
+
type: Input
|
|
2019
|
+
}], hintLabel: [{
|
|
2020
|
+
type: Input
|
|
2021
|
+
}], control: [{
|
|
2022
|
+
type: Input
|
|
2023
|
+
}], forId: [{
|
|
2024
|
+
type: Input
|
|
2025
|
+
}], errorStateMatcher: [{
|
|
2026
|
+
type: Input
|
|
2027
|
+
}], leadingIcon: [{
|
|
2028
|
+
type: Input
|
|
2029
|
+
}], trailingIcon: [{
|
|
2030
|
+
type: Input
|
|
2031
|
+
}] } });
|
|
2032
|
+
|
|
2033
|
+
class ErrorStateMatcher {
|
|
2034
|
+
isErrorState(control, formFieldControl) {
|
|
2035
|
+
if (!control) {
|
|
2036
|
+
return false;
|
|
2037
|
+
}
|
|
2038
|
+
const isSubmitted = formFieldControl && formFieldControl._isSubmitted;
|
|
2039
|
+
return !!(control.invalid &&
|
|
2040
|
+
(control.touched || control.dirty || isSubmitted));
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
class ShowOnDirtyErrorStateMatcher {
|
|
2044
|
+
isErrorState(control, formFieldControl) {
|
|
2045
|
+
if (!control) {
|
|
2046
|
+
return false;
|
|
2047
|
+
}
|
|
2048
|
+
const isSubmitted = formFieldControl && formFieldControl._isSubmitted;
|
|
2049
|
+
return !!(control.invalid && (control.dirty || isSubmitted));
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
const DEFAULT_ERROR_STATE_MATCHER = new ErrorStateMatcher();
|
|
2053
|
+
|
|
2054
|
+
class CaoHint {
|
|
2055
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoHint, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2056
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: CaoHint, isStandalone: true, selector: "cao-hint", ngImport: i0, template: "<span class=\"cao-hint\"><ng-content /></span>\n", styles: [":host{display:block;font-size:.75rem;line-height:1.25rem;color:var(--cao-form-field-color-hint, var(--input-text, #9ca3af))}.cao-hint{display:block}\n"] });
|
|
2057
|
+
}
|
|
2058
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoHint, decorators: [{
|
|
2059
|
+
type: Component,
|
|
2060
|
+
args: [{ selector: 'cao-hint', imports: [], template: "<span class=\"cao-hint\"><ng-content /></span>\n", styles: [":host{display:block;font-size:.75rem;line-height:1.25rem;color:var(--cao-form-field-color-hint, var(--input-text, #9ca3af))}.cao-hint{display:block}\n"] }]
|
|
2061
|
+
}] });
|
|
2062
|
+
|
|
2063
|
+
class CaoError {
|
|
2064
|
+
errorStateMatcher;
|
|
2065
|
+
formField = inject(CaoFormField, { optional: true });
|
|
2066
|
+
get control() {
|
|
2067
|
+
return this.formField?.control ?? null;
|
|
2068
|
+
}
|
|
2069
|
+
get hasErrorState() {
|
|
2070
|
+
const control = this.control;
|
|
2071
|
+
if (!control) {
|
|
2072
|
+
return false;
|
|
2073
|
+
}
|
|
2074
|
+
const matcher = this.errorStateMatcher ?? this.formField?.errorStateMatcher;
|
|
2075
|
+
return matcher
|
|
2076
|
+
? matcher.isErrorState(control, this.formField)
|
|
2077
|
+
: !!(control.invalid && (control.touched || control.dirty));
|
|
2078
|
+
}
|
|
2079
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoError, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2080
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: CaoError, isStandalone: true, selector: "cao-error", inputs: { errorStateMatcher: "errorStateMatcher" }, ngImport: i0, template: "@if (hasErrorState) {\n <div class=\"cao-error\" role=\"alert\">\n <ng-content />\n </div>\n}", styles: [":host{display:block;font-size:.75rem;line-height:1.25rem;color:var(--cao-form-field-color-error, var(--error, #dc2626))}.cao-error{display:block}\n"] });
|
|
2081
|
+
}
|
|
2082
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: CaoError, decorators: [{
|
|
2083
|
+
type: Component,
|
|
2084
|
+
args: [{ selector: 'cao-error', imports: [], template: "@if (hasErrorState) {\n <div class=\"cao-error\" role=\"alert\">\n <ng-content />\n </div>\n}", styles: [":host{display:block;font-size:.75rem;line-height:1.25rem;color:var(--cao-form-field-color-error, var(--error, #dc2626))}.cao-error{display:block}\n"] }]
|
|
2085
|
+
}], propDecorators: { errorStateMatcher: [{
|
|
2086
|
+
type: Input
|
|
2087
|
+
}] } });
|
|
2088
|
+
|
|
1917
2089
|
class CaoCardComponent {
|
|
1918
2090
|
variant = "horizontal";
|
|
1919
2091
|
title;
|
|
@@ -3275,5 +3447,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
3275
3447
|
* Generated bundle index. Do not edit.
|
|
3276
3448
|
*/
|
|
3277
3449
|
|
|
3278
|
-
export { BaseAlert, BaseAlertService, BaseDialog, BaseDialogService, BaseFilterTablePaginatedService, BaseFilterTableService, BaseModal, BaseModalService, BasePaginationService, BaseTable, BaseTablePaginated, BaseTableService, BaseTimeRange, CaoAutocompleteComponent, CaoBaseButtonComponent, CaoBaseIcon, CaoBaseInput, CaoBaseToggleComponent, CaoCardComponent, CaoDropDownComponent, CaoKpi, CaoSkeletonComponent, CaoTabGroup, CaoTabPanel, Footer, LinksButton, Paginator, StepComponent, StepperComponent, TablePaginatedService, TimePicker, getPtBrPaginatorIntlBasePaginated, getPtBrPaginatorIntlBaseTable };
|
|
3450
|
+
export { BaseAlert, BaseAlertService, BaseDialog, BaseDialogService, BaseFilterTablePaginatedService, BaseFilterTableService, BaseModal, BaseModalService, BasePaginationService, BaseTable, BaseTablePaginated, BaseTableService, BaseTimeRange, CaoAutocompleteComponent, CaoBaseButtonComponent, CaoBaseIcon, CaoBaseInput, CaoBaseToggleComponent, CaoCardComponent, CaoDropDownComponent, CaoError, CaoFormField, CaoHint, CaoKpi, CaoSkeletonComponent, CaoTabGroup, CaoTabPanel, DEFAULT_ERROR_STATE_MATCHER, ErrorStateMatcher, Footer, LinksButton, Paginator, ShowOnDirtyErrorStateMatcher, StepComponent, StepperComponent, TablePaginatedService, TimePicker, getPtBrPaginatorIntlBasePaginated, getPtBrPaginatorIntlBaseTable };
|
|
3279
3451
|
//# sourceMappingURL=ngx-opalbytes-components.mjs.map
|