@synchat/webchat 0.0.13 → 0.0.15

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 CHANGED
@@ -1,77 +1,150 @@
1
- # React + TypeScript Component Library (tsup)
1
+ # @synchat/webchat
2
2
 
3
- Starter para publicar um componente React no npm e consumir em outro projeto.
3
+ Componente de chat para sites, integrado à plataforma **Synchat**. Exibe um botão flutuante que abre um painel com formulário (nome, e-mail, telefone, mensagem) ou mensagem de fora do horário de atendimento, conforme a configuração do canal no portal.
4
4
 
5
- ## Como usar este template
5
+ - **Site Synchat:** [synchat.com.br](https://synchat.com.br)
6
+ - **Portal (cadastro e gestão):** [portal.synchat.com.br](https://portal.synchat.com.br)
6
7
 
7
- 1. **Renomeie o pacote** em `package.json`:
8
- - Para um pacote público com _scope_: `"name": "@seu-escopo/minha-lib"`
9
- - O primeiro publish precisa de `--access public`
10
- - Ou sem scope: `"name": "minha-lib"`
8
+ ---
9
+
10
+ ## Como se cadastrar na plataforma
11
+
12
+ 1. Acesse o **portal**: [https://portal.synchat.com.br](https://portal.synchat.com.br).
13
+ 2. Clique em **Cadastre-se** (ou acesse [https://portal.synchat.com.br/auth/register](https://portal.synchat.com.br/auth/register)).
14
+ 3. Preencha os dados da empresa e do usuário e finalize o cadastro.
15
+ 4. Após o login, você gerencia **canais**, **atendentes** e **conversas** pelo menu do portal.
16
+
17
+ Para mais informações sobre a Synchat, acesse [synchat.com.br](https://synchat.com.br).
18
+
19
+ ---
11
20
 
12
- 2. **Instale dependências**:
13
- ```bash
14
- npm install
15
- ```
21
+ ## Criar um canal WebChat e obter o secret
16
22
 
17
- 3. **Build**:
18
- ```bash
19
- npm run build
20
- ```
23
+ 1. No **portal**, vá em **Canais** (ou **Configurações** → **Canais**).
24
+ 2. Clique em **Novo canal** e escolha **WebChat**.
25
+ 3. Preencha:
26
+ - **Nome** do canal (ex.: "Chat do site")
27
+ - **Descrição** (opcional)
28
+ - **Restringir por dias e horário** (opcional): ative para exibir mensagem de “fora do horário” quando configurado
29
+ - Horários de atendimento (dias úteis e fim de semana), se usar restrição
30
+ - **Quando inativo, enviar para a fila** (opcional)
31
+ 4. Clique em **Criar canal WebChat**.
32
+ 5. Após a criação, o portal exibe o **secret** do canal. **Copie e guarde** esse valor — ele será usado no componente no seu site.
21
33
 
22
- 4. **Publicar no npm**:
23
- - Faça login (`npm login`).
24
- - Se usar scope público: `npm publish --access public`
25
- - Sem scope: `npm publish`
34
+ O **secret** identifica o canal na API e no widget; não o compartilhe publicamente.
26
35
 
27
- > Dica: mantenha `react` e `react-dom` como `peerDependencies` (já configurado).
28
- > Isso evita múltiplas cópias do React no projeto consumidor.
36
+ ---
37
+
38
+ ## Instalação
29
39
 
30
- ## Estrutura
40
+ ```bash
41
+ npm install @synchat/webchat
31
42
  ```
32
- .
33
- ├─ src/
34
- │ ├─ index.tsx
35
- │ └─ index.ts
36
- ├─ package.json
37
- ├─ tsconfig.json
38
- ├─ tsup.config.ts
39
- ├─ .gitignore
40
- └─ .npmignore
43
+
44
+ O pacote usa **React** e **Material UI** como dependências do seu projeto. Se ainda não tiver:
45
+
46
+ ```bash
47
+ npm install react react-dom @mui/material @mui/icons-material @emotion/react @emotion/styled
41
48
  ```
42
49
 
43
- - Edite/adicione componentes em `src/` e reexporte em `src/index.ts`.
50
+ ---
44
51
 
45
- ## Consumindo em outro projeto
52
+ ## Uso básico
46
53
 
47
- ```bash
48
- # em outro app (Vite, Next, CRA, etc.)
49
- npm install minha-lib
50
- # ou
51
- npm install @seu-escopo/minha-lib
54
+ Importe o componente e informe o **secret** (obtido no portal) e a **URL base da API** da Synchat:
55
+
56
+ ```tsx
57
+ import { WebChat } from "@synchat/webchat";
58
+
59
+ function App() {
60
+ return (
61
+ <WebChat
62
+ secret="SEU_SECRET_DO_PORTAL"
63
+ apiBaseUrl="https://api.synchat.com.br"
64
+ />
65
+ );
66
+ }
52
67
  ```
53
68
 
69
+ - **secret:** valor exibido ao criar o canal WebChat no portal.
70
+ - **apiBaseUrl:** URL base da API (ex.: `https://api.synchat.com.br` em produção).
71
+
72
+ O widget exibe um **botão flutuante** no canto inferior direito. Ao clicar:
73
+
74
+ - Se o canal estiver **ativo** e **dentro do horário** (ou sem restrição): mostra o formulário (nome, e-mail, telefone, mensagem) e o botão **Iniciar chat**.
75
+ - Se estiver **fora do horário** (com restrição configurada): mostra a mensagem de horário de atendimento.
76
+ - Se o canal estiver inativo ou o secret for inválido: mostra mensagem de indisponibilidade.
77
+
78
+ ---
79
+
80
+ ## Início da conversa (WebSocket)
81
+
82
+ O **início da conversa** não é feito por API; será feito via **WebSocket**. Por isso, o componente espera que você implemente o callback **onStartChat** e, nele, conecte ao WebSocket da Synchat e envie os dados do visitante.
83
+
84
+ Exemplo de uso com **onStartChat**:
85
+
54
86
  ```tsx
55
- // Exemplo de uso
56
- import { Index } from 'minha-lib'
87
+ <WebChat
88
+ secret="SEU_SECRET_DO_PORTAL"
89
+ apiBaseUrl="https://api.synchat.com.br"
90
+ onStartChat={async (data) => {
91
+ // Conectar ao WebSocket usando o secret e enviar
92
+ // name, email, phone, message conforme documentação da API/WebSocket
93
+ await minhaConexaoWebSocket.iniciarChat(data);
94
+ }}
95
+ />
96
+ ```
57
97
 
58
- export default function Page() {
59
- return <Index onClick={() => alert('olá!')}>Enviar</Index>
60
- }
98
+ Se **onStartChat** não for passado, o widget exibe uma mensagem orientando a configurá-lo (conversa via WebSocket).
99
+
100
+ ---
101
+
102
+ ## Props
103
+
104
+ | Prop | Tipo | Obrigatório | Descrição |
105
+ |-----------------|----------|-------------|-----------|
106
+ | **secret** | `string` | Sim | Secret do canal WebChat (portal → Canais → criar WebChat → copiar secret). |
107
+ | **apiBaseUrl** | `string` | Sim | URL base da API (ex.: `https://api.synchat.com.br`). |
108
+ | **onStartChat** | `(data) => void \| Promise<void>` | Não | Callback ao clicar em "Iniciar chat". Recebe `{ name, email, phone, message }`. Implemente aqui a conexão WebSocket. |
109
+ | **outOfHoursMessage** | `string` | Não | Mensagem customizada quando estiver fora do horário. Se não informado, usa o texto padrão com o horário configurado no canal. |
110
+
111
+ ---
112
+
113
+ ## Variáveis de ambiente (sugestão)
114
+
115
+ Em produção, evite deixar o secret no código. Use variáveis de ambiente:
116
+
117
+ ```env
118
+ VITE_WEBCHAT_SECRET=seu_secret_aqui
119
+ VITE_SYNCHAT_API_URL=https://api.synchat.com.br
120
+ ```
121
+
122
+ ```tsx
123
+ <WebChat
124
+ secret={import.meta.env.VITE_WEBCHAT_SECRET ?? ""}
125
+ apiBaseUrl={import.meta.env.VITE_SYNCHAT_API_URL ?? "https://api.synchat.com.br"}
126
+ onStartChat={handleStartChat}
127
+ />
61
128
  ```
62
129
 
63
- ## Versionamento
64
- - Atualize `version` no `package.json` (ex.: `0.1.1`) antes de publicar novamente.
65
- - Ou use `npm version patch|minor|major`.
130
+ ---
66
131
 
67
- ## Teste local sem publicar (opcional)
68
- - `npm pack` gera um `.tgz` local. No app consumidor: `npm install ../caminho/minha-lib-0.1.0.tgz`.
132
+ ## Resumo do fluxo
69
133
 
70
- ## Dicas de qualidade
71
- - Adicione linters (`eslint`, `prettier`).
72
- - Configure CI (GitHub Actions) e _release_ automatizado (semantic-release).
73
- - Exporte CSS opcional com `style`/`files` ou mantenha apenas estilos inline/CSS-in-JS.
74
- - Se for SSR/Next.js, prefira `exports` bem definidos (já incluso).
134
+ 1. **Cadastro:** [portal.synchat.com.br](https://portal.synchat.com.br) → Cadastre-se.
135
+ 2. **Canal WebChat:** Portal → Canais → Novo canal → WebChat → preencher → Criar → **copiar o secret**.
136
+ 3. **No site:** `npm install @synchat/webchat` e usar `<WebChat secret="..." apiBaseUrl="..." />`.
137
+ 4. **Conversa:** Implementar **onStartChat** para conectar ao WebSocket e enviar a primeira mensagem quando o recurso estiver disponível.
75
138
 
76
139
  ---
77
- Feito com ❤️
140
+
141
+ ## Links
142
+
143
+ - **Site:** [synchat.com.br](https://synchat.com.br)
144
+ - **Portal (login/cadastro):** [portal.synchat.com.br](https://portal.synchat.com.br)
145
+ - **Cadastro:** [portal.synchat.com.br/auth/register](https://portal.synchat.com.br/auth/register)
146
+ - **Pacote no npm:** [npmjs.com/package/@synchat/webchat](https://www.npmjs.com/package/@synchat/webchat)
147
+
148
+ ---
149
+
150
+ Feito com ❤️ por [Synchat](https://synchat.com.br)
package/dist/index.d.mts CHANGED
@@ -1,6 +1,5 @@
1
1
  import * as React from 'react';
2
- import { FC } from 'react';
3
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React__default, { FC } from 'react';
4
3
 
5
4
  type ChatButtonProps = {
6
5
  children?: React.ReactNode;
@@ -17,6 +16,42 @@ interface IComponent<T = {}> extends FC<IDefaultProps & T> {
17
16
 
18
17
  declare const ChatButton: IComponent<ChatButtonProps>;
19
18
 
20
- declare const WebChat: () => react_jsx_runtime.JSX.Element;
19
+ interface WebChatSchedule {
20
+ weekDays?: string[];
21
+ weekdaysStart?: string;
22
+ weekdaysEnd?: string;
23
+ weekendStart?: string;
24
+ weekendEnd?: string;
25
+ }
26
+ interface WebChatConfig {
27
+ name: string;
28
+ status: string;
29
+ restrictBySchedule?: boolean;
30
+ schedule?: WebChatSchedule;
31
+ sendToQueueWhenInactive?: boolean;
32
+ }
33
+ interface WebChatProps {
34
+ /** Channel secret (from portal when creating webchat channel). */
35
+ secret: string;
36
+ /** Base URL of the Synchat API (e.g. https://api.synchat.com.br). */
37
+ apiBaseUrl: string;
38
+ /** Called when user clicks "Iniciar chat". The app should connect via WebSocket and send the message (conversation start is not via API). */
39
+ onStartChat?: (data: {
40
+ name: string;
41
+ email: string;
42
+ phone: string;
43
+ message: string;
44
+ }) => void | Promise<void>;
45
+ /** Optional: custom out-of-hours message. If not set, uses schedule from config. */
46
+ outOfHoursMessage?: string;
47
+ }
48
+ interface WebChatFormData {
49
+ name: string;
50
+ email: string;
51
+ phone: string;
52
+ message: string;
53
+ }
54
+
55
+ declare const WebChat: React__default.FC<WebChatProps>;
21
56
 
22
- export { ChatButton, type ChatButtonProps, WebChat };
57
+ export { ChatButton, type ChatButtonProps, WebChat, type WebChatConfig, type WebChatFormData, type WebChatProps };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import * as React from 'react';
2
- import { FC } from 'react';
3
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React__default, { FC } from 'react';
4
3
 
5
4
  type ChatButtonProps = {
6
5
  children?: React.ReactNode;
@@ -17,6 +16,42 @@ interface IComponent<T = {}> extends FC<IDefaultProps & T> {
17
16
 
18
17
  declare const ChatButton: IComponent<ChatButtonProps>;
19
18
 
20
- declare const WebChat: () => react_jsx_runtime.JSX.Element;
19
+ interface WebChatSchedule {
20
+ weekDays?: string[];
21
+ weekdaysStart?: string;
22
+ weekdaysEnd?: string;
23
+ weekendStart?: string;
24
+ weekendEnd?: string;
25
+ }
26
+ interface WebChatConfig {
27
+ name: string;
28
+ status: string;
29
+ restrictBySchedule?: boolean;
30
+ schedule?: WebChatSchedule;
31
+ sendToQueueWhenInactive?: boolean;
32
+ }
33
+ interface WebChatProps {
34
+ /** Channel secret (from portal when creating webchat channel). */
35
+ secret: string;
36
+ /** Base URL of the Synchat API (e.g. https://api.synchat.com.br). */
37
+ apiBaseUrl: string;
38
+ /** Called when user clicks "Iniciar chat". The app should connect via WebSocket and send the message (conversation start is not via API). */
39
+ onStartChat?: (data: {
40
+ name: string;
41
+ email: string;
42
+ phone: string;
43
+ message: string;
44
+ }) => void | Promise<void>;
45
+ /** Optional: custom out-of-hours message. If not set, uses schedule from config. */
46
+ outOfHoursMessage?: string;
47
+ }
48
+ interface WebChatFormData {
49
+ name: string;
50
+ email: string;
51
+ phone: string;
52
+ message: string;
53
+ }
54
+
55
+ declare const WebChat: React__default.FC<WebChatProps>;
21
56
 
22
- export { ChatButton, type ChatButtonProps, WebChat };
57
+ export { ChatButton, type ChatButtonProps, WebChat, type WebChatConfig, type WebChatFormData, type WebChatProps };
package/dist/index.js CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  var material = require('@mui/material');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
+ var react = require('react');
6
+ var CloseIcon = require('@mui/icons-material/Close');
7
+ var ChatIcon = require('@mui/icons-material/Chat');
8
+ var ScheduleIcon = require('@mui/icons-material/Schedule');
9
+
10
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
+
12
+ var CloseIcon__default = /*#__PURE__*/_interopDefault(CloseIcon);
13
+ var ChatIcon__default = /*#__PURE__*/_interopDefault(ChatIcon);
14
+ var ScheduleIcon__default = /*#__PURE__*/_interopDefault(ScheduleIcon);
5
15
 
6
16
  // src/lib/components/button/styles.tsx
7
17
  var AtomButton = material.styled(material.Button, {
@@ -31,14 +41,256 @@ var ChatButton = ({ children = "Chat", onClick, className, disabled }) => {
31
41
  }
32
42
  );
33
43
  };
34
- var WebChat = () => {
35
- return /* @__PURE__ */ jsxRuntime.jsx("button", { style: {
36
- position: "fixed",
37
- bottom: "20px",
38
- right: "20px",
39
- backgroundColor: "#007bff",
40
- display: "flex"
41
- }, children: "CHAT" });
44
+ var DAY_MAP = {
45
+ 0: "SUNDAY",
46
+ 1: "MONDAY",
47
+ 2: "TUESDAY",
48
+ 3: "WEDNESDAY",
49
+ 4: "THURSDAY",
50
+ 5: "FRIDAY",
51
+ 6: "SATURDAY"
52
+ };
53
+ function isWithinSchedule(config) {
54
+ if (!config.restrictBySchedule || !config.schedule) return true;
55
+ const now = /* @__PURE__ */ new Date();
56
+ const day = DAY_MAP[now.getDay()];
57
+ const time = String(now.getHours()).padStart(2, "0") + ":" + String(now.getMinutes()).padStart(2, "0");
58
+ const weekDays = config.schedule.weekDays ?? [
59
+ "MONDAY",
60
+ "TUESDAY",
61
+ "WEDNESDAY",
62
+ "THURSDAY",
63
+ "FRIDAY"
64
+ ];
65
+ const isWeekday = weekDays.includes(day);
66
+ if (isWeekday) {
67
+ const start2 = config.schedule.weekdaysStart ?? "07:00";
68
+ const end2 = config.schedule.weekdaysEnd ?? "18:00";
69
+ return time >= start2 && time <= end2;
70
+ }
71
+ const start = config.schedule.weekendStart ?? "07:00";
72
+ const end = config.schedule.weekendEnd ?? "13:00";
73
+ return time >= start && time <= end;
74
+ }
75
+ function formatScheduleMessage(config) {
76
+ if (!config.schedule) {
77
+ return "Nosso hor\xE1rio de atendimento \xE9 de segunda \xE0 sexta-feira das 07:00h \xE0s 18:00h. S\xE1bados, domingos e feriados das 07:00h \xE0s 13:00h.";
78
+ }
79
+ const wdStart = config.schedule.weekdaysStart ?? "07:00";
80
+ const wdEnd = config.schedule.weekdaysEnd ?? "18:00";
81
+ const weStart = config.schedule.weekendStart ?? "07:00";
82
+ const weEnd = config.schedule.weekendEnd ?? "13:00";
83
+ return `Nosso hor\xE1rio de atendimento \xE9 de segunda \xE0 sexta-feira das ${wdStart}h \xE0s ${wdEnd}h. S\xE1bados, domingos e feriados das ${weStart}h \xE0s ${weEnd}h.`;
84
+ }
85
+ var WebChat = ({
86
+ secret,
87
+ apiBaseUrl,
88
+ onStartChat,
89
+ outOfHoursMessage
90
+ }) => {
91
+ const [config, setConfig] = react.useState(null);
92
+ const [loading, setLoading] = react.useState(true);
93
+ const [error, setError] = react.useState(null);
94
+ const [open, setOpen] = react.useState(false);
95
+ const [submitting, setSubmitting] = react.useState(false);
96
+ const [submitted, setSubmitted] = react.useState(false);
97
+ const [form, setForm] = react.useState({
98
+ name: "",
99
+ email: "",
100
+ phone: "",
101
+ message: ""
102
+ });
103
+ const fetchConfig = react.useCallback(async () => {
104
+ if (!secret || !apiBaseUrl) return;
105
+ setLoading(true);
106
+ setError(null);
107
+ try {
108
+ const base = apiBaseUrl.replace(/\/$/, "");
109
+ const res = await fetch(`${base}/channel/webchat/${encodeURIComponent(secret)}`);
110
+ if (!res.ok) {
111
+ setError("Canal n\xE3o encontrado.");
112
+ setConfig(null);
113
+ return;
114
+ }
115
+ const data = await res.json();
116
+ setConfig(data);
117
+ } catch {
118
+ setError("N\xE3o foi poss\xEDvel carregar o canal.");
119
+ setConfig(null);
120
+ } finally {
121
+ setLoading(false);
122
+ }
123
+ }, [secret, apiBaseUrl]);
124
+ react.useEffect(() => {
125
+ fetchConfig();
126
+ }, [fetchConfig]);
127
+ const isActive = config && (config.status === "live" || config.status === "enable");
128
+ const outsideHours = config && config.restrictBySchedule && !isWithinSchedule(config);
129
+ const showOutOfHours = isActive && outsideHours;
130
+ const showForm = isActive && !outsideHours;
131
+ const handleSubmit = async (e) => {
132
+ e.preventDefault();
133
+ if (submitting || !form.name.trim()) return;
134
+ if (!onStartChat) {
135
+ setError("In\xEDcio de conversa ser\xE1 via WebSocket. Configure onStartChat no componente.");
136
+ return;
137
+ }
138
+ setSubmitting(true);
139
+ try {
140
+ await onStartChat({
141
+ name: form.name.trim(),
142
+ email: form.email.trim(),
143
+ phone: form.phone.trim(),
144
+ message: form.message.trim()
145
+ });
146
+ setSubmitted(true);
147
+ } catch (err) {
148
+ setError(err instanceof Error ? err.message : "Erro ao enviar.");
149
+ } finally {
150
+ setSubmitting(false);
151
+ }
152
+ };
153
+ if (!secret) return null;
154
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
155
+ /* @__PURE__ */ jsxRuntime.jsx(
156
+ material.IconButton,
157
+ {
158
+ onClick: () => setOpen((o) => !o),
159
+ sx: {
160
+ position: "fixed",
161
+ bottom: 20,
162
+ right: 20,
163
+ width: 56,
164
+ height: 56,
165
+ bgcolor: "#007bff",
166
+ color: "white",
167
+ "&:hover": { bgcolor: "#0056b3" },
168
+ boxShadow: 2
169
+ },
170
+ size: "large",
171
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChatIcon__default.default, {})
172
+ }
173
+ ),
174
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
175
+ material.Box,
176
+ {
177
+ sx: {
178
+ position: "fixed",
179
+ bottom: 90,
180
+ right: 20,
181
+ width: 380,
182
+ maxWidth: "calc(100vw - 40px)",
183
+ maxHeight: "calc(100vh - 120px)",
184
+ overflow: "auto",
185
+ bgcolor: "background.paper",
186
+ borderRadius: 2,
187
+ boxShadow: 6,
188
+ zIndex: 1300,
189
+ display: "flex",
190
+ flexDirection: "column"
191
+ },
192
+ children: [
193
+ /* @__PURE__ */ jsxRuntime.jsxs(
194
+ material.Box,
195
+ {
196
+ sx: {
197
+ display: "flex",
198
+ alignItems: "center",
199
+ justifyContent: "space-between",
200
+ p: 1.5,
201
+ borderBottom: 1,
202
+ borderColor: "divider"
203
+ },
204
+ children: [
205
+ /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { variant: "subtitle1", fontWeight: 600, children: config?.name ?? "Chat" }),
206
+ /* @__PURE__ */ jsxRuntime.jsx(material.IconButton, { size: "small", onClick: () => setOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon__default.default, {}) })
207
+ ]
208
+ }
209
+ ),
210
+ /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { sx: { p: 2, flex: 1 }, children: [
211
+ loading && /* @__PURE__ */ jsxRuntime.jsx(material.Box, { display: "flex", justifyContent: "center", py: 3, children: /* @__PURE__ */ jsxRuntime.jsx(material.CircularProgress, { size: 32 }) }),
212
+ error && !loading && /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { color: "error", variant: "body2", children: error }),
213
+ !loading && config && !isActive && /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { color: "text.secondary", variant: "body2", children: "Este canal n\xE3o est\xE1 dispon\xEDvel no momento." }),
214
+ showOutOfHours && /* @__PURE__ */ jsxRuntime.jsxs(
215
+ material.Box,
216
+ {
217
+ sx: {
218
+ textAlign: "center",
219
+ py: 2,
220
+ px: 1,
221
+ bgcolor: "#1976d2",
222
+ borderRadius: 1,
223
+ color: "white"
224
+ },
225
+ children: [
226
+ /* @__PURE__ */ jsxRuntime.jsx(ScheduleIcon__default.default, { sx: { fontSize: 48, opacity: 0.9, mb: 1 } }),
227
+ /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { variant: "body1", sx: { fontWeight: 500, mb: 1 }, children: "Fora do hor\xE1rio de atendimento" }),
228
+ /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { variant: "body2", sx: { opacity: 0.95 }, children: outOfHoursMessage ?? formatScheduleMessage(config) })
229
+ ]
230
+ }
231
+ ),
232
+ showForm && !submitted && /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { display: "flex", flexDirection: "column", gap: 2, children: [
233
+ /* @__PURE__ */ jsxRuntime.jsx(
234
+ material.TextField,
235
+ {
236
+ label: "Nome",
237
+ value: form.name,
238
+ onChange: (e) => setForm((f) => ({ ...f, name: e.target.value })),
239
+ required: true,
240
+ fullWidth: true,
241
+ size: "small"
242
+ }
243
+ ),
244
+ /* @__PURE__ */ jsxRuntime.jsx(
245
+ material.TextField,
246
+ {
247
+ label: "E-mail",
248
+ type: "email",
249
+ value: form.email,
250
+ onChange: (e) => setForm((f) => ({ ...f, email: e.target.value })),
251
+ fullWidth: true,
252
+ size: "small"
253
+ }
254
+ ),
255
+ /* @__PURE__ */ jsxRuntime.jsx(
256
+ material.TextField,
257
+ {
258
+ label: "Telefone",
259
+ value: form.phone,
260
+ onChange: (e) => setForm((f) => ({ ...f, phone: e.target.value })),
261
+ fullWidth: true,
262
+ size: "small"
263
+ }
264
+ ),
265
+ /* @__PURE__ */ jsxRuntime.jsx(
266
+ material.TextField,
267
+ {
268
+ label: "Mensagem",
269
+ value: form.message,
270
+ onChange: (e) => setForm((f) => ({ ...f, message: e.target.value })),
271
+ multiline: true,
272
+ rows: 3,
273
+ fullWidth: true,
274
+ size: "small"
275
+ }
276
+ ),
277
+ /* @__PURE__ */ jsxRuntime.jsx(
278
+ material.Button,
279
+ {
280
+ type: "submit",
281
+ variant: "contained",
282
+ disabled: submitting || !form.name.trim(),
283
+ fullWidth: true,
284
+ children: submitting ? "Enviando\u2026" : "Iniciar chat"
285
+ }
286
+ )
287
+ ] }) }),
288
+ showForm && submitted && /* @__PURE__ */ jsxRuntime.jsx(material.Typography, { color: "text.secondary", variant: "body2", sx: { py: 2 }, children: "Sua mensagem foi enviada. Em breve um atendente responder\xE1." })
289
+ ] })
290
+ ]
291
+ }
292
+ )
293
+ ] });
42
294
  };
43
295
 
44
296
  exports.ChatButton = ChatButton;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/components/button/styles.tsx","../src/lib/components/button/index.tsx","../src/lib/components/webchat/index.tsx"],"names":["styled","Button","jsx"],"mappings":";;;;;;AA8EO,IAAM,UAAA,GAAaA,gBAAOC,eAAA,EAAQ;AAAA,EACrC,iBAAA,EAAmB,CAAC,IAAA,KAAS,IAAA,KAAS;AAC1C,CAAC,CAAA,CAAmB,CAAC,EAAE,UAAA,GAAa,WAAU,KAAM;AAEhD,EAAA,OAAO,EACP;AAEJ,CAAC,CAAA;AChFM,IAAM,UAAA,GAA0C,CAAC,EAAE,QAAA,GAAW,QAAQ,OAAA,EAAS,SAAA,EAAW,UAAS,KAAM;AAC9G,EAAA,uBACEC,cAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA;AAAA,MACA,QAAA;AAAA,MACA,SAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACH,QAAA,EAAU,OAAA;AAAA,QACV,MAAA,EAAQ,MAAA;AAAA,QACR,KAAA,EAAO,MAAA;AAAA,QACP,eAAA,EAAiB,SAAA;AAAA,QACjB,KAAA,EAAO,MAAA;AAAA,QACP,OAAA,EAAS,MAAA;AAAA,QACT,YAAA,EAAc,KAAA;AAAA,QACd,KAAA,EAAO,MAAA;AAAA,QACP,MAAA,EAAQ;AAAA,OACZ;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;AC1BO,IAAM,UAAU,MAAM;AACzB,EAAA,uBACIA,cAAAA,CAAC,QAAA,EAAA,EAAO,KAAA,EAAO;AAAA,IACX,QAAA,EAAU,OAAA;AAAA,IACV,MAAA,EAAQ,MAAA;AAAA,IACR,KAAA,EAAO,MAAA;AAAA,IACP,eAAA,EAAiB,SAAA;AAAA,IACjB,OAAA,EAAS;AAAA,KACV,QAAA,EAAA,MAAA,EAEH,CAAA;AAER","file":"index.js","sourcesContent":["import { Button, ButtonProps, styled } from \"@mui/material\";\nimport { ButtonHTMLAttributes } from \"react\";\n\nconst disabledStyles = {\n backgroundColor: \"#E0E0E0\",\n color: \"#9E9E9E\",\n borderColor: \"#BDBDBD\",\n};\n\nconst buttonVariants = {\n primary: {\n background: \"#00BB7E\",\n color: \"#FFF\",\n border: \"none\",\n },\n secondary: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"#00BB7E\",\n },\n error: {\n background: \"transparent\",\n color: \"#D32F2F\",\n border: \"#D32F2F\",\n },\n danger: {\n background: \"#E61E2E\",\n color: \"#fff\",\n border: \"none\",\n },\n outlinedBlue: {\n background: \"transparent\",\n color: \"#2196F3\",\n border: \"#2196F3\",\n },\n outlinedGreen: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"#00BB7E\",\n },\n outlinedBlack: {\n background: \"transparent\",\n color: \"#000000DE\",\n border: \"#000000DE\",\n },\n outlinedGrey: {\n background: \"transparent\",\n color: \"#59676D\",\n border: \"#0B0D0E52\",\n },\n textPrimary: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"transparent\",\n },\n textSecondary: {\n background: \"transparent\",\n color: \"#000000DE\",\n border: \"transparent\",\n },\n textBlue: {\n background: \"transparent\",\n color: \"#2196F3\",\n border: \"transparent\",\n },\n default: {\n background: \"#00BB7E\",\n color: \"#FFF\",\n border: \"#00BB7E\",\n },\n};\n\ninterface AtomButtonProps\n extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"color\">,\n ButtonProps {\n buttonType?: keyof typeof buttonVariants;\n}\n\nexport const AtomButton = styled(Button, {\n shouldForwardProp: (prop) => prop !== \"buttonType\",\n})<AtomButtonProps>(({ buttonType = \"default\" }) => {\n\n return {\n }\n\n});","import * as React from 'react'\nimport { ChatButtonProps } from \"./types\";\nimport IComponent from \"../../../types/component\";\nimport { AtomButton } from \"./styles\";\n\nexport const ChatButton: IComponent<ChatButtonProps> = ({ children = 'Chat', onClick, className, disabled }) => {\n return (\n <AtomButton\n onClick={onClick}\n disabled={disabled}\n className={className}\n style={{\n position: \"fixed\",\n bottom: \"20px\",\n right: \"20px\",\n backgroundColor: \"#007bff\",\n color: \"#fff\",\n display: \"flex\",\n borderRadius: \"50%\",\n width: \"60px\",\n height: \"60px\"\n }}\n >\n {children}\n </AtomButton>\n )\n}\n","export const WebChat = () => {\n return (\n <button style={{\n position: \"fixed\",\n bottom: \"20px\",\n right: \"20px\",\n backgroundColor: \"#007bff\",\n display: \"flex\",\n }}>\n CHAT\n </button>\n )\n}"]}
1
+ {"version":3,"sources":["../src/lib/components/button/styles.tsx","../src/lib/components/button/index.tsx","../src/lib/components/webchat/index.tsx"],"names":["styled","Button","jsx","start","end","useState","useCallback","useEffect","jsxs","Fragment","IconButton","ChatIcon","Box","Typography","CloseIcon","CircularProgress","ScheduleIcon","TextField"],"mappings":"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","file":"index.js","sourcesContent":["import { Button, ButtonProps, styled } from \"@mui/material\";\nimport { ButtonHTMLAttributes } from \"react\";\n\nconst disabledStyles = {\n backgroundColor: \"#E0E0E0\",\n color: \"#9E9E9E\",\n borderColor: \"#BDBDBD\",\n};\n\nconst buttonVariants = {\n primary: {\n background: \"#00BB7E\",\n color: \"#FFF\",\n border: \"none\",\n },\n secondary: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"#00BB7E\",\n },\n error: {\n background: \"transparent\",\n color: \"#D32F2F\",\n border: \"#D32F2F\",\n },\n danger: {\n background: \"#E61E2E\",\n color: \"#fff\",\n border: \"none\",\n },\n outlinedBlue: {\n background: \"transparent\",\n color: \"#2196F3\",\n border: \"#2196F3\",\n },\n outlinedGreen: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"#00BB7E\",\n },\n outlinedBlack: {\n background: \"transparent\",\n color: \"#000000DE\",\n border: \"#000000DE\",\n },\n outlinedGrey: {\n background: \"transparent\",\n color: \"#59676D\",\n border: \"#0B0D0E52\",\n },\n textPrimary: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"transparent\",\n },\n textSecondary: {\n background: \"transparent\",\n color: \"#000000DE\",\n border: \"transparent\",\n },\n textBlue: {\n background: \"transparent\",\n color: \"#2196F3\",\n border: \"transparent\",\n },\n default: {\n background: \"#00BB7E\",\n color: \"#FFF\",\n border: \"#00BB7E\",\n },\n};\n\ninterface AtomButtonProps\n extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"color\">,\n ButtonProps {\n buttonType?: keyof typeof buttonVariants;\n}\n\nexport const AtomButton = styled(Button, {\n shouldForwardProp: (prop) => prop !== \"buttonType\",\n})<AtomButtonProps>(({ buttonType = \"default\" }) => {\n\n return {\n }\n\n});","import * as React from 'react'\nimport { ChatButtonProps } from \"./types\";\nimport IComponent from \"../../../types/component\";\nimport { AtomButton } from \"./styles\";\n\nexport const ChatButton: IComponent<ChatButtonProps> = ({ children = 'Chat', onClick, className, disabled }) => {\n return (\n <AtomButton\n onClick={onClick}\n disabled={disabled}\n className={className}\n style={{\n position: \"fixed\",\n bottom: \"20px\",\n right: \"20px\",\n backgroundColor: \"#007bff\",\n color: \"#fff\",\n display: \"flex\",\n borderRadius: \"50%\",\n width: \"60px\",\n height: \"60px\"\n }}\n >\n {children}\n </AtomButton>\n )\n}\n","import React, { useCallback, useEffect, useState } from \"react\";\nimport {\n Box,\n Button,\n CircularProgress,\n IconButton,\n TextField,\n Typography,\n} from \"@mui/material\";\nimport CloseIcon from \"@mui/icons-material/Close\";\nimport ChatIcon from \"@mui/icons-material/Chat\";\nimport ScheduleIcon from \"@mui/icons-material/Schedule\";\nimport { WebChatConfig, WebChatProps } from \"./types\";\n\nconst DAY_MAP: Record<number, string> = {\n 0: \"SUNDAY\",\n 1: \"MONDAY\",\n 2: \"TUESDAY\",\n 3: \"WEDNESDAY\",\n 4: \"THURSDAY\",\n 5: \"FRIDAY\",\n 6: \"SATURDAY\",\n};\n\nfunction isWithinSchedule(config: WebChatConfig): boolean {\n if (!config.restrictBySchedule || !config.schedule) return true;\n\n const now = new Date();\n const day = DAY_MAP[now.getDay()];\n const time =\n String(now.getHours()).padStart(2, \"0\") +\n \":\" +\n String(now.getMinutes()).padStart(2, \"0\");\n const weekDays = config.schedule.weekDays ?? [\n \"MONDAY\",\n \"TUESDAY\",\n \"WEDNESDAY\",\n \"THURSDAY\",\n \"FRIDAY\",\n ];\n const isWeekday = weekDays.includes(day);\n\n if (isWeekday) {\n const start = config.schedule.weekdaysStart ?? \"07:00\";\n const end = config.schedule.weekdaysEnd ?? \"18:00\";\n return time >= start && time <= end;\n }\n\n const start = config.schedule.weekendStart ?? \"07:00\";\n const end = config.schedule.weekendEnd ?? \"13:00\";\n return time >= start && time <= end;\n}\n\nfunction formatScheduleMessage(config: WebChatConfig): string {\n if (!config.schedule) {\n return \"Nosso horário de atendimento é de segunda à sexta-feira das 07:00h às 18:00h. Sábados, domingos e feriados das 07:00h às 13:00h.\";\n }\n const wdStart = config.schedule.weekdaysStart ?? \"07:00\";\n const wdEnd = config.schedule.weekdaysEnd ?? \"18:00\";\n const weStart = config.schedule.weekendStart ?? \"07:00\";\n const weEnd = config.schedule.weekendEnd ?? \"13:00\";\n return `Nosso horário de atendimento é de segunda à sexta-feira das ${wdStart}h às ${wdEnd}h. Sábados, domingos e feriados das ${weStart}h às ${weEnd}h.`;\n}\n\nexport const WebChat: React.FC<WebChatProps> = ({\n secret,\n apiBaseUrl,\n onStartChat,\n outOfHoursMessage,\n}) => {\n const [config, setConfig] = useState<WebChatConfig | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [open, setOpen] = useState(false);\n const [submitting, setSubmitting] = useState(false);\n const [submitted, setSubmitted] = useState(false);\n\n const [form, setForm] = useState({\n name: \"\",\n email: \"\",\n phone: \"\",\n message: \"\",\n });\n\n const fetchConfig = useCallback(async () => {\n if (!secret || !apiBaseUrl) return;\n setLoading(true);\n setError(null);\n try {\n const base = apiBaseUrl.replace(/\\/$/, \"\");\n const res = await fetch(`${base}/channel/webchat/${encodeURIComponent(secret)}`);\n if (!res.ok) {\n setError(\"Canal não encontrado.\");\n setConfig(null);\n return;\n }\n const data: WebChatConfig = await res.json();\n setConfig(data);\n } catch {\n setError(\"Não foi possível carregar o canal.\");\n setConfig(null);\n } finally {\n setLoading(false);\n }\n }, [secret, apiBaseUrl]);\n\n useEffect(() => {\n fetchConfig();\n }, [fetchConfig]);\n\n const isActive =\n config &&\n (config.status === \"live\" || config.status === \"enable\");\n const outsideHours =\n config && config.restrictBySchedule && !isWithinSchedule(config);\n const showOutOfHours = isActive && outsideHours;\n const showForm = isActive && !outsideHours;\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (submitting || !form.name.trim()) return;\n if (!onStartChat) {\n setError(\"Início de conversa será via WebSocket. Configure onStartChat no componente.\");\n return;\n }\n\n setSubmitting(true);\n try {\n await onStartChat({\n name: form.name.trim(),\n email: form.email.trim(),\n phone: form.phone.trim(),\n message: form.message.trim(),\n });\n setSubmitted(true);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Erro ao enviar.\");\n } finally {\n setSubmitting(false);\n }\n };\n\n if (!secret) return null;\n\n return (\n <>\n <IconButton\n onClick={() => setOpen((o) => !o)}\n sx={{\n position: \"fixed\",\n bottom: 20,\n right: 20,\n width: 56,\n height: 56,\n bgcolor: \"#007bff\",\n color: \"white\",\n \"&:hover\": { bgcolor: \"#0056b3\" },\n boxShadow: 2,\n }}\n size=\"large\"\n >\n <ChatIcon />\n </IconButton>\n\n {open && (\n <Box\n sx={{\n position: \"fixed\",\n bottom: 90,\n right: 20,\n width: 380,\n maxWidth: \"calc(100vw - 40px)\",\n maxHeight: \"calc(100vh - 120px)\",\n overflow: \"auto\",\n bgcolor: \"background.paper\",\n borderRadius: 2,\n boxShadow: 6,\n zIndex: 1300,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <Box\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n p: 1.5,\n borderBottom: 1,\n borderColor: \"divider\",\n }}\n >\n <Typography variant=\"subtitle1\" fontWeight={600}>\n {config?.name ?? \"Chat\"}\n </Typography>\n <IconButton size=\"small\" onClick={() => setOpen(false)}>\n <CloseIcon />\n </IconButton>\n </Box>\n\n <Box sx={{ p: 2, flex: 1 }}>\n {loading && (\n <Box display=\"flex\" justifyContent=\"center\" py={3}>\n <CircularProgress size={32} />\n </Box>\n )}\n\n {error && !loading && (\n <Typography color=\"error\" variant=\"body2\">\n {error}\n </Typography>\n )}\n\n {!loading && config && !isActive && (\n <Typography color=\"text.secondary\" variant=\"body2\">\n Este canal não está disponível no momento.\n </Typography>\n )}\n\n {showOutOfHours && (\n <Box\n sx={{\n textAlign: \"center\",\n py: 2,\n px: 1,\n bgcolor: \"#1976d2\",\n borderRadius: 1,\n color: \"white\",\n }}\n >\n <ScheduleIcon sx={{ fontSize: 48, opacity: 0.9, mb: 1 }} />\n <Typography variant=\"body1\" sx={{ fontWeight: 500, mb: 1 }}>\n Fora do horário de atendimento\n </Typography>\n <Typography variant=\"body2\" sx={{ opacity: 0.95 }}>\n {outOfHoursMessage ?? formatScheduleMessage(config)}\n </Typography>\n </Box>\n )}\n\n {showForm && !submitted && (\n <form onSubmit={handleSubmit}>\n <Box display=\"flex\" flexDirection=\"column\" gap={2}>\n <TextField\n label=\"Nome\"\n value={form.name}\n onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}\n required\n fullWidth\n size=\"small\"\n />\n <TextField\n label=\"E-mail\"\n type=\"email\"\n value={form.email}\n onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}\n fullWidth\n size=\"small\"\n />\n <TextField\n label=\"Telefone\"\n value={form.phone}\n onChange={(e) => setForm((f) => ({ ...f, phone: e.target.value }))}\n fullWidth\n size=\"small\"\n />\n <TextField\n label=\"Mensagem\"\n value={form.message}\n onChange={(e) => setForm((f) => ({ ...f, message: e.target.value }))}\n multiline\n rows={3}\n fullWidth\n size=\"small\"\n />\n <Button\n type=\"submit\"\n variant=\"contained\"\n disabled={submitting || !form.name.trim()}\n fullWidth\n >\n {submitting ? \"Enviando…\" : \"Iniciar chat\"}\n </Button>\n </Box>\n </form>\n )}\n\n {showForm && submitted && (\n <Typography color=\"text.secondary\" variant=\"body2\" sx={{ py: 2 }}>\n Sua mensagem foi enviada. Em breve um atendente responderá.\n </Typography>\n )}\n </Box>\n </Box>\n )}\n </>\n );\n};\n"]}
package/dist/index.mjs CHANGED
@@ -1,5 +1,9 @@
1
- import { styled, Button } from '@mui/material';
2
- import { jsx } from 'react/jsx-runtime';
1
+ import { styled, Button, IconButton, Box, Typography, CircularProgress, TextField } from '@mui/material';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+ import { useState, useCallback, useEffect } from 'react';
4
+ import CloseIcon from '@mui/icons-material/Close';
5
+ import ChatIcon from '@mui/icons-material/Chat';
6
+ import ScheduleIcon from '@mui/icons-material/Schedule';
3
7
 
4
8
  // src/lib/components/button/styles.tsx
5
9
  var AtomButton = styled(Button, {
@@ -29,14 +33,256 @@ var ChatButton = ({ children = "Chat", onClick, className, disabled }) => {
29
33
  }
30
34
  );
31
35
  };
32
- var WebChat = () => {
33
- return /* @__PURE__ */ jsx("button", { style: {
34
- position: "fixed",
35
- bottom: "20px",
36
- right: "20px",
37
- backgroundColor: "#007bff",
38
- display: "flex"
39
- }, children: "CHAT" });
36
+ var DAY_MAP = {
37
+ 0: "SUNDAY",
38
+ 1: "MONDAY",
39
+ 2: "TUESDAY",
40
+ 3: "WEDNESDAY",
41
+ 4: "THURSDAY",
42
+ 5: "FRIDAY",
43
+ 6: "SATURDAY"
44
+ };
45
+ function isWithinSchedule(config) {
46
+ if (!config.restrictBySchedule || !config.schedule) return true;
47
+ const now = /* @__PURE__ */ new Date();
48
+ const day = DAY_MAP[now.getDay()];
49
+ const time = String(now.getHours()).padStart(2, "0") + ":" + String(now.getMinutes()).padStart(2, "0");
50
+ const weekDays = config.schedule.weekDays ?? [
51
+ "MONDAY",
52
+ "TUESDAY",
53
+ "WEDNESDAY",
54
+ "THURSDAY",
55
+ "FRIDAY"
56
+ ];
57
+ const isWeekday = weekDays.includes(day);
58
+ if (isWeekday) {
59
+ const start2 = config.schedule.weekdaysStart ?? "07:00";
60
+ const end2 = config.schedule.weekdaysEnd ?? "18:00";
61
+ return time >= start2 && time <= end2;
62
+ }
63
+ const start = config.schedule.weekendStart ?? "07:00";
64
+ const end = config.schedule.weekendEnd ?? "13:00";
65
+ return time >= start && time <= end;
66
+ }
67
+ function formatScheduleMessage(config) {
68
+ if (!config.schedule) {
69
+ return "Nosso hor\xE1rio de atendimento \xE9 de segunda \xE0 sexta-feira das 07:00h \xE0s 18:00h. S\xE1bados, domingos e feriados das 07:00h \xE0s 13:00h.";
70
+ }
71
+ const wdStart = config.schedule.weekdaysStart ?? "07:00";
72
+ const wdEnd = config.schedule.weekdaysEnd ?? "18:00";
73
+ const weStart = config.schedule.weekendStart ?? "07:00";
74
+ const weEnd = config.schedule.weekendEnd ?? "13:00";
75
+ return `Nosso hor\xE1rio de atendimento \xE9 de segunda \xE0 sexta-feira das ${wdStart}h \xE0s ${wdEnd}h. S\xE1bados, domingos e feriados das ${weStart}h \xE0s ${weEnd}h.`;
76
+ }
77
+ var WebChat = ({
78
+ secret,
79
+ apiBaseUrl,
80
+ onStartChat,
81
+ outOfHoursMessage
82
+ }) => {
83
+ const [config, setConfig] = useState(null);
84
+ const [loading, setLoading] = useState(true);
85
+ const [error, setError] = useState(null);
86
+ const [open, setOpen] = useState(false);
87
+ const [submitting, setSubmitting] = useState(false);
88
+ const [submitted, setSubmitted] = useState(false);
89
+ const [form, setForm] = useState({
90
+ name: "",
91
+ email: "",
92
+ phone: "",
93
+ message: ""
94
+ });
95
+ const fetchConfig = useCallback(async () => {
96
+ if (!secret || !apiBaseUrl) return;
97
+ setLoading(true);
98
+ setError(null);
99
+ try {
100
+ const base = apiBaseUrl.replace(/\/$/, "");
101
+ const res = await fetch(`${base}/channel/webchat/${encodeURIComponent(secret)}`);
102
+ if (!res.ok) {
103
+ setError("Canal n\xE3o encontrado.");
104
+ setConfig(null);
105
+ return;
106
+ }
107
+ const data = await res.json();
108
+ setConfig(data);
109
+ } catch {
110
+ setError("N\xE3o foi poss\xEDvel carregar o canal.");
111
+ setConfig(null);
112
+ } finally {
113
+ setLoading(false);
114
+ }
115
+ }, [secret, apiBaseUrl]);
116
+ useEffect(() => {
117
+ fetchConfig();
118
+ }, [fetchConfig]);
119
+ const isActive = config && (config.status === "live" || config.status === "enable");
120
+ const outsideHours = config && config.restrictBySchedule && !isWithinSchedule(config);
121
+ const showOutOfHours = isActive && outsideHours;
122
+ const showForm = isActive && !outsideHours;
123
+ const handleSubmit = async (e) => {
124
+ e.preventDefault();
125
+ if (submitting || !form.name.trim()) return;
126
+ if (!onStartChat) {
127
+ setError("In\xEDcio de conversa ser\xE1 via WebSocket. Configure onStartChat no componente.");
128
+ return;
129
+ }
130
+ setSubmitting(true);
131
+ try {
132
+ await onStartChat({
133
+ name: form.name.trim(),
134
+ email: form.email.trim(),
135
+ phone: form.phone.trim(),
136
+ message: form.message.trim()
137
+ });
138
+ setSubmitted(true);
139
+ } catch (err) {
140
+ setError(err instanceof Error ? err.message : "Erro ao enviar.");
141
+ } finally {
142
+ setSubmitting(false);
143
+ }
144
+ };
145
+ if (!secret) return null;
146
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
147
+ /* @__PURE__ */ jsx(
148
+ IconButton,
149
+ {
150
+ onClick: () => setOpen((o) => !o),
151
+ sx: {
152
+ position: "fixed",
153
+ bottom: 20,
154
+ right: 20,
155
+ width: 56,
156
+ height: 56,
157
+ bgcolor: "#007bff",
158
+ color: "white",
159
+ "&:hover": { bgcolor: "#0056b3" },
160
+ boxShadow: 2
161
+ },
162
+ size: "large",
163
+ children: /* @__PURE__ */ jsx(ChatIcon, {})
164
+ }
165
+ ),
166
+ open && /* @__PURE__ */ jsxs(
167
+ Box,
168
+ {
169
+ sx: {
170
+ position: "fixed",
171
+ bottom: 90,
172
+ right: 20,
173
+ width: 380,
174
+ maxWidth: "calc(100vw - 40px)",
175
+ maxHeight: "calc(100vh - 120px)",
176
+ overflow: "auto",
177
+ bgcolor: "background.paper",
178
+ borderRadius: 2,
179
+ boxShadow: 6,
180
+ zIndex: 1300,
181
+ display: "flex",
182
+ flexDirection: "column"
183
+ },
184
+ children: [
185
+ /* @__PURE__ */ jsxs(
186
+ Box,
187
+ {
188
+ sx: {
189
+ display: "flex",
190
+ alignItems: "center",
191
+ justifyContent: "space-between",
192
+ p: 1.5,
193
+ borderBottom: 1,
194
+ borderColor: "divider"
195
+ },
196
+ children: [
197
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle1", fontWeight: 600, children: config?.name ?? "Chat" }),
198
+ /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: () => setOpen(false), children: /* @__PURE__ */ jsx(CloseIcon, {}) })
199
+ ]
200
+ }
201
+ ),
202
+ /* @__PURE__ */ jsxs(Box, { sx: { p: 2, flex: 1 }, children: [
203
+ loading && /* @__PURE__ */ jsx(Box, { display: "flex", justifyContent: "center", py: 3, children: /* @__PURE__ */ jsx(CircularProgress, { size: 32 }) }),
204
+ error && !loading && /* @__PURE__ */ jsx(Typography, { color: "error", variant: "body2", children: error }),
205
+ !loading && config && !isActive && /* @__PURE__ */ jsx(Typography, { color: "text.secondary", variant: "body2", children: "Este canal n\xE3o est\xE1 dispon\xEDvel no momento." }),
206
+ showOutOfHours && /* @__PURE__ */ jsxs(
207
+ Box,
208
+ {
209
+ sx: {
210
+ textAlign: "center",
211
+ py: 2,
212
+ px: 1,
213
+ bgcolor: "#1976d2",
214
+ borderRadius: 1,
215
+ color: "white"
216
+ },
217
+ children: [
218
+ /* @__PURE__ */ jsx(ScheduleIcon, { sx: { fontSize: 48, opacity: 0.9, mb: 1 } }),
219
+ /* @__PURE__ */ jsx(Typography, { variant: "body1", sx: { fontWeight: 500, mb: 1 }, children: "Fora do hor\xE1rio de atendimento" }),
220
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", sx: { opacity: 0.95 }, children: outOfHoursMessage ?? formatScheduleMessage(config) })
221
+ ]
222
+ }
223
+ ),
224
+ showForm && !submitted && /* @__PURE__ */ jsx("form", { onSubmit: handleSubmit, children: /* @__PURE__ */ jsxs(Box, { display: "flex", flexDirection: "column", gap: 2, children: [
225
+ /* @__PURE__ */ jsx(
226
+ TextField,
227
+ {
228
+ label: "Nome",
229
+ value: form.name,
230
+ onChange: (e) => setForm((f) => ({ ...f, name: e.target.value })),
231
+ required: true,
232
+ fullWidth: true,
233
+ size: "small"
234
+ }
235
+ ),
236
+ /* @__PURE__ */ jsx(
237
+ TextField,
238
+ {
239
+ label: "E-mail",
240
+ type: "email",
241
+ value: form.email,
242
+ onChange: (e) => setForm((f) => ({ ...f, email: e.target.value })),
243
+ fullWidth: true,
244
+ size: "small"
245
+ }
246
+ ),
247
+ /* @__PURE__ */ jsx(
248
+ TextField,
249
+ {
250
+ label: "Telefone",
251
+ value: form.phone,
252
+ onChange: (e) => setForm((f) => ({ ...f, phone: e.target.value })),
253
+ fullWidth: true,
254
+ size: "small"
255
+ }
256
+ ),
257
+ /* @__PURE__ */ jsx(
258
+ TextField,
259
+ {
260
+ label: "Mensagem",
261
+ value: form.message,
262
+ onChange: (e) => setForm((f) => ({ ...f, message: e.target.value })),
263
+ multiline: true,
264
+ rows: 3,
265
+ fullWidth: true,
266
+ size: "small"
267
+ }
268
+ ),
269
+ /* @__PURE__ */ jsx(
270
+ Button,
271
+ {
272
+ type: "submit",
273
+ variant: "contained",
274
+ disabled: submitting || !form.name.trim(),
275
+ fullWidth: true,
276
+ children: submitting ? "Enviando\u2026" : "Iniciar chat"
277
+ }
278
+ )
279
+ ] }) }),
280
+ showForm && submitted && /* @__PURE__ */ jsx(Typography, { color: "text.secondary", variant: "body2", sx: { py: 2 }, children: "Sua mensagem foi enviada. Em breve um atendente responder\xE1." })
281
+ ] })
282
+ ]
283
+ }
284
+ )
285
+ ] });
40
286
  };
