@adatechnology/conversations-ui 0.1.0-rc.2 → 0.1.0-rc.20

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.
Files changed (99) hide show
  1. package/dist/{chunk-ZDURDZTM.js → chunk-2AYDBWNE.js} +14 -0
  2. package/dist/chunk-OIDAIVCH.js +1985 -0
  3. package/dist/flows/index.d.ts +14 -2
  4. package/dist/flows/index.js +117 -39
  5. package/dist/index.d.ts +729 -136
  6. package/dist/index.js +1418 -1104
  7. package/dist/preview/index.d.ts +373 -0
  8. package/dist/preview/index.js +1247 -0
  9. package/dist/styles.css +198 -0
  10. package/dist/types-O7kMP1Yn.d.ts +416 -0
  11. package/package.json +10 -3
  12. package/src/AudioRecorderButton.test.tsx +30 -0
  13. package/src/AudioRecorderButton.tsx +248 -0
  14. package/src/Avatar.tsx +30 -4
  15. package/src/ChannelIcon.tsx +87 -0
  16. package/src/ConversationContextPanel.tsx +127 -0
  17. package/src/ConversationDocumentsPanel.tsx +425 -0
  18. package/src/ConversationHeader.tsx +257 -0
  19. package/src/ConversationListItem.tsx +54 -7
  20. package/src/ConversationLocalesProvider.tsx +16 -0
  21. package/src/ConversationRow.tsx +137 -0
  22. package/src/DateDivider.tsx +16 -3
  23. package/src/DocumentsLibrary.tsx +322 -0
  24. package/src/EmojiPicker.tsx +69 -55
  25. package/src/FileIcon.test.ts +83 -0
  26. package/src/FileIcon.tsx +88 -11
  27. package/src/InteractiveMessage.test.tsx +41 -0
  28. package/src/InteractiveMessage.tsx +143 -0
  29. package/src/Lightbox.tsx +18 -3
  30. package/src/MediaRenderer.tsx +64 -21
  31. package/src/MessageBubble.tsx +54 -5
  32. package/src/MessageComposer.test.tsx +35 -0
  33. package/src/MessageComposer.tsx +146 -19
  34. package/src/RichMessageComposer.test.tsx +83 -0
  35. package/src/RichMessageComposer.tsx +380 -0
  36. package/src/Wallpaper.test.tsx +21 -0
  37. package/src/Wallpaper.tsx +54 -6
  38. package/src/WhatsAppMessageEditor.tsx +28 -4
  39. package/src/WindowExpiredNotice.tsx +57 -0
  40. package/src/audioRecorderFormat.test.ts +67 -0
  41. package/src/conversationChannel.test.ts +53 -0
  42. package/src/conversationChannel.ts +146 -0
  43. package/src/conversationTranscript.test.ts +65 -0
  44. package/src/conversationTranscript.ts +64 -0
  45. package/src/conversationWindow.test.ts +90 -0
  46. package/src/conversationWindow.ts +78 -0
  47. package/src/documentTypeLabel.test.ts +57 -0
  48. package/src/emojiCatalog.test.ts +35 -0
  49. package/src/emojiCatalog.ts +189 -0
  50. package/src/flows/FlowGroupHeader.tsx +12 -2
  51. package/src/flows/FlowMapCanvas.tsx +17 -14
  52. package/src/flows/FlowMapNode.tsx +3 -1
  53. package/src/flows/FlowNodeCard.tsx +22 -4
  54. package/src/flows/FlowNodePanel.tsx +132 -35
  55. package/src/flows/FlowPalette.tsx +6 -2
  56. package/src/flows/FlowWhatsAppPreview.tsx +14 -3
  57. package/src/flows/flowGraph.ts +5 -5
  58. package/src/flows/labels.ts +5 -0
  59. package/src/hooks/useConversationActions.ts +56 -0
  60. package/src/hooks/useConversationDocuments.ts +15 -9
  61. package/src/hooks/useConversationList.ts +15 -9
  62. package/src/hooks/useConversationMessages.ts +2 -2
  63. package/src/index.ts +129 -16
  64. package/src/lib/cn.test.ts +29 -0
  65. package/src/lib/cn.ts +15 -0
  66. package/src/lib/createMediaUrlResolver.ts +33 -0
  67. package/src/lib/paginated.test.ts +33 -0
  68. package/src/lib/paginated.ts +26 -0
  69. package/src/lib/phone.ts +34 -0
  70. package/src/preview/ConversationPreview.tsx +325 -0
  71. package/src/preview/MediaTypesPreview.tsx +87 -0
  72. package/src/preview/conversationPreviewFailures.test.ts +64 -0
  73. package/src/preview/createMockConversationsApi.ts +271 -0
  74. package/src/preview/createMockSSEProvider.ts +40 -0
  75. package/src/preview/createPreviewBridgeClient.test.ts +92 -0
  76. package/src/preview/createPreviewBridgeClient.ts +88 -0
  77. package/src/preview/createPreviewWebhookClient.test.ts +105 -0
  78. package/src/preview/createPreviewWebhookClient.ts +131 -0
  79. package/src/preview/index.ts +61 -0
  80. package/src/preview/mediaTypeOf.test.ts +15 -0
  81. package/src/preview/mockDocumentsSearch.test.ts +57 -0
  82. package/src/preview/mockEventSource.ts +53 -0
  83. package/src/preview/preview.test.ts +177 -0
  84. package/src/preview/previewFileSamples.test.ts +151 -0
  85. package/src/preview/previewFileSamples.ts +74 -0
  86. package/src/preview/previewFixtures.ts +440 -0
  87. package/src/preview/previewMediaSource.test.ts +62 -0
  88. package/src/preview/previewMediaSource.ts +91 -0
  89. package/src/preview/previewStore.ts +193 -0
  90. package/src/preview/startPreviewScript.ts +60 -0
  91. package/src/providers/types.ts +163 -11
  92. package/src/quickReply.test.ts +58 -0
  93. package/src/settings/WhatsAppCreateTemplateForm.tsx +3 -1
  94. package/src/settings/WhatsAppTemplatesSettings.tsx +106 -0
  95. package/src/styles.css +136 -0
  96. package/src/types.ts +46 -1
  97. package/src/useDarkMode.ts +26 -0
  98. package/src/useIsNarrow.ts +29 -0
  99. package/src/useWaitingNotifications.ts +74 -29
