@grazziotin/react-components-next 2.2.1 → 3.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 +60 -104
- package/dist/accessibility/index.mjs +3 -137
- package/dist/accessibility/index.mjs.map +1 -1
- package/dist/chunk-2ZJJRHPT.mjs +21 -0
- package/dist/chunk-2ZJJRHPT.mjs.map +1 -0
- 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-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 +1244 -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 +10 -0
- package/dist/providers/index.d.ts +10 -0
- package/dist/providers/index.js +23 -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 +33 -14
- package/dist/chunk-BWW3F4R4.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -8,35 +8,38 @@ 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.
|
|
20
27
|
|
|
21
|
-
|
|
22
|
-
import "@grazziotin/react-components-next/styles";
|
|
28
|
+
Carregue também a fonte **Poppins** e os estilos do Mantine:
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
import { MantineProvider } from "@mantine/core";
|
|
30
|
+
```tsx
|
|
26
31
|
import "@mantine/core/styles.css";
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
});
|
|
33
|
+
import { GrazziotinProviders } from "@grazziotin/react-components-next/providers";
|
|
34
|
+
```
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
36
|
+
No HTML ou CSS global do projeto consumidor:
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<link
|
|
40
|
+
rel="stylesheet"
|
|
41
|
+
href="https://fonts.googleapis.com/css2?family=Poppins:wght@100;200;300;400;500;600;700;800;900&display=swap"
|
|
42
|
+
/>
|
|
40
43
|
```
|
|
41
44
|
|
|
42
45
|
```css
|
|
@@ -46,39 +49,51 @@ export function AppProviders({ children }: { children: React.ReactNode }) {
|
|
|
46
49
|
}
|
|
47
50
|
```
|
|
48
51
|
|
|
49
|
-
|
|
52
|
+
```tsx
|
|
53
|
+
export function AppProviders({ children }: { children: React.ReactNode }) {
|
|
54
|
+
return <GrazziotinProviders>{children}</GrazziotinProviders>;
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
> **Atenção:** a biblioteca referencia `Poppins` via variáveis CSS, mas **não embute o arquivo da fonte** — o projeto consumidor precisa carregá-la. Os estilos do Mantine (`@mantine/core/styles.css`) também são obrigatórios.
|
|
50
59
|
|
|
51
60
|
## Componentes disponíveis
|
|
52
61
|
|
|
62
|
+
| Componente | Descrição |
|
|
63
|
+
| -------------- | --------------------------------------------------------------- |
|
|
64
|
+
| `Card` | Container com cabeçalho colorido, título, ícone e tooltip |
|
|
65
|
+
| `Dialog` | Modal baseado no MUI com título, conteúdo e ações opcionais |
|
|
66
|
+
| `DataTable` | Tabela de dados com MUI DataGrid, filtros e textos em português |
|
|
67
|
+
| `Tab`/`Tabs` | Abas estilizadas com indicador e tipografia customizáveis |
|
|
68
|
+
| `Input` | Campo de texto com máscaras e estilização MUI |
|
|
69
|
+
| `InputSelect` | Select com grid de opções |
|
|
70
|
+
| `Filter` | Drawer de filtros com campos configuráveis |
|
|
53
71
|
|
|
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 |
|
|
72
|
+
## Acessibilidade
|
|
60
73
|
|
|
74
|
+
| Export | Descrição |
|
|
75
|
+
| --------- | -------------------------------------- |
|
|
76
|
+
| `Say` | Componente de leitura de tela (toast) |
|
|
77
|
+
| `useSay` | Hook para disparar feedback por voz |
|
|
61
78
|
|
|
62
79
|
## Funções utilitárias
|
|
63
80
|
|
|
64
|
-
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
|
|
81
|
+
| Função | Descrição |
|
|
82
|
+
| ---------------- | ------------------------------------------------ |
|
|
83
|
+
| `cn` | Mescla classes CSS com `clsx` e `tailwind-merge` |
|
|
84
|
+
| `nvl` | Retorna valor padrão quando `null`/`undefined` |
|
|
85
|
+
| `formatCpfCnpj` | Formata CPF ou CNPJ |
|
|
86
|
+
| `formatPhoneBr` | Formata telefone brasileiro |
|
|
87
|
+
| `formatPriceBrl` | Formata valor monetário em BRL |
|
|
88
|
+
| `formatItem170` | Formata item 170 |
|
|
89
|
+
| `formatItem150` | Formata item 150 |
|
|
72
90
|
|
|
73
91
|
## Uso
|
|
74
92
|
|
|
75
93
|
```tsx
|
|
76
94
|
import {
|
|
77
95
|
Card,
|
|
78
|
-
Dialog,
|
|
79
96
|
DataTable,
|
|
80
|
-
Tab,
|
|
81
|
-
Tabs,
|
|
82
97
|
cn,
|
|
83
98
|
formatCpfCnpj,
|
|
84
99
|
} from "@grazziotin/react-components-next";
|
|
@@ -107,14 +122,14 @@ export function Example() {
|
|
|
107
122
|
|
|
108
123
|
A biblioteca expõe múltiplos pontos de entrada:
|
|
109
124
|
|
|
110
|
-
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
| `@grazziotin/react-components-next`
|
|
114
|
-
| `@grazziotin/react-components-next/
|
|
115
|
-
| `@grazziotin/react-components-next/
|
|
116
|
-
| `@grazziotin/react-components-next/
|
|
117
|
-
|
|
125
|
+
| Import | Conteúdo |
|
|
126
|
+
| ----------------------------------------------- | --------------------------------------------- |
|
|
127
|
+
| `@grazziotin/react-components-next` | Componentes, funções, acessibilidade e providers |
|
|
128
|
+
| `@grazziotin/react-components-next/ui` | Apenas componentes de UI |
|
|
129
|
+
| `@grazziotin/react-components-next/functions` | Apenas funções utilitárias |
|
|
130
|
+
| `@grazziotin/react-components-next/accessibility` | Componentes de acessibilidade (`Say`, `useSay`) |
|
|
131
|
+
| `@grazziotin/react-components-next/providers` | `GrazziotinProviders` |
|
|
132
|
+
| `@grazziotin/react-components-next/styles` | CSS compilado da biblioteca (opcional — já incluído ao importar `/ui` ou `.`) |
|
|
118
133
|
|
|
119
134
|
## Componentes
|
|
120
135
|
|
|
@@ -208,65 +223,6 @@ formatPhoneBr("11987654321"); // "(11) 98765-4321"
|
|
|
208
223
|
formatPhoneBr("1133334444"); // "(11) 3333-4444"
|
|
209
224
|
```
|
|
210
225
|
|
|
211
|
-
## Desenvolvimento
|
|
212
|
-
|
|
213
|
-
```bash
|
|
214
|
-
# Instalar dependências
|
|
215
|
-
npm install
|
|
216
|
-
|
|
217
|
-
# Storybook (visualização e documentação dos componentes)
|
|
218
|
-
npm run storybook
|
|
219
|
-
|
|
220
|
-
# Build estático do Storybook
|
|
221
|
-
npm run build-storybook
|
|
222
|
-
|
|
223
|
-
# Build da biblioteca para npm
|
|
224
|
-
npm run build:lib
|
|
225
|
-
|
|
226
|
-
# Verificar tipos TypeScript
|
|
227
|
-
npm run type-check
|
|
228
|
-
|
|
229
|
-
# Lint
|
|
230
|
-
npm run lint
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
## Publicar no npm
|
|
234
|
-
|
|
235
|
-
```bash
|
|
236
|
-
# Fazer login no npm
|
|
237
|
-
npm login
|
|
238
|
-
|
|
239
|
-
# Publicar (executa build:lib automaticamente via prepublishOnly)
|
|
240
|
-
npm publish
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
## Estrutura do projeto
|
|
244
|
-
|
|
245
|
-
```
|
|
246
|
-
src/
|
|
247
|
-
├── app/ # Next.js App Router (página inicial mínima)
|
|
248
|
-
│ ├── globals.css # Variáveis CSS e tema
|
|
249
|
-
│ ├── layout.tsx # Providers MUI + Mantine
|
|
250
|
-
│ └── page.tsx
|
|
251
|
-
├── components/
|
|
252
|
-
│ ├── index.ts
|
|
253
|
-
│ └── ui/
|
|
254
|
-
│ ├── card/
|
|
255
|
-
│ ├── dialog/
|
|
256
|
-
│ ├── data-table/
|
|
257
|
-
│ └── tab/
|
|
258
|
-
├── core/ # Utilitários internos
|
|
259
|
-
├── functions/
|
|
260
|
-
│ ├── cn/
|
|
261
|
-
│ ├── nvl/
|
|
262
|
-
│ ├── format-cpf-cnpj/
|
|
263
|
-
│ └── format-phone-br/
|
|
264
|
-
├── providers/
|
|
265
|
-
├── styles/
|
|
266
|
-
│ └── index.css # Entrada do Tailwind para o build CSS
|
|
267
|
-
└── index.ts # Entrypoint principal da biblioteca
|
|
268
|
-
```
|
|
269
|
-
|
|
270
226
|
## Licença
|
|
271
227
|
|
|
272
|
-
MIT
|
|
228
|
+
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,21 @@
|
|
|
1
|
+
import { createTheme, ThemeProvider, CssBaseline } from '@mui/material';
|
|
2
|
+
import { MantineProvider } from '@mantine/core';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/providers/app-providers.tsx
|
|
6
|
+
var defaultMuiTheme = createTheme({
|
|
7
|
+
typography: { fontFamily: "var(--font-family, inherit)" }
|
|
8
|
+
});
|
|
9
|
+
function GrazziotinProviders({
|
|
10
|
+
children,
|
|
11
|
+
muiTheme = defaultMuiTheme
|
|
12
|
+
}) {
|
|
13
|
+
return /* @__PURE__ */ jsxs(ThemeProvider, { theme: muiTheme, children: [
|
|
14
|
+
/* @__PURE__ */ jsx(CssBaseline, {}),
|
|
15
|
+
/* @__PURE__ */ jsx(MantineProvider, { children })
|
|
16
|
+
] });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { GrazziotinProviders };
|
|
20
|
+
//# sourceMappingURL=chunk-2ZJJRHPT.mjs.map
|
|
21
|
+
//# sourceMappingURL=chunk-2ZJJRHPT.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/providers/app-providers.tsx"],"names":[],"mappings":";;;;;AAeA,IAAM,kBAAkB,WAAA,CAAY;AAAA,EAClC,UAAA,EAAY,EAAE,UAAA,EAAY,6BAAA;AAC5B,CAAC,CAAA;AAEM,SAAS,mBAAA,CAAoB;AAAA,EAClC,QAAA;AAAA,EACA,QAAA,GAAW;AACb,CAAA,EAA6B;AAC3B,EAAA,uBACE,IAAA,CAAC,aAAA,EAAA,EAAc,KAAA,EAAO,QAAA,EACpB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WAAA,EAAA,EAAY,CAAA;AAAA,oBACb,GAAA,CAAC,mBAAiB,QAAA,EAAS;AAAA,GAAA,EAC7B,CAAA;AAEJ","file":"chunk-2ZJJRHPT.mjs","sourcesContent":["\"use client\";\r\n\r\nimport {\r\n CssBaseline,\r\n ThemeProvider,\r\n createTheme,\r\n type Theme,\r\n} from \"@mui/material\";\r\nimport { MantineProvider } from \"@mantine/core\";\r\n\r\ntype GrazziotinProvidersProps = {\r\n readonly children: React.ReactNode;\r\n readonly muiTheme?: Theme;\r\n};\r\n\r\nconst defaultMuiTheme = createTheme({\r\n typography: { fontFamily: \"var(--font-family, inherit)\" },\r\n});\r\n\r\nexport function GrazziotinProviders({\r\n children,\r\n muiTheme = defaultMuiTheme,\r\n}: GrazziotinProvidersProps) {\r\n return (\r\n <ThemeProvider theme={muiTheme}>\r\n <CssBaseline />\r\n <MantineProvider>{children}</MantineProvider>\r\n </ThemeProvider>\r\n );\r\n}\r\n"]}
|
|
@@ -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"]}
|