@grazziotin/react-components-next 2.2.1 → 3.0.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 +53 -58
- package/dist/accessibility/index.mjs +3 -137
- package/dist/accessibility/index.mjs.map +1 -1
- package/dist/chunk-4AYAPBGW.mjs +139 -0
- package/dist/chunk-4AYAPBGW.mjs.map +1 -0
- package/dist/{chunk-BWW3F4R4.mjs → chunk-DM64WOVD.mjs} +4 -34
- package/dist/chunk-DM64WOVD.mjs.map +1 -0
- package/dist/chunk-OFMJB5WP.mjs +960 -0
- package/dist/chunk-OFMJB5WP.mjs.map +1 -0
- package/dist/chunk-QLBDGAEM.mjs +24 -0
- package/dist/chunk-QLBDGAEM.mjs.map +1 -0
- package/dist/chunk-YOSPWY5K.mjs +35 -0
- package/dist/chunk-YOSPWY5K.mjs.map +1 -0
- package/dist/functions/index.mjs +2 -1
- package/dist/index.css +1 -1
- package/dist/index.d.mts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +1248 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +7 -0
- package/dist/index.mjs.map +1 -0
- package/dist/providers/index.d.mts +15 -0
- package/dist/providers/index.d.ts +15 -0
- package/dist/providers/index.js +27 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/index.mjs +4 -0
- package/dist/providers/index.mjs.map +1 -0
- package/dist/ui/index.d.mts +2 -2
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.js +70 -8
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/index.mjs +3 -896
- package/dist/ui/index.mjs.map +1 -1
- package/package.json +25 -8
- package/dist/chunk-BWW3F4R4.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -8,34 +8,30 @@ Biblioteca de componentes React reutilizáveis para o projeto Grazziotin, constr
|
|
|
8
8
|
npm install @grazziotin/react-components-next
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
Instale também as peer dependencies necessárias:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @mui/material @mui/x-data-grid @emotion/react @emotion/styled @mantine/core @mantine/hooks
|
|
15
|
+
```
|
|
16
|
+
|
|
11
17
|
### Requisitos
|
|
12
18
|
|
|
13
19
|
- React `>= 18`
|
|
14
|
-
-
|
|
15
|
-
-
|
|
20
|
+
- Material UI (`@mui/material`, `@mui/x-data-grid`) e Emotion
|
|
21
|
+
- Mantine (`@mantine/core`, `@mantine/hooks`)
|
|
22
|
+
- `GrazziotinProviders` (ou `ThemeProvider` do MUI + `MantineProvider`) envolvendo a aplicação
|
|
16
23
|
|
|
17
24
|
### Configuração no projeto consumidor
|
|
18
25
|
|
|
19
|
-
|
|
26
|
+
Configure os providers na raiz da aplicação. Os estilos Tailwind da biblioteca são carregados automaticamente ao importar componentes de `/ui` ou do entry point raiz — não é necessário importar `/styles` manualmente (o export `/styles` continua disponível para uso explícito).
|
|
20
27
|
|
|
21
28
|
```tsx
|
|
22
|
-
import "@grazziotin/react-components-next/styles";
|
|
23
|
-
|
|
24
|
-
import { CssBaseline, ThemeProvider, createTheme } from "@mui/material";
|
|
25
|
-
import { MantineProvider } from "@mantine/core";
|
|
26
29
|
import "@mantine/core/styles.css";
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
typography: { fontFamily: "var(--font-family, inherit)" },
|
|
30
|
-
});
|
|
31
|
+
import { GrazziotinProviders } from "@grazziotin/react-components-next/providers";
|
|
31
32
|
|
|
32
33
|
export function AppProviders({ children }: { children: React.ReactNode }) {
|
|
33
|
-
return
|
|
34
|
-
<ThemeProvider theme={theme}>
|
|
35
|
-
<CssBaseline />
|
|
36
|
-
<MantineProvider>{children}</MantineProvider>
|
|
37
|
-
</ThemeProvider>
|
|
38
|
-
);
|
|
34
|
+
return <GrazziotinProviders>{children}</GrazziotinProviders>;
|
|
39
35
|
}
|
|
40
36
|
```
|
|
41
37
|
|
|
@@ -46,39 +42,45 @@ export function AppProviders({ children }: { children: React.ReactNode }) {
|
|
|
46
42
|
}
|
|
47
43
|
```
|
|
48
44
|
|
|
49
|
-
> **Atenção:**
|
|
45
|
+
> **Atenção:** os estilos do Mantine (`@mantine/core/styles.css`) ainda precisam ser importados no projeto consumidor. Os providers MUI/Mantine são obrigatórios.
|
|
50
46
|
|
|
51
47
|
## Componentes disponíveis
|
|
52
48
|
|
|
49
|
+
| Componente | Descrição |
|
|
50
|
+
| -------------- | --------------------------------------------------------------- |
|
|
51
|
+
| `Card` | Container com cabeçalho colorido, título, ícone e tooltip |
|
|
52
|
+
| `Dialog` | Modal baseado no MUI com título, conteúdo e ações opcionais |
|
|
53
|
+
| `DataTable` | Tabela de dados com MUI DataGrid, filtros e textos em português |
|
|
54
|
+
| `Tab`/`Tabs` | Abas estilizadas com indicador e tipografia customizáveis |
|
|
55
|
+
| `Input` | Campo de texto com máscaras e estilização MUI |
|
|
56
|
+
| `InputSelect` | Select com grid de opções |
|
|
57
|
+
| `Filter` | Drawer de filtros com campos configuráveis |
|
|
53
58
|
|
|
54
|
-
|
|
55
|
-
| ------------ | --------------------------------------------------------------- |
|
|
56
|
-
| `Card` | Container com cabeçalho colorido, título, ícone e tooltip |
|
|
57
|
-
| `Dialog` | Modal baseado no MUI com título, conteúdo e ações opcionais |
|
|
58
|
-
| `DataTable` | Tabela de dados com MUI DataGrid, filtros e textos em português |
|
|
59
|
-
| `Tab`/`Tabs` | Abas estilizadas com indicador e tipografia customizáveis |
|
|
59
|
+
## Acessibilidade
|
|
60
60
|
|
|
61
|
+
| Export | Descrição |
|
|
62
|
+
| --------- | -------------------------------------- |
|
|
63
|
+
| `Say` | Componente de leitura de tela (toast) |
|
|
64
|
+
| `useSay` | Hook para disparar feedback por voz |
|
|
61
65
|
|
|
62
66
|
## Funções utilitárias
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
|
|
68
|
+
| Função | Descrição |
|
|
69
|
+
| ---------------- | ------------------------------------------------ |
|
|
70
|
+
| `cn` | Mescla classes CSS com `clsx` e `tailwind-merge` |
|
|
71
|
+
| `nvl` | Retorna valor padrão quando `null`/`undefined` |
|
|
72
|
+
| `formatCpfCnpj` | Formata CPF ou CNPJ |
|
|
73
|
+
| `formatPhoneBr` | Formata telefone brasileiro |
|
|
74
|
+
| `formatPriceBrl` | Formata valor monetário em BRL |
|
|
75
|
+
| `formatItem170` | Formata item 170 |
|
|
76
|
+
| `formatItem150` | Formata item 150 |
|
|
72
77
|
|
|
73
78
|
## Uso
|
|
74
79
|
|
|
75
80
|
```tsx
|
|
76
81
|
import {
|
|
77
82
|
Card,
|
|
78
|
-
Dialog,
|
|
79
83
|
DataTable,
|
|
80
|
-
Tab,
|
|
81
|
-
Tabs,
|
|
82
84
|
cn,
|
|
83
85
|
formatCpfCnpj,
|
|
84
86
|
} from "@grazziotin/react-components-next";
|
|
@@ -107,14 +109,14 @@ export function Example() {
|
|
|
107
109
|
|
|
108
110
|
A biblioteca expõe múltiplos pontos de entrada:
|
|
109
111
|
|
|
110
|
-
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
| `@grazziotin/react-components-next`
|
|
114
|
-
| `@grazziotin/react-components-next/
|
|
115
|
-
| `@grazziotin/react-components-next/
|
|
116
|
-
| `@grazziotin/react-components-next/
|
|
117
|
-
|
|
112
|
+
| Import | Conteúdo |
|
|
113
|
+
| ----------------------------------------------- | --------------------------------------------- |
|
|
114
|
+
| `@grazziotin/react-components-next` | Componentes, funções, acessibilidade e providers |
|
|
115
|
+
| `@grazziotin/react-components-next/ui` | Apenas componentes de UI |
|
|
116
|
+
| `@grazziotin/react-components-next/functions` | Apenas funções utilitárias |
|
|
117
|
+
| `@grazziotin/react-components-next/accessibility` | Componentes de acessibilidade (`Say`, `useSay`) |
|
|
118
|
+
| `@grazziotin/react-components-next/providers` | `GrazziotinProviders` e `MantineAppProvider` |
|
|
119
|
+
| `@grazziotin/react-components-next/styles` | CSS compilado da biblioteca (opcional — já incluído ao importar `/ui` ou `.`) |
|
|
118
120
|
|
|
119
121
|
## Componentes
|
|
120
122
|
|
|
@@ -244,24 +246,17 @@ npm publish
|
|
|
244
246
|
|
|
245
247
|
```
|
|
246
248
|
src/
|
|
247
|
-
├── app/ # Next.js App Router (
|
|
248
|
-
│ ├── globals.css
|
|
249
|
-
│ ├── layout.tsx
|
|
249
|
+
├── app/ # Next.js App Router (demo local, não publicado)
|
|
250
|
+
│ ├── globals.css
|
|
251
|
+
│ ├── layout.tsx
|
|
250
252
|
│ └── page.tsx
|
|
251
253
|
├── components/
|
|
254
|
+
│ ├── accessibility/ # Say, useSay
|
|
252
255
|
│ ├── index.ts
|
|
253
|
-
│ └── ui/
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
│ └── tab/
|
|
258
|
-
├── core/ # Utilitários internos
|
|
259
|
-
├── functions/
|
|
260
|
-
│ ├── cn/
|
|
261
|
-
│ ├── nvl/
|
|
262
|
-
│ ├── format-cpf-cnpj/
|
|
263
|
-
│ └── format-phone-br/
|
|
264
|
-
├── providers/
|
|
256
|
+
│ └── ui/ # Card, Dialog, DataTable, Tab, Input, Filter...
|
|
257
|
+
├── core/ # Utilitários internos (não exportados)
|
|
258
|
+
├── functions/ # cn, nvl, formatters
|
|
259
|
+
├── providers/ # GrazziotinProviders, MantineAppProvider
|
|
265
260
|
├── styles/
|
|
266
261
|
│ └── index.css # Entrada do Tailwind para o build CSS
|
|
267
262
|
└── index.ts # Entrypoint principal da biblioteca
|
|
@@ -269,4 +264,4 @@ src/
|
|
|
269
264
|
|
|
270
265
|
## Licença
|
|
271
266
|
|
|
272
|
-
MIT
|
|
267
|
+
MIT
|
|
@@ -1,139 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import '
|
|
3
|
-
import
|
|
4
|
-
import SayEngine from 'react-say';
|
|
5
|
-
import { useCallback, useState, useMemo, useEffect } from 'react';
|
|
6
|
-
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
7
|
-
|
|
8
|
-
var DEFAULT_SAY_RATE = 1.4;
|
|
9
|
-
var DEFAULT_SAY_VOLUME = 1;
|
|
10
|
-
var DEFAULT_SAY_PITCH = 0.8;
|
|
11
|
-
var DEFAULT_SAY_VIBRATE_DURATION = 500;
|
|
12
|
-
var DEFAULT_SAY_VOICE = "Google portugu\xEAs do Brasil";
|
|
13
|
-
var SPEECH_APIS = ["speechSynthesis", "SpeechSynthesisUtterance"];
|
|
14
|
-
function hasSpeechSupport() {
|
|
15
|
-
return SPEECH_APIS.every((api) => api in globalThis);
|
|
16
|
-
}
|
|
17
|
-
function voicesAreEqual(current, next) {
|
|
18
|
-
if (current.length !== next.length) return false;
|
|
19
|
-
return current.every(
|
|
20
|
-
(v, i) => {
|
|
21
|
-
var _a, _b;
|
|
22
|
-
return v.name === ((_a = next[i]) == null ? void 0 : _a.name) && v.lang === ((_b = next[i]) == null ? void 0 : _b.lang);
|
|
23
|
-
}
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
function getSpeechSupport() {
|
|
27
|
-
if (!hasSpeechSupport()) return null;
|
|
28
|
-
return {
|
|
29
|
-
speechSynthesis: globalThis.speechSynthesis,
|
|
30
|
-
SpeechSynthesisUtterance: globalThis.SpeechSynthesisUtterance
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
function defaultShouldVibrate(type) {
|
|
34
|
-
return type === "warning";
|
|
35
|
-
}
|
|
36
|
-
function showSayNotify(text, { type = "success", autoClose = 4500 }) {
|
|
37
|
-
toast(text, { type, autoClose });
|
|
38
|
-
}
|
|
39
|
-
function useSpeechPonyfill() {
|
|
40
|
-
const ponyfill = useMemo(() => getSpeechSupport(), []);
|
|
41
|
-
const [voices, setVoices] = useState([]);
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
if (!hasSpeechSupport()) return;
|
|
44
|
-
const synthesis = globalThis.speechSynthesis;
|
|
45
|
-
const updateVoices = () => {
|
|
46
|
-
setVoices((current) => {
|
|
47
|
-
const next = synthesis.getVoices();
|
|
48
|
-
return voicesAreEqual(current, next) ? current : next;
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
synthesis.onvoiceschanged = updateVoices;
|
|
52
|
-
updateVoices();
|
|
53
|
-
return () => {
|
|
54
|
-
synthesis.onvoiceschanged = null;
|
|
55
|
-
};
|
|
56
|
-
}, []);
|
|
57
|
-
return { voices, ponyfill };
|
|
58
|
-
}
|
|
59
|
-
function Say({
|
|
60
|
-
text,
|
|
61
|
-
onEnd,
|
|
62
|
-
onStart,
|
|
63
|
-
isSpeaking,
|
|
64
|
-
setIsSpeaking,
|
|
65
|
-
rate = DEFAULT_SAY_RATE,
|
|
66
|
-
voice = DEFAULT_SAY_VOICE,
|
|
67
|
-
pitch = DEFAULT_SAY_PITCH,
|
|
68
|
-
volume = DEFAULT_SAY_VOLUME
|
|
69
|
-
}) {
|
|
70
|
-
const { voices, ponyfill } = useSpeechPonyfill();
|
|
71
|
-
const canSpeak = isSpeaking && voices.length > 0 && ponyfill;
|
|
72
|
-
const handleEnd = useCallback(() => {
|
|
73
|
-
setIsSpeaking(false);
|
|
74
|
-
onEnd == null ? void 0 : onEnd();
|
|
75
|
-
}, [setIsSpeaking, onEnd]);
|
|
76
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
77
|
-
/* @__PURE__ */ jsx(
|
|
78
|
-
ToastContainer,
|
|
79
|
-
{
|
|
80
|
-
limit: 3,
|
|
81
|
-
draggable: true,
|
|
82
|
-
newestOnTop: true,
|
|
83
|
-
pauseOnHover: true,
|
|
84
|
-
closeOnClick: true,
|
|
85
|
-
autoClose: 4500,
|
|
86
|
-
pauseOnFocusLoss: true,
|
|
87
|
-
closeButton: false,
|
|
88
|
-
position: "top-right",
|
|
89
|
-
style: { fontSize: "14px" }
|
|
90
|
-
}
|
|
91
|
-
),
|
|
92
|
-
canSpeak && /* @__PURE__ */ jsx(
|
|
93
|
-
SayEngine,
|
|
94
|
-
{
|
|
95
|
-
text,
|
|
96
|
-
rate,
|
|
97
|
-
pitch,
|
|
98
|
-
volume,
|
|
99
|
-
onEnd: handleEnd,
|
|
100
|
-
onStart,
|
|
101
|
-
ponyfill,
|
|
102
|
-
voice: voices.find((v) => v.name === voice)
|
|
103
|
-
}
|
|
104
|
-
)
|
|
105
|
-
] });
|
|
106
|
-
}
|
|
107
|
-
var say_default = Say;
|
|
108
|
-
function useSay({
|
|
109
|
-
notifyAutoClose = 4500,
|
|
110
|
-
vibrateDuration = DEFAULT_SAY_VIBRATE_DURATION,
|
|
111
|
-
shouldVibrate = defaultShouldVibrate
|
|
112
|
-
} = {}) {
|
|
113
|
-
const [isSpeaking, setIsSpeaking] = useState(false);
|
|
114
|
-
const [textSpeaking, setTextSpeaking] = useState("");
|
|
115
|
-
const handleSay = useCallback(
|
|
116
|
-
(text, options) => {
|
|
117
|
-
const notify = nvl(options.notify, true);
|
|
118
|
-
const vibrate = nvl(options.vibrate, true);
|
|
119
|
-
const { type } = options;
|
|
120
|
-
setIsSpeaking(true);
|
|
121
|
-
setTextSpeaking(text);
|
|
122
|
-
if (notify) {
|
|
123
|
-
showSayNotify(text, {
|
|
124
|
-
type,
|
|
125
|
-
autoClose: nvl(options.autoClose, notifyAutoClose)
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
if (vibrate && shouldVibrate(type) && navigator.vibrate) {
|
|
129
|
-
navigator.vibrate(vibrateDuration);
|
|
130
|
-
}
|
|
131
|
-
},
|
|
132
|
-
[shouldVibrate, vibrateDuration, notifyAutoClose]
|
|
133
|
-
);
|
|
134
|
-
return { handleSay, isSpeaking, textSpeaking, setIsSpeaking };
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export { say_default as Say, useSay };
|
|
1
|
+
export { say_default as Say, useSay } from '../chunk-4AYAPBGW.mjs';
|
|
2
|
+
import '../chunk-DM64WOVD.mjs';
|
|
3
|
+
import '../chunk-YOSPWY5K.mjs';
|
|
138
4
|
//# sourceMappingURL=index.mjs.map
|
|
139
5
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/accessibility/say/utils/constants.ts","../../src/components/accessibility/say/use-speech-ponyfill.ts","../../src/components/accessibility/say/index.tsx","../../src/components/accessibility/say/use-say.ts"],"names":["useState","useCallback"],"mappings":"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","file":"index.mjs","sourcesContent":["import type {\r\n SayFeedbackType,\r\n SayNotifyOptions,\r\n SpeechPonyfill,\r\n} from \"./interface\";\r\nimport { toast } from \"react-toastify\";\r\n\r\nexport const DEFAULT_SAY_RATE = 1.4;\r\nexport const DEFAULT_SAY_VOLUME = 1;\r\nexport const DEFAULT_SAY_PITCH = 0.8;\r\nexport const DEFAULT_SAY_VIBRATE_DURATION = 500;\r\nexport const DEFAULT_SAY_VOICE = \"Google português do Brasil\";\r\nexport const SPEECH_APIS = [\"speechSynthesis\", \"SpeechSynthesisUtterance\"];\r\n\r\nexport function hasSpeechSupport(): boolean {\r\n return SPEECH_APIS.every((api) => api in globalThis);\r\n}\r\n\r\nexport function voicesAreEqual(\r\n current: SpeechSynthesisVoice[],\r\n next: SpeechSynthesisVoice[],\r\n): boolean {\r\n if (current.length !== next.length) return false;\r\n return current.every(\r\n (v, i) => v.name === next[i]?.name && v.lang === next[i]?.lang,\r\n );\r\n}\r\n\r\nexport function getSpeechSupport(): SpeechPonyfill | null {\r\n if (!hasSpeechSupport()) return null;\r\n return {\r\n speechSynthesis: globalThis.speechSynthesis,\r\n SpeechSynthesisUtterance: globalThis.SpeechSynthesisUtterance,\r\n };\r\n}\r\n\r\nexport function defaultShouldVibrate(type: SayFeedbackType): boolean {\r\n return type === \"warning\";\r\n}\r\n\r\n/** Exibe toast integrado do {@link Say}. */\r\nexport function showSayNotify(\r\n text: string,\r\n { type = \"success\", autoClose = 4500 }: SayNotifyOptions,\r\n): void {\r\n toast(text, { type, autoClose });\r\n}\r\n\r\nconst sayConstants = `\r\nSintetiza texto em fala via Web Speech API (\\`react-say\\`), com toast integrado (\\`react-toastify\\`) e vibração.\r\n\r\n**Importação:**\r\n\\`\\`\\`tsx\r\nimport { Say, useSay } from \"@grazziotin/react-components-next/accessibility\";\r\n\\`\\`\\`\r\n\r\n**Uso básico:**\r\n\\`\\`\\`tsx\r\nconst { handleSay, isSpeaking, textSpeaking, setIsSpeaking } = useSay();\r\n\r\n<>\r\n <Say\r\n isSpeaking={isSpeaking}\r\n text={textSpeaking}\r\n setIsSpeaking={setIsSpeaking}\r\n />\r\n <button type=\"button\" onClick={() => handleSay(\"Operação concluída\", { type: \"success\" })}>\r\n Falar\r\n </button>\r\n</>\r\nonSuccess: (r) => handleSay(r.status, { type: \"success\" })\r\n\\`\\`\\`\r\n\r\nMonte \\`<Say />\\` uma vez no layout. Toast e CSS já vêm embutidos.\r\nUse \\`notify: false\\` para falar sem toast: \\`handleSay(texto, { type: \"default\", notify: false })\\`.\r\n`;\r\nexport default sayConstants;\r\n","import {\r\n voicesAreEqual,\r\n getSpeechSupport,\r\n hasSpeechSupport,\r\n} from \"./utils/constants\";\r\n\r\nimport { useEffect, useMemo, useState } from \"react\";\r\n\r\nexport function useSpeechPonyfill() {\r\n const ponyfill = useMemo(() => getSpeechSupport(), []);\r\n const [voices, setVoices] = useState<SpeechSynthesisVoice[]>([]);\r\n\r\n useEffect(() => {\r\n if (!hasSpeechSupport()) return;\r\n const synthesis = globalThis.speechSynthesis;\r\n\r\n const updateVoices = () => {\r\n setVoices((current) => {\r\n const next = synthesis.getVoices();\r\n return voicesAreEqual(current, next) ? current : next;\r\n });\r\n };\r\n\r\n synthesis.onvoiceschanged = updateVoices;\r\n updateVoices();\r\n\r\n return () => {\r\n synthesis.onvoiceschanged = null;\r\n };\r\n }, []);\r\n\r\n return { voices, ponyfill };\r\n}\r\n","\"use client\";\r\nimport \"react-toastify/dist/ReactToastify.css\";\r\n\r\nimport {\r\n DEFAULT_SAY_PITCH,\r\n DEFAULT_SAY_RATE,\r\n DEFAULT_SAY_VOICE,\r\n DEFAULT_SAY_VOLUME,\r\n} from \"./utils/constants\";\r\nimport SayEngine from \"react-say\";\r\nimport React, { useCallback } from \"react\";\r\nimport { ToastContainer } from \"react-toastify\";\r\nimport type { SayProps } from \"./utils/interface\";\r\nimport { useSpeechPonyfill } from \"./use-speech-ponyfill\";\r\n\r\n/**\r\n * Sintetiza texto em fala via Web Speech API (`react-say`).\r\n * Inclui toast integrado para notificações do {@link useSay}.\r\n *\r\n * @example\r\n * ```tsx\r\n * const { handleSay, isSpeaking, textSpeaking, setIsSpeaking } = useSay();\r\n *\r\n * return (\r\n * <>\r\n * <Say\r\n * isSpeaking={isSpeaking}\r\n * text={textSpeaking}\r\n * setIsSpeaking={setIsSpeaking}\r\n * />\r\n * <button type=\"button\" onClick={() => handleSay(\"Pronto\", { type: \"success\" })}>\r\n * Falar\r\n * </button>\r\n * </>\r\n * );\r\n * ```\r\n */\r\nfunction Say({\r\n text,\r\n onEnd,\r\n onStart,\r\n isSpeaking,\r\n setIsSpeaking,\r\n rate = DEFAULT_SAY_RATE,\r\n voice = DEFAULT_SAY_VOICE,\r\n pitch = DEFAULT_SAY_PITCH,\r\n volume = DEFAULT_SAY_VOLUME,\r\n}: Readonly<SayProps>): React.ReactElement {\r\n const { voices, ponyfill } = useSpeechPonyfill();\r\n const canSpeak = isSpeaking && voices.length > 0 && ponyfill;\r\n\r\n const handleEnd = useCallback(() => {\r\n setIsSpeaking(false);\r\n onEnd?.();\r\n }, [setIsSpeaking, onEnd]);\r\n\r\n return (\r\n <>\r\n <ToastContainer\r\n limit={3}\r\n draggable\r\n newestOnTop\r\n pauseOnHover\r\n closeOnClick\r\n autoClose={4500}\r\n pauseOnFocusLoss\r\n closeButton={false}\r\n position=\"top-right\"\r\n style={{ fontSize: \"14px\" }}\r\n />\r\n {canSpeak && (\r\n <SayEngine\r\n text={text}\r\n rate={rate}\r\n pitch={pitch}\r\n volume={volume}\r\n onEnd={handleEnd}\r\n onStart={onStart}\r\n ponyfill={ponyfill}\r\n voice={voices.find((v) => v.name === voice)}\r\n />\r\n )}\r\n </>\r\n );\r\n}\r\nexport default Say;\r\n","import {\r\n showSayNotify,\r\n defaultShouldVibrate,\r\n DEFAULT_SAY_VIBRATE_DURATION,\r\n} from \"./utils/constants\";\r\nimport type {\r\n SayCallOptions,\r\n UseSayReturn,\r\n UseSayOptions,\r\n} from \"./utils/interface\";\r\nimport { nvl } from \"@/functions\";\r\nimport { useCallback, useState } from \"react\";\r\n\r\n/**\r\n * Hook para disparar fala, toast integrado e vibração.\r\n *\r\n * @example\r\n * ```tsx\r\n * const { handleSay, isSpeaking, textSpeaking, setIsSpeaking } = useSay();\r\n *\r\n * <Say\r\n * isSpeaking={isSpeaking}\r\n * text={textSpeaking}\r\n * setIsSpeaking={setIsSpeaking}\r\n * />\r\n *\r\n * handleSay(\"Operação concluída\", { type: \"success\" });\r\n * handleSay(\"Atenção\", { type: \"warning\" });\r\n * handleSay(\"Apenas fala\", { type: \"default\", notify: false });\r\n * ```\r\n */\r\nexport function useSay({\r\n notifyAutoClose = 4500,\r\n vibrateDuration = DEFAULT_SAY_VIBRATE_DURATION,\r\n shouldVibrate = defaultShouldVibrate,\r\n}: UseSayOptions = {}): UseSayReturn {\r\n const [isSpeaking, setIsSpeaking] = useState(false);\r\n const [textSpeaking, setTextSpeaking] = useState(\"\");\r\n\r\n const handleSay = useCallback(\r\n (text: string, options: SayCallOptions) => {\r\n const notify = nvl(options.notify, true);\r\n const vibrate = nvl(options.vibrate, true);\r\n const { type } = options;\r\n\r\n setIsSpeaking(true);\r\n setTextSpeaking(text);\r\n\r\n if (notify) {\r\n showSayNotify(text, {\r\n type,\r\n autoClose: nvl(options.autoClose, notifyAutoClose),\r\n });\r\n }\r\n\r\n if (vibrate && shouldVibrate(type) && navigator.vibrate) {\r\n navigator.vibrate(vibrateDuration);\r\n }\r\n },\r\n [shouldVibrate, vibrateDuration, notifyAutoClose],\r\n );\r\n\r\n return { handleSay, isSpeaking, textSpeaking, setIsSpeaking };\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { nvl } from './chunk-DM64WOVD.mjs';
|
|
2
|
+
import 'react-toastify/dist/ReactToastify.css';
|
|
3
|
+
import { ToastContainer, toast } from 'react-toastify';
|
|
4
|
+
import SayEngine from 'react-say';
|
|
5
|
+
import { useCallback, useState, useMemo, useEffect } from 'react';
|
|
6
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
var DEFAULT_SAY_RATE = 1.4;
|
|
9
|
+
var DEFAULT_SAY_VOLUME = 1;
|
|
10
|
+
var DEFAULT_SAY_PITCH = 0.8;
|
|
11
|
+
var DEFAULT_SAY_VIBRATE_DURATION = 500;
|
|
12
|
+
var DEFAULT_SAY_VOICE = "Google portugu\xEAs do Brasil";
|
|
13
|
+
var SPEECH_APIS = ["speechSynthesis", "SpeechSynthesisUtterance"];
|
|
14
|
+
function hasSpeechSupport() {
|
|
15
|
+
return SPEECH_APIS.every((api) => api in globalThis);
|
|
16
|
+
}
|
|
17
|
+
function voicesAreEqual(current, next) {
|
|
18
|
+
if (current.length !== next.length) return false;
|
|
19
|
+
return current.every(
|
|
20
|
+
(v, i) => {
|
|
21
|
+
var _a, _b;
|
|
22
|
+
return v.name === ((_a = next[i]) == null ? void 0 : _a.name) && v.lang === ((_b = next[i]) == null ? void 0 : _b.lang);
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
function getSpeechSupport() {
|
|
27
|
+
if (!hasSpeechSupport()) return null;
|
|
28
|
+
return {
|
|
29
|
+
speechSynthesis: globalThis.speechSynthesis,
|
|
30
|
+
SpeechSynthesisUtterance: globalThis.SpeechSynthesisUtterance
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function defaultShouldVibrate(type) {
|
|
34
|
+
return type === "warning";
|
|
35
|
+
}
|
|
36
|
+
function showSayNotify(text, { type = "success", autoClose = 4500 }) {
|
|
37
|
+
toast(text, { type, autoClose });
|
|
38
|
+
}
|
|
39
|
+
function useSpeechPonyfill() {
|
|
40
|
+
const ponyfill = useMemo(() => getSpeechSupport(), []);
|
|
41
|
+
const [voices, setVoices] = useState([]);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!hasSpeechSupport()) return;
|
|
44
|
+
const synthesis = globalThis.speechSynthesis;
|
|
45
|
+
const updateVoices = () => {
|
|
46
|
+
setVoices((current) => {
|
|
47
|
+
const next = synthesis.getVoices();
|
|
48
|
+
return voicesAreEqual(current, next) ? current : next;
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
synthesis.onvoiceschanged = updateVoices;
|
|
52
|
+
updateVoices();
|
|
53
|
+
return () => {
|
|
54
|
+
synthesis.onvoiceschanged = null;
|
|
55
|
+
};
|
|
56
|
+
}, []);
|
|
57
|
+
return { voices, ponyfill };
|
|
58
|
+
}
|
|
59
|
+
function Say({
|
|
60
|
+
text,
|
|
61
|
+
onEnd,
|
|
62
|
+
onStart,
|
|
63
|
+
isSpeaking,
|
|
64
|
+
setIsSpeaking,
|
|
65
|
+
rate = DEFAULT_SAY_RATE,
|
|
66
|
+
voice = DEFAULT_SAY_VOICE,
|
|
67
|
+
pitch = DEFAULT_SAY_PITCH,
|
|
68
|
+
volume = DEFAULT_SAY_VOLUME
|
|
69
|
+
}) {
|
|
70
|
+
const { voices, ponyfill } = useSpeechPonyfill();
|
|
71
|
+
const canSpeak = isSpeaking && voices.length > 0 && ponyfill;
|
|
72
|
+
const handleEnd = useCallback(() => {
|
|
73
|
+
setIsSpeaking(false);
|
|
74
|
+
onEnd == null ? void 0 : onEnd();
|
|
75
|
+
}, [setIsSpeaking, onEnd]);
|
|
76
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
77
|
+
/* @__PURE__ */ jsx(
|
|
78
|
+
ToastContainer,
|
|
79
|
+
{
|
|
80
|
+
limit: 3,
|
|
81
|
+
draggable: true,
|
|
82
|
+
newestOnTop: true,
|
|
83
|
+
pauseOnHover: true,
|
|
84
|
+
closeOnClick: true,
|
|
85
|
+
autoClose: 4500,
|
|
86
|
+
pauseOnFocusLoss: true,
|
|
87
|
+
closeButton: false,
|
|
88
|
+
position: "top-right",
|
|
89
|
+
style: { fontSize: "14px" }
|
|
90
|
+
}
|
|
91
|
+
),
|
|
92
|
+
canSpeak && /* @__PURE__ */ jsx(
|
|
93
|
+
SayEngine,
|
|
94
|
+
{
|
|
95
|
+
text,
|
|
96
|
+
rate,
|
|
97
|
+
pitch,
|
|
98
|
+
volume,
|
|
99
|
+
onEnd: handleEnd,
|
|
100
|
+
onStart,
|
|
101
|
+
ponyfill,
|
|
102
|
+
voice: voices.find((v) => v.name === voice)
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
] });
|
|
106
|
+
}
|
|
107
|
+
var say_default = Say;
|
|
108
|
+
function useSay({
|
|
109
|
+
notifyAutoClose = 4500,
|
|
110
|
+
vibrateDuration = DEFAULT_SAY_VIBRATE_DURATION,
|
|
111
|
+
shouldVibrate = defaultShouldVibrate
|
|
112
|
+
} = {}) {
|
|
113
|
+
const [isSpeaking, setIsSpeaking] = useState(false);
|
|
114
|
+
const [textSpeaking, setTextSpeaking] = useState("");
|
|
115
|
+
const handleSay = useCallback(
|
|
116
|
+
(text, options) => {
|
|
117
|
+
const notify = nvl(options.notify, true);
|
|
118
|
+
const vibrate = nvl(options.vibrate, true);
|
|
119
|
+
const { type } = options;
|
|
120
|
+
setIsSpeaking(true);
|
|
121
|
+
setTextSpeaking(text);
|
|
122
|
+
if (notify) {
|
|
123
|
+
showSayNotify(text, {
|
|
124
|
+
type,
|
|
125
|
+
autoClose: nvl(options.autoClose, notifyAutoClose)
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
if (vibrate && shouldVibrate(type) && navigator.vibrate) {
|
|
129
|
+
navigator.vibrate(vibrateDuration);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
[shouldVibrate, vibrateDuration, notifyAutoClose]
|
|
133
|
+
);
|
|
134
|
+
return { handleSay, isSpeaking, textSpeaking, setIsSpeaking };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export { say_default, useSay };
|
|
138
|
+
//# sourceMappingURL=chunk-4AYAPBGW.mjs.map
|
|
139
|
+
//# sourceMappingURL=chunk-4AYAPBGW.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/accessibility/say/utils/constants.ts","../src/components/accessibility/say/use-speech-ponyfill.ts","../src/components/accessibility/say/index.tsx","../src/components/accessibility/say/use-say.ts"],"names":["useState","useCallback"],"mappings":"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","file":"chunk-4AYAPBGW.mjs","sourcesContent":["import type {\r\n SayFeedbackType,\r\n SayNotifyOptions,\r\n SpeechPonyfill,\r\n} from \"./interface\";\r\nimport { toast } from \"react-toastify\";\r\n\r\nexport const DEFAULT_SAY_RATE = 1.4;\r\nexport const DEFAULT_SAY_VOLUME = 1;\r\nexport const DEFAULT_SAY_PITCH = 0.8;\r\nexport const DEFAULT_SAY_VIBRATE_DURATION = 500;\r\nexport const DEFAULT_SAY_VOICE = \"Google português do Brasil\";\r\nexport const SPEECH_APIS = [\"speechSynthesis\", \"SpeechSynthesisUtterance\"];\r\n\r\nexport function hasSpeechSupport(): boolean {\r\n return SPEECH_APIS.every((api) => api in globalThis);\r\n}\r\n\r\nexport function voicesAreEqual(\r\n current: SpeechSynthesisVoice[],\r\n next: SpeechSynthesisVoice[],\r\n): boolean {\r\n if (current.length !== next.length) return false;\r\n return current.every(\r\n (v, i) => v.name === next[i]?.name && v.lang === next[i]?.lang,\r\n );\r\n}\r\n\r\nexport function getSpeechSupport(): SpeechPonyfill | null {\r\n if (!hasSpeechSupport()) return null;\r\n return {\r\n speechSynthesis: globalThis.speechSynthesis,\r\n SpeechSynthesisUtterance: globalThis.SpeechSynthesisUtterance,\r\n };\r\n}\r\n\r\nexport function defaultShouldVibrate(type: SayFeedbackType): boolean {\r\n return type === \"warning\";\r\n}\r\n\r\n/** Exibe toast integrado do {@link Say}. */\r\nexport function showSayNotify(\r\n text: string,\r\n { type = \"success\", autoClose = 4500 }: SayNotifyOptions,\r\n): void {\r\n toast(text, { type, autoClose });\r\n}\r\n\r\nconst sayConstants = `\r\nSintetiza texto em fala via Web Speech API (\\`react-say\\`), com toast integrado (\\`react-toastify\\`) e vibração.\r\n\r\n**Importação:**\r\n\\`\\`\\`tsx\r\nimport { Say, useSay } from \"@grazziotin/react-components-next/accessibility\";\r\n\\`\\`\\`\r\n\r\n**Uso básico:**\r\n\\`\\`\\`tsx\r\nconst { handleSay, isSpeaking, textSpeaking, setIsSpeaking } = useSay();\r\n\r\n<>\r\n <Say\r\n isSpeaking={isSpeaking}\r\n text={textSpeaking}\r\n setIsSpeaking={setIsSpeaking}\r\n />\r\n <button type=\"button\" onClick={() => handleSay(\"Operação concluída\", { type: \"success\" })}>\r\n Falar\r\n </button>\r\n</>\r\nonSuccess: (r) => handleSay(r.status, { type: \"success\" })\r\n\\`\\`\\`\r\n\r\nMonte \\`<Say />\\` uma vez no layout. Toast e CSS já vêm embutidos.\r\nUse \\`notify: false\\` para falar sem toast: \\`handleSay(texto, { type: \"default\", notify: false })\\`.\r\n`;\r\nexport default sayConstants;\r\n","import {\r\n voicesAreEqual,\r\n getSpeechSupport,\r\n hasSpeechSupport,\r\n} from \"./utils/constants\";\r\n\r\nimport { useEffect, useMemo, useState } from \"react\";\r\n\r\nexport function useSpeechPonyfill() {\r\n const ponyfill = useMemo(() => getSpeechSupport(), []);\r\n const [voices, setVoices] = useState<SpeechSynthesisVoice[]>([]);\r\n\r\n useEffect(() => {\r\n if (!hasSpeechSupport()) return;\r\n const synthesis = globalThis.speechSynthesis;\r\n\r\n const updateVoices = () => {\r\n setVoices((current) => {\r\n const next = synthesis.getVoices();\r\n return voicesAreEqual(current, next) ? current : next;\r\n });\r\n };\r\n\r\n synthesis.onvoiceschanged = updateVoices;\r\n updateVoices();\r\n\r\n return () => {\r\n synthesis.onvoiceschanged = null;\r\n };\r\n }, []);\r\n\r\n return { voices, ponyfill };\r\n}\r\n","\"use client\";\r\nimport \"react-toastify/dist/ReactToastify.css\";\r\n\r\nimport {\r\n DEFAULT_SAY_PITCH,\r\n DEFAULT_SAY_RATE,\r\n DEFAULT_SAY_VOICE,\r\n DEFAULT_SAY_VOLUME,\r\n} from \"./utils/constants\";\r\nimport SayEngine from \"react-say\";\r\nimport React, { useCallback } from \"react\";\r\nimport { ToastContainer } from \"react-toastify\";\r\nimport type { SayProps } from \"./utils/interface\";\r\nimport { useSpeechPonyfill } from \"./use-speech-ponyfill\";\r\n\r\n/**\r\n * Sintetiza texto em fala via Web Speech API (`react-say`).\r\n * Inclui toast integrado para notificações do {@link useSay}.\r\n *\r\n * @example\r\n * ```tsx\r\n * const { handleSay, isSpeaking, textSpeaking, setIsSpeaking } = useSay();\r\n *\r\n * return (\r\n * <>\r\n * <Say\r\n * isSpeaking={isSpeaking}\r\n * text={textSpeaking}\r\n * setIsSpeaking={setIsSpeaking}\r\n * />\r\n * <button type=\"button\" onClick={() => handleSay(\"Pronto\", { type: \"success\" })}>\r\n * Falar\r\n * </button>\r\n * </>\r\n * );\r\n * ```\r\n */\r\nfunction Say({\r\n text,\r\n onEnd,\r\n onStart,\r\n isSpeaking,\r\n setIsSpeaking,\r\n rate = DEFAULT_SAY_RATE,\r\n voice = DEFAULT_SAY_VOICE,\r\n pitch = DEFAULT_SAY_PITCH,\r\n volume = DEFAULT_SAY_VOLUME,\r\n}: Readonly<SayProps>): React.ReactElement {\r\n const { voices, ponyfill } = useSpeechPonyfill();\r\n const canSpeak = isSpeaking && voices.length > 0 && ponyfill;\r\n\r\n const handleEnd = useCallback(() => {\r\n setIsSpeaking(false);\r\n onEnd?.();\r\n }, [setIsSpeaking, onEnd]);\r\n\r\n return (\r\n <>\r\n <ToastContainer\r\n limit={3}\r\n draggable\r\n newestOnTop\r\n pauseOnHover\r\n closeOnClick\r\n autoClose={4500}\r\n pauseOnFocusLoss\r\n closeButton={false}\r\n position=\"top-right\"\r\n style={{ fontSize: \"14px\" }}\r\n />\r\n {canSpeak && (\r\n <SayEngine\r\n text={text}\r\n rate={rate}\r\n pitch={pitch}\r\n volume={volume}\r\n onEnd={handleEnd}\r\n onStart={onStart}\r\n ponyfill={ponyfill}\r\n voice={voices.find((v) => v.name === voice)}\r\n />\r\n )}\r\n </>\r\n );\r\n}\r\nexport default Say;\r\n","import {\r\n showSayNotify,\r\n defaultShouldVibrate,\r\n DEFAULT_SAY_VIBRATE_DURATION,\r\n} from \"./utils/constants\";\r\nimport type {\r\n SayCallOptions,\r\n UseSayReturn,\r\n UseSayOptions,\r\n} from \"./utils/interface\";\r\nimport { nvl } from \"@/functions\";\r\nimport { useCallback, useState } from \"react\";\r\n\r\n/**\r\n * Hook para disparar fala, toast integrado e vibração.\r\n *\r\n * @example\r\n * ```tsx\r\n * const { handleSay, isSpeaking, textSpeaking, setIsSpeaking } = useSay();\r\n *\r\n * <Say\r\n * isSpeaking={isSpeaking}\r\n * text={textSpeaking}\r\n * setIsSpeaking={setIsSpeaking}\r\n * />\r\n *\r\n * handleSay(\"Operação concluída\", { type: \"success\" });\r\n * handleSay(\"Atenção\", { type: \"warning\" });\r\n * handleSay(\"Apenas fala\", { type: \"default\", notify: false });\r\n * ```\r\n */\r\nexport function useSay({\r\n notifyAutoClose = 4500,\r\n vibrateDuration = DEFAULT_SAY_VIBRATE_DURATION,\r\n shouldVibrate = defaultShouldVibrate,\r\n}: UseSayOptions = {}): UseSayReturn {\r\n const [isSpeaking, setIsSpeaking] = useState(false);\r\n const [textSpeaking, setTextSpeaking] = useState(\"\");\r\n\r\n const handleSay = useCallback(\r\n (text: string, options: SayCallOptions) => {\r\n const notify = nvl(options.notify, true);\r\n const vibrate = nvl(options.vibrate, true);\r\n const { type } = options;\r\n\r\n setIsSpeaking(true);\r\n setTextSpeaking(text);\r\n\r\n if (notify) {\r\n showSayNotify(text, {\r\n type,\r\n autoClose: nvl(options.autoClose, notifyAutoClose),\r\n });\r\n }\r\n\r\n if (vibrate && shouldVibrate(type) && navigator.vibrate) {\r\n navigator.vibrate(vibrateDuration);\r\n }\r\n },\r\n [shouldVibrate, vibrateDuration, notifyAutoClose],\r\n );\r\n\r\n return { handleSay, isSpeaking, textSpeaking, setIsSpeaking };\r\n}\r\n"]}
|
|
@@ -1,37 +1,7 @@
|
|
|
1
1
|
import { twMerge } from 'tailwind-merge';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
var __defProps = Object.defineProperties;
|
|
6
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
10
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
11
|
-
var __spreadValues = (a, b) => {
|
|
12
|
-
for (var prop in b || (b = {}))
|
|
13
|
-
if (__hasOwnProp.call(b, prop))
|
|
14
|
-
__defNormalProp(a, prop, b[prop]);
|
|
15
|
-
if (__getOwnPropSymbols)
|
|
16
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
17
|
-
if (__propIsEnum.call(b, prop))
|
|
18
|
-
__defNormalProp(a, prop, b[prop]);
|
|
19
|
-
}
|
|
20
|
-
return a;
|
|
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
|
-
};
|
|
4
|
+
// src/functions/cn/cn.ts
|
|
35
5
|
function cn(...values) {
|
|
36
6
|
return twMerge(clsx(values));
|
|
37
7
|
}
|
|
@@ -113,6 +83,6 @@ function formatItem150(item) {
|
|
|
113
83
|
return digits.replace(/(\d{2})(\d)/, "$1.$2").replace(/(\d{2})(\d)/, "$1.$2").replace(/(\d{2})(\d)/, "$1.$2").replace(/(\d{2})\.(\d)(\d{1,3})$/, "$1.$2.$3");
|
|
114
84
|
}
|
|
115
85
|
|
|
116
|
-
export {
|
|
117
|
-
//# sourceMappingURL=chunk-
|
|
118
|
-
//# sourceMappingURL=chunk-
|
|
86
|
+
export { cn, formatCpfCnpj, formatItem150, formatItem170, formatPhoneBr, formatPriceBrl, nvl, removeDigits, removeNonDigits, removeTextOnly };
|
|
87
|
+
//# sourceMappingURL=chunk-DM64WOVD.mjs.map
|
|
88
|
+
//# sourceMappingURL=chunk-DM64WOVD.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","../src/functions/format-price-brl/format-price-brl.ts","../src/functions/format-item-170/format-item-170.ts","../src/functions/format-item-150/format-item-150.ts"],"names":[],"mappings":"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","file":"chunk-DM64WOVD.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\r\n/** Remove tudo que não for número. */\r\nexport function removeNonDigits(value: string) {\r\n return value.replaceAll(/\\d/g, \"\");\r\n}\r\n\r\n/** Remove tudo que não for letra. */\r\nexport function removeTextOnly(value: string) {\r\n return value.replaceAll(/[^\\p{L}]/gu, \"\");\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","import { removeDigits } from \"../../core/remove-digits\";\r\n\r\n/**\r\n * Formata um valor como moeda brasileira (BRL).\r\n *\r\n * - **string** — máscara de input: remove não dígitos, divide por 100 (centavos)\r\n * - **number** — valor já em reais\r\n *\r\n * @param value - Valor digitado ou numérico em reais\r\n * @returns Valor formatado (ex.: `R$ 1.234,56`) ou string vazia se ausente\r\n * @example\r\n * formatPriceBrl(\"123456\") // \"R$ 1.234,56\" (input)\r\n * formatPriceBrl(1234.56) // \"R$ 1.234,56\" (número)\r\n * formatPriceBrl(0) // \"R$ 0,00\"\r\n */\r\nexport function formatPriceBrl(value?: string | number | null): string {\r\n if (value === undefined || value === null) return \"\";\r\n\r\n if (typeof value === \"string\") {\r\n const digits = removeDigits(value);\r\n if (!digits) return \"\";\r\n const price = Number(digits) / 100;\r\n if (Number.isNaN(price)) return \"\";\r\n return price.toLocaleString(\"pt-BR\", {\r\n style: \"currency\",\r\n currency: \"BRL\",\r\n });\r\n }\r\n\r\n if (Number.isNaN(value)) return \"\";\r\n return value.toLocaleString(\"pt-BR\", { style: \"currency\", currency: \"BRL\" });\r\n}\r\n","import { removeDigits } from \"../../core/remove-digits\";\r\n\r\n/**\r\n * Formata máscara de item 170 (até 12 dígitos) no padrão `00.00.00.00.0.000`.\r\n * Remove caracteres não numéricos antes de formatar.\r\n * @param item - Valor com ou sem formatação\r\n * @returns Item formatado ou string vazia se ausente\r\n * @example\r\n * formatItem170(\"123456789012\") // \"12.34.56.78.9.012\"\r\n */\r\nexport function formatItem170(item?: string): string {\r\n if (!item) return \"\";\r\n const digits = removeDigits(item).slice(0, 12);\r\n if (!digits) return \"\";\r\n\r\n return digits\r\n .replace(/(\\d{2})(\\d)/, \"$1.$2\")\r\n .replace(/(\\d{2})(\\d)/, \"$1.$2\")\r\n .replace(/(\\d{2})(\\d)/, \"$1.$2\")\r\n .replace(/(\\d{2})(\\d)/, \"$1.$2\")\r\n .replace(/(\\d{2})\\.(\\d)(\\d{1,3})$/, \"$1.$2.$3\");\r\n}\r\n","import { removeDigits } from \"../../core/remove-digits\";\r\n\r\n/**\r\n * Formata máscara de item 150 (até 10 dígitos) no padrão `00.00.00.0.000`.\r\n * Remove caracteres não numéricos antes de formatar.\r\n * @param item - Valor com ou sem formatação\r\n * @returns Item formatado ou string vazia se ausente\r\n * @example\r\n * formatItem150(\"1234567890\") // \"12.34.56.7.890\"\r\n */\r\nexport function formatItem150(item?: string): string {\r\n if (!item) return \"\";\r\n const digits = removeDigits(item).slice(0, 10);\r\n if (!digits) return \"\";\r\n\r\n return digits\r\n .replace(/(\\d{2})(\\d)/, \"$1.$2\")\r\n .replace(/(\\d{2})(\\d)/, \"$1.$2\")\r\n .replace(/(\\d{2})(\\d)/, \"$1.$2\")\r\n .replace(/(\\d{2})\\.(\\d)(\\d{1,3})$/, \"$1.$2.$3\");\r\n}\r\n"]}
|