@grazziotin/react-components-next 1.0.0 → 1.0.1
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 +184 -105
- package/dist/{chunk-NHHZBMJL.mjs → chunk-4DIPDYEU.mjs} +18 -3
- package/dist/chunk-4DIPDYEU.mjs.map +1 -0
- package/dist/chunk-XNWAGZVV.mjs +467 -0
- package/dist/chunk-XNWAGZVV.mjs.map +1 -0
- package/dist/functions/index.mjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +368 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/dist/ui/index.d.mts +98 -6
- package/dist/ui/index.d.ts +98 -6
- package/dist/ui/index.js +367 -2
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/index.mjs +2 -2
- package/package.json +2 -3
- package/dist/chunk-CNXFSE26.mjs +0 -120
- package/dist/chunk-CNXFSE26.mjs.map +0 -1
- package/dist/chunk-NHHZBMJL.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,132 +1,205 @@
|
|
|
1
|
-
# React Components Library
|
|
1
|
+
# Grazziotin React Components Library
|
|
2
2
|
|
|
3
|
-
Biblioteca de componentes React reutilizáveis, construída com TypeScript
|
|
3
|
+
Biblioteca de componentes React reutilizáveis para o projeto Grazziotin, construída com TypeScript, Tailwind CSS, Material UI e Mantine.
|
|
4
4
|
|
|
5
5
|
## Instalação
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npm install react-components-next
|
|
8
|
+
npm install @grazziotin/react-components-next
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
### Requisitos
|
|
12
|
+
|
|
13
|
+
- React `>= 18`
|
|
14
|
+
- Tailwind CSS v4 configurado no projeto consumidor
|
|
15
|
+
- `ThemeProvider` do MUI e `MantineProvider` do Mantine envolvendo a aplicação
|
|
16
|
+
|
|
17
|
+
### Configuração no projeto consumidor
|
|
18
|
+
|
|
19
|
+
Importe os estilos da biblioteca e configure as variáveis CSS do tema:
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import "@grazziotin/react-components-next/styles";
|
|
23
|
+
|
|
24
|
+
import { CssBaseline, ThemeProvider, createTheme } from "@mui/material";
|
|
25
|
+
import { MantineProvider } from "@mantine/core";
|
|
26
|
+
import "@mantine/core/styles.css";
|
|
27
|
+
|
|
28
|
+
const theme = createTheme({
|
|
29
|
+
typography: { fontFamily: "var(--font-family, inherit)" },
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export function AppProviders({ children }: { children: React.ReactNode }) {
|
|
33
|
+
return (
|
|
34
|
+
<ThemeProvider theme={theme}>
|
|
35
|
+
<CssBaseline />
|
|
36
|
+
<MantineProvider>{children}</MantineProvider>
|
|
37
|
+
</ThemeProvider>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
```css
|
|
43
|
+
:root {
|
|
44
|
+
--primary-color: #00b2a6;
|
|
45
|
+
--font-family: "Poppins", sans-serif;
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
> **Atenção:** vários componentes usam classes do Tailwind CSS e dependem do MUI/Mantine. Certifique-se de que o Tailwind esteja configurado e os providers estejam na raiz da aplicação.
|
|
12
50
|
|
|
13
51
|
## Componentes disponíveis
|
|
14
52
|
|
|
15
|
-
| Componente
|
|
16
|
-
|
|
|
17
|
-
| `
|
|
18
|
-
| `
|
|
19
|
-
| `
|
|
20
|
-
| `
|
|
21
|
-
|
|
53
|
+
| Componente | Descrição |
|
|
54
|
+
| ------------ | --------------------------------------------------------------- |
|
|
55
|
+
| `Card` | Container com cabeçalho colorido, título, ícone e tooltip |
|
|
56
|
+
| `Dialog` | Modal baseado no MUI com título, conteúdo e ações opcionais |
|
|
57
|
+
| `DataTable` | Tabela de dados com MUI DataGrid, filtros e textos em português |
|
|
58
|
+
| `Tab`/`Tabs` | Abas estilizadas com indicador e tipografia customizáveis |
|
|
59
|
+
|
|
60
|
+
## Funções utilitárias
|
|
61
|
+
|
|
62
|
+
| Função | Descrição |
|
|
63
|
+
| --------------- | ------------------------------------------------ |
|
|
64
|
+
| `cn` | Mescla classes CSS com `clsx` e `tailwind-merge` |
|
|
65
|
+
| `nvl` | Retorna valor padrão quando `null`/`undefined` |
|
|
66
|
+
| `formatCpfCnpj` | Formata CPF ou CNPJ |
|
|
67
|
+
| `formatPhoneBr` | Formata telefone brasileiro |
|
|
22
68
|
|
|
23
69
|
## Uso
|
|
24
70
|
|
|
25
71
|
```tsx
|
|
26
72
|
import {
|
|
27
|
-
Button,
|
|
28
73
|
Card,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} from "react-components-next";
|
|
74
|
+
Dialog,
|
|
75
|
+
DataTable,
|
|
76
|
+
Tab,
|
|
77
|
+
Tabs,
|
|
78
|
+
cn,
|
|
79
|
+
formatCpfCnpj,
|
|
80
|
+
} from "@grazziotin/react-components-next";
|
|
81
|
+
import type { GridColDef } from "@mui/x-data-grid";
|
|
82
|
+
|
|
83
|
+
const colunas: GridColDef[] = [
|
|
84
|
+
{ field: "id", headerName: "ID", width: 80 },
|
|
85
|
+
{ field: "nome", headerName: "Nome", flex: 1 },
|
|
86
|
+
{ field: "documento", headerName: "CPF/CNPJ", width: 180 },
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
const linhas = [
|
|
90
|
+
{ id: 1, nome: "Ana Silva", documento: formatCpfCnpj("12345678901") },
|
|
91
|
+
];
|
|
36
92
|
|
|
37
93
|
export function Example() {
|
|
38
94
|
return (
|
|
39
|
-
<Card>
|
|
40
|
-
<
|
|
41
|
-
<CardTitle>Perfil</CardTitle>
|
|
42
|
-
</CardHeader>
|
|
43
|
-
<CardContent>
|
|
44
|
-
<div className="flex items-center gap-3">
|
|
45
|
-
<Avatar fallback="João Silva" size="md" />
|
|
46
|
-
<div>
|
|
47
|
-
<p>João Silva</p>
|
|
48
|
-
<Badge variant="success" dot>
|
|
49
|
-
Online
|
|
50
|
-
</Badge>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
<Input label="E-mail" type="email" placeholder="joao@exemplo.com" />
|
|
54
|
-
<Button variant="primary" fullWidth>
|
|
55
|
-
Salvar
|
|
56
|
-
</Button>
|
|
57
|
-
</CardContent>
|
|
95
|
+
<Card title="Colaboradores" toolTip className={cn("max-w-3xl")}>
|
|
96
|
+
<DataTable rows={linhas} columns={colunas} pageSizeOptions={[10, 20]} />
|
|
58
97
|
</Card>
|
|
59
98
|
);
|
|
60
99
|
}
|
|
61
100
|
```
|
|
62
101
|
|
|
102
|
+
## Entry points
|
|
103
|
+
|
|
104
|
+
A biblioteca expõe múltiplos pontos de entrada:
|
|
105
|
+
|
|
106
|
+
| Import | Conteúdo |
|
|
107
|
+
| --------------------------------------------- | ---------------------------------------- |
|
|
108
|
+
| `@grazziotin/react-components-next` | Componentes e funções (export principal) |
|
|
109
|
+
| `@grazziotin/react-components-next/ui` | Apenas componentes de UI |
|
|
110
|
+
| `@grazziotin/react-components-next/functions` | Apenas funções utilitárias |
|
|
111
|
+
| `@grazziotin/react-components-next/styles` | CSS compilado da biblioteca |
|
|
112
|
+
|
|
63
113
|
## Componentes
|
|
64
114
|
|
|
65
|
-
###
|
|
115
|
+
### Card
|
|
66
116
|
|
|
67
117
|
```tsx
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
118
|
+
<Card
|
|
119
|
+
title="Título do card"
|
|
120
|
+
toolTip={false}
|
|
121
|
+
width="100%"
|
|
122
|
+
height="auto"
|
|
123
|
+
titleColor="var(--primary-color)"
|
|
124
|
+
borderRadius="10px"
|
|
125
|
+
borderTitle="10px 10px 0 0"
|
|
126
|
+
icon={<Icon />}
|
|
127
|
+
onClick={() => {}}
|
|
128
|
+
className="text-sm"
|
|
75
129
|
>
|
|
76
|
-
|
|
77
|
-
</
|
|
130
|
+
Conteúdo do card
|
|
131
|
+
</Card>
|
|
78
132
|
```
|
|
79
133
|
|
|
80
|
-
###
|
|
134
|
+
### Dialog
|
|
81
135
|
|
|
82
136
|
```tsx
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
137
|
+
<Dialog
|
|
138
|
+
open={open}
|
|
139
|
+
title="Confirmar exclusão"
|
|
140
|
+
onClose={() => setOpen(false)}
|
|
141
|
+
maxWidth="sm"
|
|
142
|
+
blurBackdrop={false}
|
|
143
|
+
actions={<button onClick={() => setOpen(false)}>OK</button>}
|
|
144
|
+
>
|
|
145
|
+
Deseja realmente excluir este item?
|
|
146
|
+
</Dialog>
|
|
93
147
|
```
|
|
94
148
|
|
|
95
|
-
###
|
|
149
|
+
### DataTable
|
|
150
|
+
|
|
151
|
+
Wrapper sobre o MUI `DataGrid` com estilização, textos em português e operador de filtro "entre" automático para colunas `string` e `number`. Aceita todas as props do `DataGrid`.
|
|
96
152
|
|
|
97
153
|
```tsx
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
<CardFooter>
|
|
105
|
-
<Button>Ação</Button>
|
|
106
|
-
</CardFooter>
|
|
107
|
-
</Card>
|
|
154
|
+
<DataTable
|
|
155
|
+
rows={dados}
|
|
156
|
+
columns={colunas}
|
|
157
|
+
loading={carregando}
|
|
158
|
+
pageSizeOptions={[10, 20, 50]}
|
|
159
|
+
/>
|
|
108
160
|
```
|
|
109
161
|
|
|
110
|
-
###
|
|
162
|
+
### Tab / Tabs
|
|
111
163
|
|
|
112
164
|
```tsx
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
165
|
+
const [value, setValue] = useState(0);
|
|
166
|
+
|
|
167
|
+
<Tabs
|
|
168
|
+
value={value}
|
|
169
|
+
onChange={(_, newValue) => setValue(newValue)}
|
|
170
|
+
color="var(--primary-color)"
|
|
116
171
|
>
|
|
117
|
-
|
|
118
|
-
|
|
172
|
+
<Tab label="Geral" />
|
|
173
|
+
<Tab label="Detalhes" />
|
|
174
|
+
</Tabs>;
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Funções
|
|
178
|
+
|
|
179
|
+
### cn
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
cn("px-4 py-2", condicao && "bg-teal-500", "px-6");
|
|
119
183
|
```
|
|
120
184
|
|
|
121
|
-
###
|
|
185
|
+
### nvl
|
|
122
186
|
|
|
123
187
|
```tsx
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
188
|
+
nvl(valor, "padrão"); // retorna "padrão" se valor for null/undefined
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### formatCpfCnpj
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
formatCpfCnpj("12345678901"); // "123.456.789-01"
|
|
195
|
+
formatCpfCnpj("12345678000199"); // "12.345.678/0001-99"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### formatPhoneBr
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
formatPhoneBr("11987654321"); // "(11) 98765-4321"
|
|
202
|
+
formatPhoneBr("1133334444"); // "(11) 3333-4444"
|
|
130
203
|
```
|
|
131
204
|
|
|
132
205
|
## Desenvolvimento
|
|
@@ -135,17 +208,20 @@ export function Example() {
|
|
|
135
208
|
# Instalar dependências
|
|
136
209
|
npm install
|
|
137
210
|
|
|
138
|
-
#
|
|
139
|
-
npm run
|
|
211
|
+
# Storybook (visualização e documentação dos componentes)
|
|
212
|
+
npm run storybook
|
|
213
|
+
|
|
214
|
+
# Build estático do Storybook
|
|
215
|
+
npm run build-storybook
|
|
140
216
|
|
|
141
217
|
# Build da biblioteca para npm
|
|
142
218
|
npm run build:lib
|
|
143
219
|
|
|
144
|
-
# Build completo (biblioteca + Next.js)
|
|
145
|
-
npm run build:all
|
|
146
|
-
|
|
147
220
|
# Verificar tipos TypeScript
|
|
148
221
|
npm run type-check
|
|
222
|
+
|
|
223
|
+
# Lint
|
|
224
|
+
npm run lint
|
|
149
225
|
```
|
|
150
226
|
|
|
151
227
|
## Publicar no npm
|
|
@@ -162,24 +238,27 @@ npm publish
|
|
|
162
238
|
|
|
163
239
|
```
|
|
164
240
|
src/
|
|
165
|
-
├── app/
|
|
166
|
-
│ ├──
|
|
167
|
-
│
|
|
168
|
-
│
|
|
169
|
-
|
|
170
|
-
│
|
|
171
|
-
│ ├── badge/
|
|
172
|
-
│ └── avatar/
|
|
173
|
-
├── components/ # Biblioteca de componentes (publicada no npm)
|
|
174
|
-
│ ├── index.ts # Entrypoint principal
|
|
241
|
+
├── app/ # Next.js App Router (página inicial mínima)
|
|
242
|
+
│ ├── globals.css # Variáveis CSS e tema
|
|
243
|
+
│ ├── layout.tsx # Providers MUI + Mantine
|
|
244
|
+
│ └── page.tsx
|
|
245
|
+
├── components/
|
|
246
|
+
│ ├── index.ts
|
|
175
247
|
│ └── ui/
|
|
176
|
-
│ ├──
|
|
177
|
-
│ ├──
|
|
178
|
-
│ ├──
|
|
179
|
-
│
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
248
|
+
│ ├── card/
|
|
249
|
+
│ ├── dialog/
|
|
250
|
+
│ ├── data-table/
|
|
251
|
+
│ └── tab/
|
|
252
|
+
├── core/ # Utilitários internos
|
|
253
|
+
├── functions/
|
|
254
|
+
│ ├── cn/
|
|
255
|
+
│ ├── nvl/
|
|
256
|
+
│ ├── format-cpf-cnpj/
|
|
257
|
+
│ └── format-phone-br/
|
|
258
|
+
├── providers/
|
|
259
|
+
├── styles/
|
|
260
|
+
│ └── index.css # Entrada do Tailwind para o build CSS
|
|
261
|
+
└── index.ts # Entrypoint principal da biblioteca
|
|
183
262
|
```
|
|
184
263
|
|
|
185
264
|
## Licença
|
|
@@ -2,6 +2,8 @@ import { twMerge } from 'tailwind-merge';
|
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
|
+
var __defProps = Object.defineProperties;
|
|
6
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
7
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
9
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -17,6 +19,19 @@ var __spreadValues = (a, b) => {
|
|
|
17
19
|
}
|
|
18
20
|
return a;
|
|
19
21
|
};
|
|
22
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
23
|
+
var __objRest = (source, exclude) => {
|
|
24
|
+
var target = {};
|
|
25
|
+
for (var prop in source)
|
|
26
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
27
|
+
target[prop] = source[prop];
|
|
28
|
+
if (source != null && __getOwnPropSymbols)
|
|
29
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
30
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
31
|
+
target[prop] = source[prop];
|
|
32
|
+
}
|
|
33
|
+
return target;
|
|
34
|
+
};
|
|
20
35
|
function cn(...values) {
|
|
21
36
|
return twMerge(clsx(values));
|
|
22
37
|
}
|
|
@@ -59,6 +74,6 @@ function formatPhoneBr(phone) {
|
|
|
59
74
|
return digits.replace(/(\d{2})(\d{5})(\d+)/, "($1) $2-$3");
|
|
60
75
|
}
|
|
61
76
|
|
|
62
|
-
export { __spreadValues, cn, formatCpfCnpj, formatPhoneBr, nvl };
|
|
63
|
-
//# sourceMappingURL=chunk-
|
|
64
|
-
//# sourceMappingURL=chunk-
|
|
77
|
+
export { __objRest, __spreadProps, __spreadValues, cn, formatCpfCnpj, formatPhoneBr, nvl };
|
|
78
|
+
//# sourceMappingURL=chunk-4DIPDYEU.mjs.map
|
|
79
|
+
//# sourceMappingURL=chunk-4DIPDYEU.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/functions/cn/cn.ts","../src/functions/nvl/nvl.ts","../src/core/remove-digits.ts","../src/functions/format-cpf-cnpj/format-cpf-cnpj.ts","../src/functions/format-phone-br/format-phone-br.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIO,SAAS,MAAM,MAAA,EAA8B;AAClD,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;;;ACIO,SAAS,GAAA,CAAO,OAA6B,YAAA,EAAoB;AACtE,EAAA,OAAO,KAAA,IAAA,IAAA,GAAA,KAAA,GAAS,YAAA;AAClB;;;ACXO,SAAS,aAAa,KAAA,EAAuB;AAClD,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAChC;;;ACOO,SAAS,cAAc,IAAA,EAAuB;AACnD,EAAA,IAAI,CAAC,MAAM,OAAO,EAAA;AAClB,EAAA,MAAM,KAAA,GAAQ,aAAa,IAAI,CAAA;AAE/B,EAAA,IAAI,CAAC,OAAO,OAAO,EAAA;AACnB,EAAA,IAAI,KAAA,CAAM,UAAU,EAAA,EAAI;AACtB,IAAA,MAAM,GAAA,GAAM,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC7B,IAAA,OAAO,GAAA,CACJ,OAAA,CAAQ,aAAA,EAAe,OAAO,CAAA,CAC9B,OAAA,CAAQ,aAAA,EAAe,OAAO,CAAA,CAC9B,OAAA,CAAQ,mBAAA,EAAqB,OAAO,CAAA;AAAA,EACzC;AAEA,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AAC9B,EAAA,OAAO,IAAA,CACJ,OAAA,CAAQ,cAAA,EAAgB,OAAO,EAC/B,OAAA,CAAQ,uBAAA,EAAyB,UAAU,CAAA,CAC3C,QAAQ,eAAA,EAAiB,QAAQ,CAAA,CACjC,OAAA,CAAQ,eAAe,OAAO,CAAA;AACnC;;;ACnBO,SAAS,cAAc,KAAA,EAAwB;AACpD,EAAA,IAAI,CAAC,OAAO,OAAO,EAAA;AACnB,EAAA,MAAM,SAAS,YAAA,CAAa,KAAK,CAAA,CAAE,KAAA,CAAM,GAAG,EAAE,CAAA;AAE9C,EAAA,IAAI,CAAC,QAAQ,OAAO,EAAA;AACpB,EAAA,IAAI,MAAA,CAAO,MAAA,IAAU,CAAA,EAAG,OAAO,MAAA;AAC/B,EAAA,IAAI,MAAA,CAAO,UAAU,CAAA,EAAG;AACtB,IAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,cAAA,EAAgB,SAAS,CAAA;AAAA,EACjD;AACA,EAAA,IAAI,MAAA,CAAO,UAAU,EAAA,EAAI;AACvB,IAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,qBAAA,EAAuB,YAAY,CAAA;AAAA,EAC3D;AACA,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,qBAAA,EAAuB,YAAY,CAAA;AAC3D","file":"chunk-4DIPDYEU.mjs","sourcesContent":["import { twMerge } from \"tailwind-merge\";\r\nimport { clsx } from \"clsx\";\r\nimport type { ClassValue } from \"./utils/interfaces\";\r\n\r\nexport function cn(...values: ClassValue[]): string {\r\n return twMerge(clsx(values));\r\n}\r\n","/**\r\n * Função NVL (Null Value Logic) - retorna valor padrão se o valor for null/undefined\r\n * @param {T | null | undefined} value - Valor a ser verificado\r\n * @param {T} defaultValue - Valor padrão a ser retornado se value for null/undefined\r\n * @returns {T} Value se não for null/undefined, senão defaultValue\r\n * @template T - Tipo do valor\r\n * @example\r\n * nvl(null, 'padrão') // Retorna: 'padrão'\r\n * nvl('valor', 'padrão') // Retorna: 'valor'\r\n */\r\nexport function nvl<T>(value: T | null | undefined, defaultValue: T): T {\r\n return value ?? defaultValue;\r\n}\r\n","/** Remove tudo que não for dígito. */\r\nexport function removeDigits(value: string): string {\r\n return value.replace(/\\D/g, \"\");\r\n}\r\n","import { removeDigits } from \"../../core/remove-digits\";\r\n\r\n/**\r\n * Formata CPF (até 11 dígitos) ou CNPJ (12–14 dígitos) conforme o tamanho.\r\n * @param data - Valor com ou sem formatação\r\n * @returns CPF `000.000.000-00` ou CNPJ `00.000.000/0000-00`; string vazia se ausente\r\n * @example\r\n * formatCpfCnpj(\"12345678901\") // \"123.456.789-01\"\r\n * formatCpfCnpj(\"12345678000199\") // \"12.345.678/0001-99\"\r\n */\r\nexport function formatCpfCnpj(data?: string): string {\r\n if (!data) return \"\";\r\n const value = removeDigits(data);\r\n\r\n if (!value) return \"\";\r\n if (value.length <= 11) {\r\n const cpf = value.slice(0, 11);\r\n return cpf\r\n .replace(/(\\d{3})(\\d)/, \"$1.$2\")\r\n .replace(/(\\d{3})(\\d)/, \"$1.$2\")\r\n .replace(/(\\d{3})(\\d{1,2})$/, \"$1-$2\");\r\n }\r\n\r\n const cnpj = value.slice(0, 14);\r\n return cnpj\r\n .replace(/^(\\d{2})(\\d)/, \"$1.$2\")\r\n .replace(/^(\\d{2})\\.(\\d{3})(\\d)/, \"$1.$2.$3\")\r\n .replace(/\\.(\\d{3})(\\d)/, \".$1/$2\")\r\n .replace(/(\\d{4})(\\d)/, \"$1-$2\");\r\n}\r\n","import { removeDigits } from \"../../core/remove-digits\";\r\n\r\n/**\r\n * Formata telefone brasileiro (até 11 dígitos): fixo `(00) 0000-0000` ou celular `(00) 00000-0000`.\r\n * @param phone - Valor com ou sem formatação\r\n * @returns Telefone formatado ou string vazia se ausente\r\n * @example\r\n * formatPhoneBr(\"11987654321\") // \"(11) 98765-4321\"\r\n * formatPhoneBr(\"1133334444\") // \"(11) 3333-4444\"\r\n */\r\nexport function formatPhoneBr(phone?: string): string {\r\n if (!phone) return \"\";\r\n const digits = removeDigits(phone).slice(0, 11);\r\n\r\n if (!digits) return \"\";\r\n if (digits.length <= 2) return digits;\r\n if (digits.length <= 6) {\r\n return digits.replace(/(\\d{2})(\\d+)/, \"($1) $2\");\r\n }\r\n if (digits.length <= 10) {\r\n return digits.replace(/(\\d{2})(\\d{4})(\\d+)/, \"($1) $2-$3\");\r\n }\r\n return digits.replace(/(\\d{2})(\\d{5})(\\d+)/, \"($1) $2-$3\");\r\n}\r\n"]}
|