41
287
 
42
288
  export { ChatButton, WebChat };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/components/button/styles.tsx","../src/lib/components/button/index.tsx","../src/lib/components/webchat/index.tsx"],"names":["jsx"],"mappings":";;;;AA8EO,IAAM,UAAA,GAAa,OAAO,MAAA,EAAQ;AAAA,EACrC,iBAAA,EAAmB,CAAC,IAAA,KAAS,IAAA,KAAS;AAC1C,CAAC,CAAA,CAAmB,CAAC,EAAE,UAAA,GAAa,WAAU,KAAM;AAEhD,EAAA,OAAO,EACP;AAEJ,CAAC,CAAA;AChFM,IAAM,UAAA,GAA0C,CAAC,EAAE,QAAA,GAAW,QAAQ,OAAA,EAAS,SAAA,EAAW,UAAS,KAAM;AAC9G,EAAA,uBACE,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA;AAAA,MACA,QAAA;AAAA,MACA,SAAA;AAAA,MACA,KAAA,EAAO;AAAA,QACH,QAAA,EAAU,OAAA;AAAA,QACV,MAAA,EAAQ,MAAA;AAAA,QACR,KAAA,EAAO,MAAA;AAAA,QACP,eAAA,EAAiB,SAAA;AAAA,QACjB,KAAA,EAAO,MAAA;AAAA,QACP,OAAA,EAAS,MAAA;AAAA,QACT,YAAA,EAAc,KAAA;AAAA,QACd,KAAA,EAAO,MAAA;AAAA,QACP,MAAA,EAAQ;AAAA,OACZ;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;AC1BO,IAAM,UAAU,MAAM;AACzB,EAAA,uBACIA,GAAAA,CAAC,QAAA,EAAA,EAAO,KAAA,EAAO;AAAA,IACX,QAAA,EAAU,OAAA;AAAA,IACV,MAAA,EAAQ,MAAA;AAAA,IACR,KAAA,EAAO,MAAA;AAAA,IACP,eAAA,EAAiB,SAAA;AAAA,IACjB,OAAA,EAAS;AAAA,KACV,QAAA,EAAA,MAAA,EAEH,CAAA;AAER","file":"index.mjs","sourcesContent":["import { Button, ButtonProps, styled } from \"@mui/material\";\nimport { ButtonHTMLAttributes } from \"react\";\n\nconst disabledStyles = {\n backgroundColor: \"#E0E0E0\",\n color: \"#9E9E9E\",\n borderColor: \"#BDBDBD\",\n};\n\nconst buttonVariants = {\n primary: {\n background: \"#00BB7E\",\n color: \"#FFF\",\n border: \"none\",\n },\n secondary: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"#00BB7E\",\n },\n error: {\n background: \"transparent\",\n color: \"#D32F2F\",\n border: \"#D32F2F\",\n },\n danger: {\n background: \"#E61E2E\",\n color: \"#fff\",\n border: \"none\",\n },\n outlinedBlue: {\n background: \"transparent\",\n color: \"#2196F3\",\n border: \"#2196F3\",\n },\n outlinedGreen: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"#00BB7E\",\n },\n outlinedBlack: {\n background: \"transparent\",\n color: \"#000000DE\",\n border: \"#000000DE\",\n },\n outlinedGrey: {\n background: \"transparent\",\n color: \"#59676D\",\n border: \"#0B0D0E52\",\n },\n textPrimary: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"transparent\",\n },\n textSecondary: {\n background: \"transparent\",\n color: \"#000000DE\",\n border: \"transparent\",\n },\n textBlue: {\n background: \"transparent\",\n color: \"#2196F3\",\n border: \"transparent\",\n },\n default: {\n background: \"#00BB7E\",\n color: \"#FFF\",\n border: \"#00BB7E\",\n },\n};\n\ninterface AtomButtonProps\n extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"color\">,\n ButtonProps {\n buttonType?: keyof typeof buttonVariants;\n}\n\nexport const AtomButton = styled(Button, {\n shouldForwardProp: (prop) => prop !== \"buttonType\",\n})<AtomButtonProps>(({ buttonType = \"default\" }) => {\n\n return {\n }\n\n});","import * as React from 'react'\nimport { ChatButtonProps } from \"./types\";\nimport IComponent from \"../../../types/component\";\nimport { AtomButton } from \"./styles\";\n\nexport const ChatButton: IComponent<ChatButtonProps> = ({ children = 'Chat', onClick, className, disabled }) => {\n return (\n <AtomButton\n onClick={onClick}\n disabled={disabled}\n className={className}\n style={{\n position: \"fixed\",\n bottom: \"20px\",\n right: \"20px\",\n backgroundColor: \"#007bff\",\n color: \"#fff\",\n display: \"flex\",\n borderRadius: \"50%\",\n width: \"60px\",\n height: \"60px\"\n }}\n >\n {children}\n </AtomButton>\n )\n}\n","export const WebChat = () => {\n return (\n <button style={{\n position: \"fixed\",\n bottom: \"20px\",\n right: \"20px\",\n backgroundColor: \"#007bff\",\n display: \"flex\",\n }}>\n CHAT\n </button>\n )\n}"]}