@@ -0,0 +1,373 @@
1
+ import { G as MessagePayload, o as ConversationSummary, m as ConversationEventSource, q as ConversationsApi, L as ListConversationsParams, n as ConversationPage, S as SSEProvider, k as ConversationDocument, K as ResolveMediaUrl } from '../types-O7kMP1Yn.js';
2
+ export { A as AudioRecorderButton, a as AudioRecorderButtonLabels, b as AudioRecorderButtonProps, D as DEFAULT_AUDIO_RECORDER_BUTTON_LABELS } from '../types-O7kMP1Yn.js';
3
+ import * as react from 'react';
4
+ import { InteractiveReplyOption, InboundMediaType } from '@adatechnology/meta-whatsapp-contracts/testing';
5
+
6
+ /**
7
+ * Estado em memória que alimenta o preview de atendimento humano. Mock de API e mock de SSE
8
+ * compartilham este store de propósito: se cada um tivesse dados próprios, um evento anunciaria
9
+ * mensagem nova e o refetch da lista devolveria o estado antigo — a inbox pareceria funcionar e
10
+ * estaria mentindo, que é exatamente o defeito que o preview deveria expor.
11
+ *
12
+ * Os nomes de canal e de evento espelham o servidor (`conv:<whatsappNumber>`, `global`,
13
+ * `message`/`message-status`/`mode-changed`/`data-changed`). Fidelidade de vocabulário é o que
14
+ * permite trocar mock por servidor real sem tocar na UI.
15
+ */
16
+
17
+ declare const GLOBAL_CHANNEL = "global";
18
+ declare function conversationChannel(conversationId: string): string;
19
+ type PreviewEmission = {
20
+ readonly channel: string;
21
+ readonly event: string;
22
+ readonly payload: Record<string, unknown>;
23
+ };
24
+ type PreviewStoreListener = (emission: PreviewEmission) => void;
25
+ type AppendMessageParams = {
26
+ readonly conversationId: string;
27
+ readonly content: string;
28
+ readonly direction: MessagePayload['direction'];
29
+ readonly sender: MessagePayload['sender'];
30
+ };
31
+ type SetModeParams = {
32
+ readonly conversationId: string;
33
+ readonly mode: ConversationSummary['mode'];
34
+ readonly assignedUserId?: string | undefined;
35
+ };
36
+ type ListConversationsFilters = {
37
+ readonly waitingHuman?: boolean;
38
+ readonly search?: string;
39
+ };
40
+ type PreviewStore = {
41
+ listConversations(filters?: ListConversationsFilters): ConversationSummary[];
42
+ listMessages(conversationId: string): MessagePayload[];
43
+ appendMessage(params: AppendMessageParams): MessagePayload;
44
+ setMode(params: SetModeParams): void;
45
+ requestHuman(conversationId: string): void;
46
+ markRead(conversationId: string): void;
47
+ subscribe(channel: string, listener: PreviewStoreListener): () => void;
48
+ };
49
+ type CreatePreviewStoreParams = {
50
+ readonly conversations: readonly ConversationSummary[];
51
+ readonly messages: Readonly<Record<string, readonly MessagePayload[]>>;
52
+ readonly now?: () => Date;
53
+ };
54
+ declare function createPreviewStore(params: CreatePreviewStoreParams): PreviewStore;
55
+
56
+ /**
57
+ * `EventSource` só existe com um servidor HTTP do outro lado — é justamente o que falta quando se
58
+ * quer a inbox rodando com dados mockados. Este é o objeto mínimo que satisfaz
59
+ * `ConversationEventSource`: assina eventos nomeados, desassina e fecha.
60
+ *
61
+ * Não imita `EventSource` por completo de propósito: um fake "quase real" convida a depender de
62
+ * membros que o pacote não usa, e passa a quebrar a cada mudança de runtime.
63
+ */
64
+
65
+ type MockEventSource = ConversationEventSource & {
66
+ emit(event: string, payload: unknown): void;
67
+ readonly closed: boolean;
68
+ };
69
+ declare function createMockEventSource(): MockEventSource;
70
+
71
+ /**
72
+ * `ConversationsApi` servido pelo store em memória. Como o pacote é headless e recebe a API por
73
+ * injeção, o preview de atendimento humano não precisa de servidor, banco nem Meta: é só outra
74
+ * implementação deste mesmo contrato.
75
+ *
76
+ * Toda resposta é assíncrona e passa por um atraso configurável — API instantânea esconde estados
77
+ * de carregamento, e é neles que a inbox costuma mostrar defeito.
78
+ */
79
+
80
+ type CreateMockConversationsApiParams = {
81
+ readonly store: PreviewStore;
82
+ readonly latencyMs?: number;
83
+ readonly agentName?: string;
84
+ };
85
+ /**
86
+ * O mock satisfaz `ConversationsApi`, mas com o retorno de `fetchConversations` ESTREITADO para a
87
+ * forma paginada. Sem isto o contrato — que aceita array ou página — obrigaria todo consumidor do
88
+ * preview a desempacotar uma união que aqui nunca varia.
89
+ */
90
+ type MockConversationsApi = Omit<ConversationsApi, 'fetchConversations'> & {
91
+ fetchConversations(params?: ListConversationsParams): Promise<ConversationPage>;
92
+ };
93
+ declare function createMockConversationsApi(params: CreateMockConversationsApiParams): MockConversationsApi;
94
+
95
+ /**
96
+ * `SSEProvider` servido pelo store em memória. Mesmo mapeamento de canal do servidor
97
+ * (`conv:<conversationId>` e `global`), para que a UI não perceba a troca.
98
+ */
99
+
100
+ type CreateMockSSEProviderParams = {
101
+ readonly store: PreviewStore;
102
+ };
103
+ declare function createMockSSEProvider(params: CreateMockSSEProviderParams): SSEProvider;
104
+
105
+ /**
106
+ * Conversas de partida do preview. Cobrem o espaço de estados que a inbox precisa saber desenhar —
107
+ * bot em atendimento, cliente esperando humano, conversa já assumida por atendente, conversa com
108
+ * áudio — porque estado que não aparece em fixture é estado que ninguém testa.
109
+ */
110
+
111
+ declare const PREVIEW_CONVERSATIONS: readonly ConversationSummary[];
112
+ declare const PREVIEW_MESSAGES: Readonly<Record<string, readonly MessagePayload[]>>;
113
+ declare const PREVIEW_DOCUMENTS: Readonly<Record<string, readonly ConversationDocument[]>>;
114
+
115
+ /**
116
+ * Cliente que entrega mensagens do preview no webhook real, assinadas com HMAC — a mesma validação
117
+ * de staging e produção, sem rota alternativa e sem bypass. Do ponto de vista da API, este cliente
118
+ * é indistinguível da Meta; o que muda é apenas quem assina.
119
+ *
120
+ * Assina com WebCrypto porque `node:crypto` não existe no navegador. Os builders vêm dos contratos
121
+ * (isomórficos) justamente para que o mesmo payload seja montado nos dois runtimes.
122
+ *
123
+ * ⚠️ SOMENTE EXECUÇÃO LOCAL. Isto carrega o app secret no bundle, e bundle é público onde quer que
124
+ * seja servido — em qualquer ambiente com URL acessível (homologação inclusive) usar esta fábrica
125
+ * equivale a publicar o segredo, e quem o tiver forja webhooks válidos daquele app da Meta: injeta
126
+ * mensagem de qualquer número e dispara os fluxos. `assertPreviewEnvironment` barra produção, mas
127
+ * homologação passaria, então a barreira não basta.
128
+ *
129
+ * Para qualquer ambiente publicado use `createPreviewBridgeClient`: o navegador manda a intenção e
130
+ * o servidor assina com o segredo que ele já tem.
131
+ */
132
+
133
+ type PreviewWebhookClient = {
134
+ sendText(text: string): Promise<void>;
135
+ sendButtonReply(reply: InteractiveReplyOption): Promise<void>;
136
+ sendListReply(reply: InteractiveReplyOption): Promise<void>;
137
+ sendAudio(mediaId: string): Promise<void>;
138
+ sendMedia(params: SendPreviewMediaParams): Promise<void>;
139
+ };
140
+ type SendPreviewMediaParams = {
141
+ readonly mediaType: InboundMediaType;
142
+ /**
143
+ * Id que o host já usa para buscar o arquivo. Não é bytes: o webhook da Meta entrega mídia por
144
+ * referência, e o consumidor baixa depois — mandar base64 aqui simularia um payload que a Meta
145
+ * nunca produz, e o caminho testado deixaria de ser o de produção.
146
+ */
147
+ readonly mediaId: string;
148
+ readonly mimeType?: string;
149
+ readonly filename?: string;
150
+ readonly caption?: string;
151
+ };
152
+ type CreatePreviewWebhookClientParams = {
153
+ readonly webhookUrl: string;
154
+ readonly appSecret: string;
155
+ readonly from: string;
156
+ readonly phoneNumberId?: string;
157
+ readonly fetchImplementation?: typeof fetch;
158
+ };
159
+ declare class PreviewInProductionError extends Error {
160
+ constructor();
161
+ }
162
+ declare class PreviewWebhookRejectedError extends Error {
163
+ readonly status: number;
164
+ constructor(status: number);
165
+ }
166
+ /**
167
+ * Falha alto em vez de degradar em silêncio: um preview que "quase funciona" em produção é pior
168
+ * que um que se recusa a montar.
169
+ */
170
+ declare function assertPreviewEnvironment(isProduction: boolean): void;
171
+ /**
172
+ * Assina um texto qualquer com o app secret, no mesmo formato do header da Meta.
173
+ *
174
+ * Exportada porque o preview precisa provar identidade em MAIS de um lugar: além de entregar a
175
+ * mensagem no webhook, ele lê o transcript de volta — e ler pela API de admin exigia uma sessão que
176
+ * a aba do simulador não tem. Assinar a leitura com o segredo que ele já carrega resolve sem token
177
+ * de admin e sem rota aberta.
178
+ */
179
+ declare function signPreviewPayload(params: {
180
+ rawBody: string;
181
+ appSecret: string;
182
+ }): Promise<string>;
183
+ declare function createPreviewWebhookClient(params: CreatePreviewWebhookClientParams): PreviewWebhookClient;
184
+
185
+ type ConversationPreviewProps = {
186
+ client: PreviewWebhookClient;
187
+ sse: SSEProvider;
188
+ conversationId: string;
189
+ loadMessages: (conversationId: string) => Promise<MessagePayload[]>;
190
+ placeholder?: string;
191
+ /**
192
+ * Recarrega o transcript a cada N ms. Serve a host SEM stream: a resposta do bot é assíncrona, e
193
+ * sem SSE nem polling ela só apareceria no próximo envio — o sintoma é "às vezes ele não
194
+ * responde". Ausente, não faz polling (host com SSE não precisa).
195
+ */
196
+ pollIntervalMs?: number;
197
+ /**
198
+ * Como transformar um arquivo do disco (ou o áudio gravado) na referência que o webhook carrega.
199
+ * O caminho da Meta entrega mídia por `id`, e quem sabe hospedar o arquivo é o host — a SDK não
200
+ * inventa um endpoint de upload. Ausente, o compositor não oferece anexo nem gravação: melhor um
201
+ * botão que não existe do que um que falha ao ser tocado.
202
+ */
203
+ uploadMedia?: (file: File) => Promise<PreviewUploadedMedia>;
204
+ };
205
+ type PreviewUploadedMedia = {
206
+ readonly mediaId: string;
207
+ readonly mimeType?: string;
208
+ readonly filename?: string;
209
+ };
210
+ /** Deriva o tipo de mídia do WhatsApp a partir do MIME do arquivo escolhido. */
211
+ declare function mediaTypeOf(mimeType: string): SendPreviewMediaParams['mediaType'];
212
+ declare function ConversationPreview({ client, sse, conversationId, loadMessages, placeholder, pollIntervalMs, uploadMedia, }: ConversationPreviewProps): react.JSX.Element;
213
+
214
+ /**
215
+ * Cliente do preview que NÃO carrega segredo: em vez de montar e assinar o payload da Meta no
216
+ * navegador, manda um comando semântico (`{ kind: 'text', text }`) para uma rota do próprio host,
217
+ * autenticada pela sessão que o painel já tem. Quem monta o payload e assina é o servidor, com o
218
+ * app secret que nunca sai de lá.
219
+ *
220
+ * Por que esta fábrica existe ao lado de `createPreviewWebhookClient`: assinar no navegador exige o
221
+ * app secret dentro do bundle, e bundle é público por definição — em qualquer ambiente com URL
222
+ * acessível isso é o mesmo que publicar o segredo. Com o segredo vazado, qualquer um forja webhooks
223
+ * válidos daquele app: injeta mensagens de qualquer número e dispara os fluxos. `createPreviewWebhook
224
+ * Client` continua servindo para execução puramente local (docker de dev, onde o bundle não é
225
+ * servido para ninguém); para qualquer ambiente publicado, a ponte é o caminho.
226
+ *
227
+ * O pacote não decide autenticação: o host injeta `sendCommand` (ou `headers` + `fetchImplementation`),
228
+ * porque token, cookie e cabeçalho de sessão são do produto, não da biblioteca.
229
+ */
230
+
231
+ /**
232
+ * Comando semântico entregue ao host. É deliberadamente o QUE o cliente fez, não o payload da Meta:
233
+ * se o navegador mandasse o payload pronto, a rota viraria um injetor de webhook arbitrário para
234
+ * quem tivesse sessão. Mandando a intenção, o servidor é quem escolhe a forma.
235
+ */
236
+ type PreviewInboundCommand = {
237
+ readonly kind: 'text';
238
+ readonly from: string;
239
+ readonly text: string;
240
+ } | {
241
+ readonly kind: 'buttonReply';
242
+ readonly from: string;
243
+ readonly reply: InteractiveReplyOption;
244
+ } | {
245
+ readonly kind: 'listReply';
246
+ readonly from: string;
247
+ readonly reply: InteractiveReplyOption;
248
+ } | {
249
+ readonly kind: 'audio';
250
+ readonly from: string;
251
+ readonly mediaId: string;
252
+ } | ({
253
+ readonly kind: 'media';
254
+ readonly from: string;
255
+ } & SendPreviewMediaParams);
256
+ type SendPreviewInboundCommand = (command: PreviewInboundCommand) => Promise<void>;
257
+ declare class PreviewBridgeRejectedError extends Error {
258
+ readonly status: number;
259
+ constructor(status: number);
260
+ }
261
+ type CreatePreviewBridgeClientParams = {
262
+ readonly from: string;
263
+ /**
264
+ * Entrega o comando. Use quando o host já tem um cliente HTTP com sessão, interceptors e refresh
265
+ * de token — reimplementar isso aqui só duplicaria a autenticação do produto.
266
+ */
267
+ readonly sendCommand?: SendPreviewInboundCommand;
268
+ /** Alternativa a `sendCommand` para hosts sem cliente HTTP próprio. */
269
+ readonly endpointUrl?: string;
270
+ readonly headers?: Readonly<Record<string, string>>;
271
+ readonly fetchImplementation?: typeof fetch;
272
+ };
273
+ declare function createPreviewBridgeClient(params: CreatePreviewBridgeClientParams): PreviewWebhookClient;
274
+
275
+ /**
276
+ * Roteiro que mantém o preview vivo: sem tráfego chegando, a inbox é uma tela estática e as
277
+ * transições que o atendente precisa testar (fila de espera enchendo, handoff, devolução ao bot)
278
+ * nunca acontecem.
279
+ *
280
+ * O roteiro é cíclico e determinístico — mesma ordem a cada execução. Aleatoriedade tornaria um
281
+ * defeito visto uma vez difícil de reencontrar.
282
+ */
283
+
284
+ type PreviewScriptStep = (store: PreviewStore) => void;
285
+ declare const DEFAULT_PREVIEW_SCRIPT: readonly PreviewScriptStep[];
286
+ type StartPreviewScriptParams = {
287
+ readonly store: PreviewStore;
288
+ readonly intervalMs?: number;
289
+ readonly steps?: readonly PreviewScriptStep[];
290
+ };
291
+ declare function startPreviewScript(params: StartPreviewScriptParams): () => void;
292
+
293
+ /**
294
+ * Bytes de verdade para o preview abrir.
295
+ *
296
+ * O mock antes devolvia a MESMA imagem PNG para qualquer documento, então clicar em "visualizar" num
297
+ * PDF entregava um PNG rotulado `application/pdf` e o leitor dizia que o arquivo era inválido. Cada
298
+ * amostra aqui é um arquivo mínimo porém legítimo do seu tipo: as de mídia foram geradas com ffmpeg
299
+ * e conferidas com ffprobe, o PDF tem xref/startxref/%%EOF, e os pacotes Office são zips com as
300
+ * partes obrigatórias (`[Content_Types].xml`, `_rels/.rels`, o documento).
301
+ *
302
+ * Não há amostra de `audio/amr`, `video/3gp` nem dos formatos binários legados do Office
303
+ * (`application/msword`, `application/vnd.ms-excel`, `application/vnd.ms-powerpoint`): não há
304
+ * encoder para eles nesta máquina e forjar OLE2 à mão daria arquivo corrompido — exatamente o que
305
+ * este módulo existe para evitar. Esses caem no texto explicativo de `resolvePreviewFileSample`,
306
+ * que abre sem erro e diz o que é.
307
+ *
308
+ * GERADO — não editar à mão.
309
+ */
310
+ declare const PREVIEW_FILE_SAMPLES: Readonly<Record<string, string>>;
311
+ /**
312
+ * A data URL que o preview abre para um documento.
313
+ *
314
+ * Ordem: tipo exato → família (`audio/amr` toca como mp3, `video/3gp` como mp4) → nota em texto.
315
+ * A nota fecha o caso dos tipos sem amostra: abre num leitor de texto e explica, em vez de baixar
316
+ * um binário quebrado com extensão de Word.
317
+ */
318
+ declare function resolvePreviewFileSample(mimeType: string | undefined, filename?: string): string;
319
+
320
+ /**
321
+ * Como o preview entrega mídia para a UI abrir.
322
+ *
323
+ * Separado de `previewFileSamples` (que é gerado) porque aqui está a parte que depende do navegador:
324
+ * **blob URL, não data URL**. O Chrome bloqueia navegação de topo para `data:` desde a v60, então
325
+ * `window.open(dataUrl)` — que é o que os botões "visualizar" e "baixar" fazem — abre aba em branco
326
+ * mesmo com bytes perfeitamente válidos. Em `src` de `<img>`/`<video>` a data URL funcionaria; no
327
+ * `window.open` não, e o mesmo `getDocumentUrl` alimenta os dois.
328
+ */
329
+
330
+ /** URL que o preview pode abrir em aba nova. Cai na data URL fora do navegador (teste, SSR). */
331
+ declare function previewFileUrl(mimeType: string | undefined, filename?: string): string;
332
+ /**
333
+ * A mesma amostra em base64 cru, como o proxy de mídia do backend a devolveria.
334
+ *
335
+ * Existe porque `getMediaProxyUrl` é o caminho da mídia AINDA NÃO ingerida (só existe o id na Meta),
336
+ * e o contrato pede `{ mimeType, data }` — não URL. Sem isto o mock devolvia o PNG 1x1 para
337
+ * qualquer id, e vídeo e áudio da thread apareciam quebrados apesar de haver amostra válida.
338
+ */
339
+ declare function previewFileBase64(mimeType: string | undefined, filename?: string): {
340
+ mimeType: string;
341
+ data: string;
342
+ };
343
+ /**
344
+ * O `onResolveMediaUrl` que o `MessageBubble` espera.
345
+ *
346
+ * Sem ele, foto, vídeo e áudio da thread ficam parados no placeholder para sempre — o
347
+ * `MediaRenderer` só resolve `uploadId`/`mediaId` por esta porta, de propósito, para o pacote nunca
348
+ * chamar endpoint fixo. O preview não tinha resolvedor nenhum, então nenhuma mídia carregava.
349
+ */
350
+ declare function createPreviewMediaResolver(): ResolveMediaUrl;
351
+
352
+ /**
353
+ * Bancada de teste manual de mídia — montável em uma linha por qualquer projeto que adote o SDK.
354
+ *
355
+ * Existe porque o defeito que ela pega não é pegável por teste automatizado: "o PDF abre?" depende
356
+ * do leitor do navegador, "o vídeo toca?" do decodificador, e "a aba abre?" da política do Chrome
357
+ * sobre `data:` URL. Teste unitário confere bytes; só o olho confere que o arquivo abre. Sem uma
358
+ * superfície pronta no pacote, cada projeto teria de montar a sua — e, na prática, nenhum montava.
359
+ *
360
+ * Traz o próprio store, o próprio mock e o próprio provider: o host não injeta nada. E não passa
361
+ * `onResolveMediaUrl` em lugar nenhum de propósito — é o `MessageBubble` resolvendo mídia pelo
362
+ * `ConversationsApi` do contexto, então se essa resolução automática quebrar, esta tela mostra.
363
+ */
364
+ /** A conversa do fixture que carrega uma mensagem de cada tipo aceito. */
365
+ declare const MEDIA_TYPES_CONVERSATION_ID = "5511944443333";
366
+ type MediaTypesPreviewProps = {
367
+ /** Outra conversa do fixture, se o projeto tiver acrescentado a sua. */
368
+ conversationId?: string;
369
+ className?: string;
370
+ };
371
+ declare function MediaTypesPreview({ conversationId, className, }: MediaTypesPreviewProps): react.JSX.Element;
372
+
373
+ export { type AppendMessageParams, ConversationPreview, type ConversationPreviewProps, type CreateMockConversationsApiParams, type CreateMockSSEProviderParams, type CreatePreviewBridgeClientParams, type CreatePreviewStoreParams, type CreatePreviewWebhookClientParams, DEFAULT_PREVIEW_SCRIPT, GLOBAL_CHANNEL, type ListConversationsFilters, MEDIA_TYPES_CONVERSATION_ID, MediaTypesPreview, type MediaTypesPreviewProps, type MockEventSource, PREVIEW_CONVERSATIONS, PREVIEW_DOCUMENTS, PREVIEW_FILE_SAMPLES, PREVIEW_MESSAGES, PreviewBridgeRejectedError, type PreviewEmission, PreviewInProductionError, type PreviewInboundCommand, type PreviewScriptStep, type PreviewStore, type PreviewStoreListener, type PreviewUploadedMedia, type PreviewWebhookClient, PreviewWebhookRejectedError, type SendPreviewInboundCommand, type SendPreviewMediaParams, type SetModeParams, type StartPreviewScriptParams, assertPreviewEnvironment, conversationChannel, createMockConversationsApi, createMockEventSource, createMockSSEProvider, createPreviewBridgeClient, createPreviewMediaResolver, createPreviewStore, createPreviewWebhookClient, mediaTypeOf, previewFileBase64, previewFileUrl, resolvePreviewFileSample, signPreviewPayload, startPreviewScript };