1
+ {"version":3,"sources":["../src/lib/components/button/styles.tsx","../src/lib/components/button/index.tsx","../src/lib/components/webchat/index.tsx"],"names":["start","end","jsx","Button"],"mappings":"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","file":"index.mjs","sourcesContent":["import { Button, ButtonProps, styled } from \"@mui/material\";\nimport { ButtonHTMLAttributes } from \"react\";\n\nconst disabledStyles = {\n backgroundColor: \"#E0E0E0\",\n color: \"#9E9E9E\",\n borderColor: \"#BDBDBD\",\n};\n\nconst buttonVariants = {\n primary: {\n background: \"#00BB7E\",\n color: \"#FFF\",\n border: \"none\",\n },\n secondary: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"#00BB7E\",\n },\n error: {\n background: \"transparent\",\n color: \"#D32F2F\",\n border: \"#D32F2F\",\n },\n danger: {\n background: \"#E61E2E\",\n color: \"#fff\",\n border: \"none\",\n },\n outlinedBlue: {\n background: \"transparent\",\n color: \"#2196F3\",\n border: \"#2196F3\",\n },\n outlinedGreen: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"#00BB7E\",\n },\n outlinedBlack: {\n background: \"transparent\",\n color: \"#000000DE\",\n border: \"#000000DE\",\n },\n outlinedGrey: {\n background: \"transparent\",\n color: \"#59676D\",\n border: \"#0B0D0E52\",\n },\n textPrimary: {\n background: \"transparent\",\n color: \"#00BB7E\",\n border: \"transparent\",\n },\n textSecondary: {\n background: \"transparent\",\n color: \"#000000DE\",\n border: \"transparent\",\n },\n textBlue: {\n background: \"transparent\",\n color: \"#2196F3\",\n border: \"transparent\",\n },\n default: {\n background: \"#00BB7E\",\n color: \"#FFF\",\n border: \"#00BB7E\",\n },\n};\n\ninterface AtomButtonProps\n extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"color\">,\n ButtonProps {\n buttonType?: keyof typeof buttonVariants;\n}\n\nexport const AtomButton = styled(Button, {\n shouldForwardProp: (prop) => prop !== \"buttonType\",\n})<AtomButtonProps>(({ buttonType = \"default\" }) => {\n\n return {\n }\n\n});","import * as React from 'react'\nimport { ChatButtonProps } from \"./types\";\nimport IComponent from \"../../../types/component\";\nimport { AtomButton } from \"./styles\";\n\nexport const ChatButton: IComponent<ChatButtonProps> = ({ children = 'Chat', onClick, className, disabled }) => {\n return (\n <AtomButton\n onClick={onClick}\n disabled={disabled}\n className={className}\n style={{\n position: \"fixed\",\n bottom: \"20px\",\n right: \"20px\",\n backgroundColor: \"#007bff\",\n color: \"#fff\",\n display: \"flex\",\n borderRadius: \"50%\",\n width: \"60px\",\n height: \"60px\"\n }}\n >\n {children}\n </AtomButton>\n )\n}\n","import React, { useCallback, useEffect, useState } from \"react\";\nimport {\n Box,\n Button,\n CircularProgress,\n IconButton,\n TextField,\n Typography,\n} from \"@mui/material\";\nimport CloseIcon from \"@mui/icons-material/Close\";\nimport ChatIcon from \"@mui/icons-material/Chat\";\nimport ScheduleIcon from \"@mui/icons-material/Schedule\";\nimport { WebChatConfig, WebChatProps } from \"./types\";\n\nconst DAY_MAP: Record<number, string> = {\n 0: \"SUNDAY\",\n 1: \"MONDAY\",\n 2: \"TUESDAY\",\n 3: \"WEDNESDAY\",\n 4: \"THURSDAY\",\n 5: \"FRIDAY\",\n 6: \"SATURDAY\",\n};\n\nfunction isWithinSchedule(config: WebChatConfig): boolean {\n if (!config.restrictBySchedule || !config.schedule) return true;\n\n const now = new Date();\n const day = DAY_MAP[now.getDay()];\n const time =\n String(now.getHours()).padStart(2, \"0\") +\n \":\" +\n String(now.getMinutes()).padStart(2, \"0\");\n const weekDays = config.schedule.weekDays ?? [\n \"MONDAY\",\n \"TUESDAY\",\n \"WEDNESDAY\",\n \"THURSDAY\",\n \"FRIDAY\",\n ];\n const isWeekday = weekDays.includes(day);\n\n if (isWeekday) {\n const start = config.schedule.weekdaysStart ?? \"07:00\";\n const end = config.schedule.weekdaysEnd ?? \"18:00\";\n return time >= start && time <= end;\n }\n\n const start = config.schedule.weekendStart ?? \"07:00\";\n const end = config.schedule.weekendEnd ?? \"13:00\";\n return time >= start && time <= end;\n}\n\nfunction formatScheduleMessage(config: WebChatConfig): string {\n if (!config.schedule) {\n return \"Nosso horário de atendimento é de segunda à sexta-feira das 07:00h às 18:00h. Sábados, domingos e feriados das 07:00h às 13:00h.\";\n }\n const wdStart = config.schedule.weekdaysStart ?? \"07:00\";\n const wdEnd = config.schedule.weekdaysEnd ?? \"18:00\";\n const weStart = config.schedule.weekendStart ?? \"07:00\";\n const weEnd = config.schedule.weekendEnd ?? \"13:00\";\n return `Nosso horário de atendimento é de segunda à sexta-feira das ${wdStart}h às ${wdEnd}h. Sábados, domingos e feriados das ${weStart}h às ${weEnd}h.`;\n}\n\nexport const WebChat: React.FC<WebChatProps> = ({\n secret,\n apiBaseUrl,\n onStartChat,\n outOfHoursMessage,\n}) => {\n const [config, setConfig] = useState<WebChatConfig | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [open, setOpen] = useState(false);\n const [submitting, setSubmitting] = useState(false);\n const [submitted, setSubmitted] = useState(false);\n\n const [form, setForm] = useState({\n name: \"\",\n email: \"\",\n phone: \"\",\n message: \"\",\n });\n\n const fetchConfig = useCallback(async () => {\n if (!secret || !apiBaseUrl) return;\n setLoading(true);\n setError(null);\n try {\n const base = apiBaseUrl.replace(/\\/$/, \"\");\n const res = await fetch(`${base}/channel/webchat/${encodeURIComponent(secret)}`);\n if (!res.ok) {\n setError(\"Canal não encontrado.\");\n setConfig(null);\n return;\n }\n const data: WebChatConfig = await res.json();\n setConfig(data);\n } catch {\n setError(\"Não foi possível carregar o canal.\");\n setConfig(null);\n } finally {\n setLoading(false);\n }\n }, [secret, apiBaseUrl]);\n\n useEffect(() => {\n fetchConfig();\n }, [fetchConfig]);\n\n const isActive =\n config &&\n (config.status === \"live\" || config.status === \"enable\");\n const outsideHours =\n config && config.restrictBySchedule && !isWithinSchedule(config);\n const showOutOfHours = isActive && outsideHours;\n const showForm = isActive && !outsideHours;\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (submitting || !form.name.trim()) return;\n if (!onStartChat) {\n setError(\"Início de conversa será via WebSocket. Configure onStartChat no componente.\");\n return;\n }\n\n setSubmitting(true);\n try {\n await onStartChat({\n name: form.name.trim(),\n email: form.email.trim(),\n phone: form.phone.trim(),\n message: form.message.trim(),\n });\n setSubmitted(true);\n } catch (err) {\n setError(err instanceof Error ? err.message : \"Erro ao enviar.\");\n } finally {\n setSubmitting(false);\n }\n };\n\n if (!secret) return null;\n\n return (\n <>\n <IconButton\n onClick={() => setOpen((o) => !o)}\n sx={{\n position: \"fixed\",\n bottom: 20,\n right: 20,\n width: 56,\n height: 56,\n bgcolor: \"#007bff\",\n color: \"white\",\n \"&:hover\": { bgcolor: \"#0056b3\" },\n boxShadow: 2,\n }}\n size=\"large\"\n >\n <ChatIcon />\n </IconButton>\n\n {open && (\n <Box\n sx={{\n position: \"fixed\",\n bottom: 90,\n right: 20,\n width: 380,\n maxWidth: \"calc(100vw - 40px)\",\n maxHeight: \"calc(100vh - 120px)\",\n overflow: \"auto\",\n bgcolor: \"background.paper\",\n borderRadius: 2,\n boxShadow: 6,\n zIndex: 1300,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <Box\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n p: 1.5,\n borderBottom: 1,\n borderColor: \"divider\",\n }}\n >\n <Typography variant=\"subtitle1\" fontWeight={600}>\n {config?.name ?? \"Chat\"}\n </Typography>\n <IconButton size=\"small\" onClick={() => setOpen(false)}>\n <CloseIcon />\n </IconButton>\n </Box>\n\n <Box sx={{ p: 2, flex: 1 }}>\n {loading && (\n <Box display=\"flex\" justifyContent=\"center\" py={3}>\n <CircularProgress size={32} />\n </Box>\n )}\n\n {error && !loading && (\n <Typography color=\"error\" variant=\"body2\">\n {error}\n </Typography>\n )}\n\n {!loading && config && !isActive && (\n <Typography color=\"text.secondary\" variant=\"body2\">\n Este canal não está disponível no momento.\n </Typography>\n )}\n\n {showOutOfHours && (\n <Box\n sx={{\n textAlign: \"center\",\n py: 2,\n px: 1,\n bgcolor: \"#1976d2\",\n borderRadius: 1,\n color: \"white\",\n }}\n >\n <ScheduleIcon sx={{ fontSize: 48, opacity: 0.9, mb: 1 }} />\n <Typography variant=\"body1\" sx={{ fontWeight: 500, mb: 1 }}>\n Fora do horário de atendimento\n </Typography>\n <Typography variant=\"body2\" sx={{ opacity: 0.95 }}>\n {outOfHoursMessage ?? formatScheduleMessage(config)}\n </Typography>\n </Box>\n )}\n\n {showForm && !submitted && (\n <form onSubmit={handleSubmit}>\n <Box display=\"flex\" flexDirection=\"column\" gap={2}>\n <TextField\n label=\"Nome\"\n value={form.name}\n onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}\n required\n fullWidth\n size=\"small\"\n />\n <TextField\n label=\"E-mail\"\n type=\"email\"\n value={form.email}\n onChange={(e) => setForm((f) => ({ ...f, email: e.target.value }))}\n fullWidth\n size=\"small\"\n />\n <TextField\n label=\"Telefone\"\n value={form.phone}\n onChange={(e) => setForm((f) => ({ ...f, phone: e.target.value }))}\n fullWidth\n size=\"small\"\n />\n <TextField\n label=\"Mensagem\"\n value={form.message}\n onChange={(e) => setForm((f) => ({ ...f, message: e.target.value }))}\n multiline\n rows={3}\n fullWidth\n size=\"small\"\n />\n <Button\n type=\"submit\"\n variant=\"contained\"\n disabled={submitting || !form.name.trim()}\n fullWidth\n >\n {submitting ? \"Enviando…\" : \"Iniciar chat\"}\n </Button>\n </Box>\n </form>\n )}\n\n {showForm && submitted && (\n <Typography color=\"text.secondary\" variant=\"body2\" sx={{ py: 2 }}>\n Sua mensagem foi enviada. Em breve um atendente responderá.\n </Typography>\n )}\n </Box>\n </Box>\n )}\n </>\n );\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synchat/webchat",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "description": "Starter de biblioteca de componentes React + TypeScript com tsup.",
5
5
  "author": "synchat <contato@synchat.com.br>",
6
6
  "license": "MIT",
@@ -34,19 +34,25 @@
34
34
  "component-library",
35
35
  "tsup"
36
36
  ],
37
- "dependencies": {
37
+ "peerDependencies": {
38
+ "@emotion/react": ">=11",
39
+ "@emotion/styled": ">=11",
40
+ "@mui/icons-material": ">=5",
41
+ "@mui/material": ">=5",
42
+ "react": ">=18",
43
+ "react-dom": ">=18"
44
+ },
45
+ "devDependencies": {
38
46
  "@emotion/react": "^11.14.0",
39
47
  "@emotion/styled": "^11.14.1",
40
48
  "@mui/icons-material": "^7.3.5",
41
49
  "@mui/material": "^7.3.5",
42
- "react": "19.2.0",
43
- "react-dom": "19.2.0"
44
- },
45
- "devDependencies": {
46
50
  "@types/react": "^18.3.0",
47
51
  "@types/react-dom": "^18.3.0",
52
+ "react": "19.2.0",
53
+ "react-dom": "19.2.0",
48
54
  "rimraf": "^6.0.0",
49
55
  "tsup": "^8.0.1",
50
56
  "typescript": "^5.6.0"
51
57
  }
52
- }
58
+ }