@adatechnology/conversations-ui 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/README.md +106 -0
  2. package/dist/{ConversationSimulatorPanel-q-wVgBCN.d.ts → ConversationSimulatorPanel-P6eqTSAO.d.ts} +1 -16
  3. package/dist/{chunk-HMCOTZAX.js → chunk-NSOAUYNE.js} +33 -28
  4. package/dist/{chunk-O6457XHK.js → chunk-WCZNIJ3M.js} +16 -1
  5. package/dist/{chunk-L3OFAQPS.js → chunk-Y326LLEP.js} +4 -14
  6. package/dist/chunk-ZSOD5AQT.js +19 -0
  7. package/dist/flows/index.js +4 -2
  8. package/dist/index.d.ts +10 -3
  9. package/dist/index.js +8 -6
  10. package/dist/participant/index.d.ts +54 -3
  11. package/dist/participant/index.js +1722 -418
  12. package/dist/preview/index.d.ts +2 -2
  13. package/dist/preview/index.js +2 -2
  14. package/dist/styles.css +281 -23
  15. package/package.json +3 -2
  16. package/src/AudioRecorderButton.tsx +4 -28
  17. package/src/Tooltip.tsx +5 -12
  18. package/src/TooltipDom.test.tsx +78 -0
  19. package/src/audioRecorderFormat.ts +27 -0
  20. package/src/domHarness.test-helper.ts +53 -0
  21. package/src/participant/ConversationThread.tsx +4 -0
  22. package/src/participant/ParticipantAttachmentItem.tsx +7 -10
  23. package/src/participant/ParticipantAudioAttachment.tsx +34 -0
  24. package/src/participant/ParticipantAudioPlayer.tsx +68 -0
  25. package/src/participant/ParticipantAudioPlayerControls.tsx +68 -0
  26. package/src/participant/ParticipantAudioRecorderView.tsx +55 -0
  27. package/src/participant/ParticipantAudioTranscription.tsx +90 -0
  28. package/src/participant/ParticipantBackButton.tsx +1 -1
  29. package/src/participant/ParticipantBubbleBody.tsx +54 -0
  30. package/src/participant/ParticipantBubbleStatus.tsx +22 -28
  31. package/src/participant/ParticipantChannelBadges.tsx +10 -2
  32. package/src/participant/ParticipantComposer.tsx +51 -16
  33. package/src/participant/ParticipantComposerAudio.tsx +95 -0
  34. package/src/participant/ParticipantComposerControls.tsx +2 -0
  35. package/src/participant/ParticipantConversations.tsx +3 -0
  36. package/src/participant/ParticipantCopyableToken.tsx +1 -0
  37. package/src/participant/ParticipantFailedMenu.tsx +40 -0
  38. package/src/participant/ParticipantFailedMenuList.tsx +41 -0
  39. package/src/participant/ParticipantMessageBubble.test.tsx +6 -6
  40. package/src/participant/ParticipantMessageBubble.tsx +20 -52
  41. package/src/participant/ParticipantMessageText.test.tsx +1 -1
  42. package/src/participant/ParticipantMessageText.tsx +4 -2
  43. package/src/participant/ParticipantProtocolBadge.tsx +1 -0
  44. package/src/participant/ParticipantRecorderParts.tsx +118 -0
  45. package/src/participant/ParticipantScrollToLatest.tsx +1 -1
  46. package/src/participant/ParticipantThread.tsx +30 -12
  47. package/src/participant/ParticipantThreadHeader.test.tsx +1 -1
  48. package/src/participant/ParticipantThreadScreen.tsx +1 -0
  49. package/src/participant/failedMenuKeyboard.ts +29 -0
  50. package/src/participant/index.ts +3 -0
  51. package/src/participant/participantAudio.types.ts +10 -0
  52. package/src/participant/participantAudioCapture.test.ts +15 -0
  53. package/src/participant/participantAudioCapture.ts +85 -0
  54. package/src/participant/participantAudioCoordinator.ts +13 -0
  55. package/src/participant/participantAudioFormat.test.ts +93 -0
  56. package/src/participant/participantAudioFormat.ts +72 -0
  57. package/src/participant/participantAudioGolden.test.tsx +168 -0
  58. package/src/participant/participantAudioLabels.test.ts +22 -0
  59. package/src/participant/participantAudioLabels.ts +76 -0
  60. package/src/participant/participantAudioPlayerControlsDom.test.tsx +123 -0
  61. package/src/participant/participantAudioPlayerCss.test.ts +63 -0
  62. package/src/participant/participantAudioPlayerDom.test.tsx +154 -0
  63. package/src/participant/participantAudioPlayerDomKit.test-helper.tsx +84 -0
  64. package/src/participant/participantAudioPlayerState.ts +35 -0
  65. package/src/participant/participantAudioRecorderDom.test.tsx +127 -0
  66. package/src/participant/participantAudioRecorderInterruptionDom.test.tsx +135 -0
  67. package/src/participant/participantAudioRecorderSpecDom.test.tsx +110 -0
  68. package/src/participant/participantAudioRecorderState.test.ts +144 -0
  69. package/src/participant/participantAudioRecorderState.ts +93 -0
  70. package/src/participant/participantAudioRecorderView.test.tsx +98 -0
  71. package/src/participant/participantAudioSupport.ts +36 -0
  72. package/src/participant/participantAudioTranscriptionDom.test.tsx +198 -0
  73. package/src/participant/participantComposerAudioDom.test.tsx +185 -0
  74. package/src/participant/participantComposerAudioGolden.test.tsx +68 -0
  75. package/src/participant/participantComposerAudioSsr.test.tsx +74 -0
  76. package/src/participant/participantFailedMenuDom.test.tsx +154 -0
  77. package/src/participant/participantFailedMenuState.test.ts +61 -0
  78. package/src/participant/participantFailedMenuState.ts +57 -0
  79. package/src/participant/participantFailedMessage.test.tsx +83 -0
  80. package/src/participant/participantFileValidation.ts +1 -1
  81. package/src/participant/participantGolden.test.tsx +2 -0
  82. package/src/participant/participantGoldenScenarios.test-helper.tsx +14 -1
  83. package/src/participant/participantLabels.ts +10 -1
  84. package/src/participant/participantMediaFakes.test-helper.ts +82 -0
  85. package/src/participant/participantNoMicrophoneDom.test.tsx +44 -0
  86. package/src/participant/participantPublicTypes.test.ts +11 -0
  87. package/src/participant/participantRecorderDomKit.test-helper.tsx +131 -0
  88. package/src/participant/participantRecorderFakes.test-helper.ts +47 -0
  89. package/src/participant/participantSpecRecorderFake.test-helper.ts +52 -0
  90. package/src/participant/participantThemeContrast.test.ts +17 -0
  91. package/src/participant/participantTooltips.test.tsx +74 -0
  92. package/src/participant/test-fixtures/composer-audio-denied.golden.html +1 -0
  93. package/src/participant/test-fixtures/composer-audio-idle.golden.html +1 -0
  94. package/src/participant/test-fixtures/composer-audio-recording.golden.html +1 -0
  95. package/src/participant/test-fixtures/composer-audio-review.golden.html +1 -0
  96. package/src/participant/test-fixtures/thread-audio-native.golden.html +1 -0
  97. package/src/participant/test-fixtures/thread-audio-player.golden.html +1 -0
  98. package/src/participant/test-fixtures/thread-audio-transcription-empty.golden.html +1 -0
  99. package/src/participant/test-fixtures/thread-audio-transcription-pending.golden.html +1 -0
  100. package/src/participant/test-fixtures/thread-audio-transcription-ready.golden.html +1 -0
  101. package/src/participant/test-fixtures/thread-audio-transcription-too_long.golden.html +1 -0
  102. package/src/participant/test-fixtures/thread-avatars-initials.golden.html +1 -1
  103. package/src/participant/test-fixtures/thread-closed.golden.html +1 -1
  104. package/src/participant/test-fixtures/thread-composer-microphone-idle.golden.html +1 -0
  105. package/src/participant/test-fixtures/thread-default.golden.html +1 -1
  106. package/src/participant/test-fixtures/thread-empty-draft.golden.html +1 -0
  107. package/src/participant/test-fixtures/thread-error.golden.html +1 -1
  108. package/src/participant/test-fixtures/thread-loading.golden.html +1 -1
  109. package/src/participant/test-fixtures/thread-plain.golden.html +1 -1
  110. package/src/participant/test-fixtures/thread-tail-off.golden.html +1 -1
  111. package/src/participant/useFailedMenuEffects.ts +59 -0
  112. package/src/participant/useParticipantAudioMediaEvents.ts +46 -0
  113. package/src/participant/useParticipantAudioPlayer.ts +52 -0
  114. package/src/participant/useParticipantAudioPlayerActions.ts +47 -0
  115. package/src/participant/useParticipantAudioRecorder.ts +153 -0
  116. package/src/participant/useParticipantAudioRecorderCore.ts +55 -0
  117. package/src/participant/useParticipantAudioRecorderEffects.ts +70 -0
  118. package/src/participant/useParticipantAudioSourceRetry.ts +42 -0
  119. package/src/participant/useParticipantFailedMenu.ts +60 -0
  120. package/src/participant/useParticipantSendAudio.test.tsx +85 -0
  121. package/src/participant/useParticipantSendAudio.ts +28 -0
  122. package/src/participant/useParticipantThreadController.ts +20 -7
  123. package/src/participant/useStableAttachmentUrl.ts +71 -0
  124. package/src/participant/useSuppressTouchTooltips.ts +38 -0
  125. package/src/participant/useTranscriptionOverflow.ts +25 -0
  126. package/src/participant/useTranscriptionReadyAnnouncement.ts +24 -0
  127. package/src/styles.css +48 -5
  128. package/src/tooltipLayerRegistry.test.ts +56 -0
  129. package/src/tooltipLayerRegistry.ts +34 -0
package/README.md CHANGED
@@ -392,6 +392,112 @@ superfície) e nenhum texto depende dele (o erro de carga ganha painel sólido).
392
392
  decorativa (cerca de 1,4:1): quem a distingue da página é o preenchimento, e o texto passa de 4,5:1. Ao mapear o
393
393
  acento, mantenha-o a 4,5:1 contra `--cv-p-highlight`, que é onde ficam os links da bolha própria. Os contrastes só valem com `--cv-p-highlight` **opaco**: o padrão do tema escuro do pacote é translúcido (`rgb(213 138 71 / 10%)`), então o host que mapeia o token deve fornecer um valor opaco.
394
394
 
395
+ ### Gravação de áudio e transcrição (`audioRecording`)
396
+
397
+ Capacidade **opt-in**: sem a prop `audioRecording`, não há microfone, e o compositor e a bolha mantêm o markup de
398
+ antes, byte a byte. A prop existe em `ParticipantConversations` e em `ConversationThread`.
399
+
400
+ ```tsx
401
+ import { ParticipantConversations } from '@adatechnology/conversations-ui/participant'
402
+
403
+ ;<ParticipantConversations
404
+ api={participantApi}
405
+ audioRecording={{
406
+ maxDurationMs: 120_000,
407
+ maxSizeBytes: 8 * 1024 * 1024,
408
+ onCaptureChange: (isCapturing) => captureRegistry.set('audio', isCapturing),
409
+ }}
410
+ />
411
+ ```
412
+
413
+ Tipo `ParticipantAudioRecordingOptions`, exportado por `@adatechnology/conversations-ui/participant`:
414
+
415
+ | Campo | Efeito |
416
+ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
417
+ | `maxDurationMs?` | teto da gravação. Só baixa: acima de 5 min (padrão) é cortado para 5 min |
418
+ | `maxSizeBytes?` | teto do arquivo. Só baixa: fica no menor valor entre `DEFAULT_MAX_RECORDING_BYTES` (16 MiB, a política de áudio da API) e o teto do canal |
419
+ | `onCaptureChange?(isCapturing)` | `true` de `requesting` até sair de `review`; `false` ao sair. Nunca recebe o áudio |
420
+
421
+ Regras de exibição e envio:
422
+
423
+ - O microfone só aparece com a prop **e** com o campo de texto vazio. Com texto ou anexo, o lugar dele é do botão de enviar.
424
+ - O canal só desliga a gravação. `portal` e `webchat` não gravam; `app`, `email` e `whatsapp` gravam.
425
+ - Sem `MediaRecorder` ou `getUserMedia` no navegador, o microfone não aparece.
426
+ - O áudio gravado vai como mensagem própria, pelo mesmo caminho do anexo (`send({ files: [file] })` por dentro). O rascunho de texto e os anexos do rascunho não são alterados. Dois toques seguidos enviam uma mensagem só.
427
+ - `onSendAudio` é fiação interna do controlador da thread, não prop do host. O host só passa `audioRecording`.
428
+
429
+ **Estados do gravador:** `idle` → `requesting` → `recording` → `review` (ouvir, enviar ou descartar). Os caminhos de erro
430
+ são `denied`, `unsupported`, `empty` e `tooLarge`, com mensagem no compositor. Durante a gravação, uma interrupção
431
+ (aba oculta, `pagehide`, trilha do microfone encerrada ou muda por mais de 3 s) para a captura e vai para `review`; em
432
+ `review`, pausa e mantém. Desmontar o componente descarta. O microfone é liberado em toda saída.
433
+
434
+ **Player.** Cada anexo `audio/*` mostra o player `.cv-p-audio` (tocar e pausar, posição, velocidade 1×, 1,5× e 2×) e
435
+ depois o nome do arquivo. Nada é baixado antes do primeiro toque (`preload="none"`); a URL é resolvida ao montar, por
436
+ `id` do anexo. A duração aparece depois do toque quando o servidor não manda `durationMs`. Tocar um áudio pausa o que
437
+ estava tocando em qualquer player da visão do participante na página (o player do operador e uma segunda cópia do
438
+ pacote não são coordenados).
439
+
440
+ **Bloco de transcrição** (por `transcription.status` do anexo):
441
+
442
+ - `pending`: linha "Transcribing…" (default em inglês).
443
+ - `ready`: aviso "gerada por máquina" e o texto, com expandir e recolher quando passa do espaço. Texto vazio mostra
444
+ "Nothing was said in the audio" (é resultado, não falha).
445
+ - `failed` com `reason: 'too_long'` e `maxDurationMs`: aviso com o limite aplicado.
446
+ - Qualquer outro `failed`, `disabled` ou ausência do campo: só o player.
447
+
448
+ **Rótulos novos.** Todos opcionais em `ParticipantConversationsLabels`; os defaults também entraram em `DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS`. `{minutes}` é **calculado** pela UI a partir de `maxDurationMs` (piso em minutos inteiros; abaixo de 1 minuto nada é desenhado), não vem do servidor. Os defaults em inglês estão em
449
+ `DEFAULT_PARTICIPANT_AUDIO_LABELS` (tipo `ParticipantAudioLabels`). Placeholders entre chaves são preenchidos pela
450
+ própria UI.
451
+
452
+ | Chave | Default | Onde aparece |
453
+ | ----------------------- | ------------------------------------------------------------ | -------------------------------------------- |
454
+ | `recordAudio` | Record audio | botão do microfone |
455
+ | `recordingInProgress` | Recording | grupo em `recording` |
456
+ | `stopRecording` | Stop recording | parar |
457
+ | `recordingElapsed` | {elapsed} of {limit} | relógio da gravação |
458
+ | `reviewAudio` | Listen before sending | dica em `review` |
459
+ | `sendAudio` | Send audio | enviar |
460
+ | `discardAudio` | Discard audio | descartar |
461
+ | `microphoneDenied` | No permission to use the microphone. | `denied` |
462
+ | `recordingUnsupported` | This device cannot record audio. | `unsupported` |
463
+ | `audioEmpty` | Nothing was captured by the microphone. | `empty` |
464
+ | `audioTooLarge` | Audio too large to send. | `tooLarge` |
465
+ | `audioPlayer` | Audio | grupo do player |
466
+ | `playAudio` | Play audio | tocar |
467
+ | `pauseAudio` | Pause audio | pausar |
468
+ | `audioPosition` | Audio position | nome do controle de posição |
469
+ | `audioPositionValue` | {position} of {duration} | `aria-valuetext` (sem duração, só a posição) |
470
+ | `playbackRate` | Playback speed {rate} | velocidade |
471
+ | `audioUnavailable` | Audio unavailable | falha do player |
472
+ | `transcribing` | Transcribing… | `pending` |
473
+ | `transcriptionReady` | Transcription ready | região viva ao terminar |
474
+ | `machineTranscription` | Transcription generated by machine | aviso de `ready` |
475
+ | `emptyTranscription` | Nothing was said in the audio | `ready` vazio |
476
+ | `transcriptionTooLong` | Transcription only for audios shorter than {minutes} minutes | `too_long` (`{minutes}` vem do servidor) |
477
+ | `showFullTranscription` | Show all | expandir |
478
+ | `collapseTranscription` | Show less | recolher |
479
+
480
+ **Classes novas** (todas `.cv-p-*`, em `styles.css`): `.cv-p-audio`, `.cv-p-audio__toggle`, `.cv-p-audio__seek`,
481
+ `.cv-p-audio__time`, `.cv-p-audio__rate`, `.cv-p-audio__media`, `.cv-p-audio__error`, `.cv-p-composer__record`,
482
+ `.cv-p-recorder` (com `--review`), `.cv-p-recorder__dot`, `.cv-p-recorder__elapsed`, `.cv-p-recorder__hint`,
483
+ `.cv-p-recorder__stop`, `.cv-p-recorder__send`, `.cv-p-recorder__discard`, `.cv-p-transcription` (com `--pending` e
484
+ `--too-long`), `.cv-p-transcription__notice`, `.cv-p-transcription__text`, `.cv-p-transcription__empty` e
485
+ `.cv-p-transcription__toggle`. Não há variável `--cv-p-*` nova: o áudio usa as que já existem (`--cv-p-accent`,
486
+ `--cv-p-text-muted`, `--cv-p-danger` e as demais da tabela acima).
487
+
488
+ **Limites conhecidos desta versão**
489
+
490
+ - **WhatsApp:** **não ative o microfone com `channel="whatsapp"` antes da validação**: o Chromium grava WebM, que o
491
+ WhatsApp não aceita. A capacidade do canal `whatsapp` declara gravação, mas o envio de áudio de volta ao WhatsApp não foi
492
+ validado ponta a ponta nesta branch. Não trate a gravação nessa conversa como pronta até a validação da spec 264.
493
+ - **Safari e iPhone:** o formato e a gravação no Safari/iPhone (`audio/mp4`) e o pedido de permissão no toque ficam a
494
+ conferir em aparelho real na T7.1 do consumidor.
495
+ - **Evento `stop` ausente:** se o `stop` do `MediaRecorder` nunca chegar (a especificação o garante), a UI permanece em
496
+ `recording` até o usuário descartar a gravação. Um vigia opcional fica para uma versão futura.
497
+
498
+ **Validação do anexo.** `transcription` e `durationMs` inválidos reprovam o anexo inteiro (só chaves desconhecidas são
499
+ descartadas): valide por anexo com `participantTranscriptionSchema.safeParse` e descarte o campo que falhar.
500
+
395
501
  ### Limitações conhecidas
396
502
 
397
503
  - O avatar alinha pelo topo da bolha, não pelo rabinho no canto inferior.
@@ -20,15 +20,6 @@ interface MediaRendererProps {
20
20
  }
21
21
  declare function MediaRenderer({ message, onLightbox, onResolveUrl, onTranscribeAudio, className, }: MediaRendererProps): react.JSX.Element | null;
22
22
 
23
- /**
24
- * Gravação de áudio no simulador, pelo microfone do próprio navegador.
25
- *
26
- * Existe porque áudio é o formato que mais chega de cliente real e o que mais quebra fluxo: sem
27
- * poder gravar aqui, testar o caminho de transcrição exigia mandar mensagem do celular de alguém.
28
- *
29
- * O arquivo gravado sai daqui como `File` e segue exatamente o mesmo caminho de um anexo — quem
30
- * hospeda e devolve o `mediaId` é o host, via `uploadMedia`.
31
- */
32
23
  interface AudioRecorderButtonLabels {
33
24
  start: string;
34
25
  stop: string;
@@ -69,12 +60,6 @@ interface AudioRecorderButtonProps {
69
60
  */
70
61
  disabledHint?: string;
71
62
  }
72
- /**
73
- * Cinco minutos: com o codec de voz do WhatsApp isso dá menos de 3MB, folgado dentro do teto de
74
- * 16MB que a Meta impõe a áudio, e é mais do que qualquer recado de cliente. O corte automático
75
- * existe porque gravação esquecida aberta só se descobre no envio, com o arquivo inteiro perdido.
76
- */
77
- declare const DEFAULT_MAX_RECORDING_MILLISECONDS: number;
78
63
  declare function AudioRecorderButton({ onRecorded, onFailure, onRecordingChange, reviewBeforeSend, maxDurationMilliseconds, labels, disabled, disabledHint, }: AudioRecorderButtonProps): react.JSX.Element;
79
64
 
80
65
  interface ListConversationsParams {
@@ -651,4 +636,4 @@ type ConversationSimulatorPanelProps = Omit<ConversationPreviewProps, 'placehold
651
636
  };
652
637
  declare function ConversationSimulatorPanel({ onClose, channel, displayHandle, displayNumber, labels, headerActions, ...previewProps }: ConversationSimulatorPanelProps): react.JSX.Element;
653
638
 
654
- export { AudioRecorderButton as A, acceptsMediaKind as B, type ConversationSummary as C, DEFAULT_AUDIO_RECORDER_BUTTON_LABELS as D, assertPreviewEnvironment as E, createPreviewMediaPoster as F, createPreviewMediaUploader as G, createPreviewWebhookClient as H, isConversationSimulatorClient as I, mediaKindOf as J, mediaTypeOf as K, type ListConversationsParams as L, signPreviewPayload as M, simulatorPanelLabelsOf as N, toConversationSimulatorClient as O, type PreviewUploadedMedia$1 as P, type ListDocumentsParams as Q, type ResolveMediaUrl as R, type SSEProvider as S, type ToSimulatorClientParams as T, type ConversationTemplate as U, type CompanyDocument as V, type CompanyDocumentPage as W, type ConversationDocumentPage as X, DEFAULT_MAX_RECORDING_MILLISECONDS as Y, MediaRenderer as Z, type MediaRendererProps as _, type ConversationEventSource as a, type ConversationsApi as b, type ConversationPage as c, type ConversationDocument as d, type SendPreviewMediaParams as e, type PreviewWebhookClient as f, type AudioRecorderButtonLabels as g, type AudioRecorderButtonProps as h, ConversationPreview as i, type ConversationPreviewProps as j, type ConversationSimulatorClient as k, ConversationSimulatorPanel as l, type ConversationSimulatorPanelLabels as m, type ConversationSimulatorPanelProps as n, type CreatePreviewMediaUploaderParams as o, type CreatePreviewWebhookClientParams as p, DEFAULT_CONVERSATION_SIMULATOR_PANEL_LABELS as q, DEFAULT_MEDIA_UPLOAD_PATH as r, PreviewInProductionError as s, PreviewMediaUploadRejectedError as t, type PreviewMediaUploadRequest as u, type PreviewUploadedMedia as v, PreviewWebhookRejectedError as w, SIMULATOR_FILE_MEDIA_KINDS as x, type SendSimulatorMediaParams as y, type SimulatorMediaKind as z };
639
+ export { AudioRecorderButton as A, acceptsMediaKind as B, type ConversationSummary as C, DEFAULT_AUDIO_RECORDER_BUTTON_LABELS as D, assertPreviewEnvironment as E, createPreviewMediaPoster as F, createPreviewMediaUploader as G, createPreviewWebhookClient as H, isConversationSimulatorClient as I, mediaKindOf as J, mediaTypeOf as K, type ListConversationsParams as L, signPreviewPayload as M, simulatorPanelLabelsOf as N, toConversationSimulatorClient as O, type PreviewUploadedMedia$1 as P, type ListDocumentsParams as Q, type ResolveMediaUrl as R, type SSEProvider as S, type ToSimulatorClientParams as T, type ConversationTemplate as U, type CompanyDocument as V, type CompanyDocumentPage as W, type ConversationDocumentPage as X, MediaRenderer as Y, type MediaRendererProps as Z, type ConversationEventSource as a, type ConversationsApi as b, type ConversationPage as c, type ConversationDocument as d, type SendPreviewMediaParams as e, type PreviewWebhookClient as f, type AudioRecorderButtonLabels as g, type AudioRecorderButtonProps as h, ConversationPreview as i, type ConversationPreviewProps as j, type ConversationSimulatorClient as k, ConversationSimulatorPanel as l, type ConversationSimulatorPanelLabels as m, type ConversationSimulatorPanelProps as n, type CreatePreviewMediaUploaderParams as o, type CreatePreviewWebhookClientParams as p, DEFAULT_CONVERSATION_SIMULATOR_PANEL_LABELS as q, DEFAULT_MEDIA_UPLOAD_PATH as r, PreviewInProductionError as s, PreviewMediaUploadRejectedError as t, type PreviewMediaUploadRequest as u, type PreviewUploadedMedia as v, PreviewWebhookRejectedError as w, SIMULATOR_FILE_MEDIA_KINDS as x, type SendSimulatorMediaParams as y, type SimulatorMediaKind as z };
@@ -1,10 +1,36 @@
1
- import {
2
- cn
3
- } from "./chunk-PJNR6UMN.js";
4
-
5
1
  // src/Tooltip.tsx
6
2
  import { useEffect, useRef, useState } from "react";
7
3
  import { createPortal } from "react-dom";
4
+
5
+ // src/tooltipLayerRegistry.ts
6
+ function createTooltipLayerRegistry() {
7
+ const layers = /* @__PURE__ */ new Map();
8
+ let owner;
9
+ function handOff() {
10
+ const next = layers.entries().next();
11
+ if (next.done) {
12
+ owner = void 0;
13
+ return;
14
+ }
15
+ const [layer, onOwnershipChange] = next.value;
16
+ owner = layer;
17
+ onOwnershipChange(true);
18
+ }
19
+ return {
20
+ register(layer, onOwnershipChange) {
21
+ layers.set(layer, onOwnershipChange);
22
+ if (owner === void 0) handOff();
23
+ return () => {
24
+ layers.delete(layer);
25
+ if (owner !== layer) return;
26
+ owner = void 0;
27
+ handOff();
28
+ };
29
+ }
30
+ };
31
+ }
32
+
33
+ // src/Tooltip.tsx
8
34
  import { jsx } from "react/jsx-runtime";
9
35
  var TOOLTIP_ATTRIBUTE = "data-cv-tooltip";
10
36
  var TOOLTIP_DELAY_MS = 120;
@@ -26,20 +52,12 @@ function tooltipStateFor(target, text) {
26
52
  });
27
53
  return { text, ...position };
28
54
  }
29
- var layerOwner;
55
+ var layerRegistry = createTooltipLayerRegistry();
30
56
  function TooltipLayer() {
31
57
  const identity = useRef({});
32
58
  const [isOwner, setIsOwner] = useState(false);
33
59
  const [tooltip, setTooltip] = useState(void 0);
34
- useEffect(() => {
35
- const owned = identity.current;
36
- if (layerOwner && layerOwner !== owned) return void 0;
37
- layerOwner = owned;
38
- setIsOwner(true);
39
- return () => {
40
- if (layerOwner === owned) layerOwner = void 0;
41
- };
42
- }, []);
60
+ useEffect(() => layerRegistry.register(identity.current, setIsOwner), []);
43
61
  useEffect(() => {
44
62
  if (!isOwner) return void 0;
45
63
  let timer;
@@ -108,20 +126,7 @@ function TooltipLayer() {
108
126
  );
109
127
  }
110
128
 
111
- // src/lib/WhatsAppMessagePreview.tsx
112
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
113
- function WhatsAppMessagePreview({ children, belowBubble, footer, className }) {
114
- return /* @__PURE__ */ jsxs("div", { className: cn("rounded-xl bg-[#e5ddd5] dark:bg-gray-900 p-3 space-y-1.5", className), children: [
115
- /* @__PURE__ */ jsxs("div", { className: "max-w-[85%]", children: [
116
- /* @__PURE__ */ jsx2("div", { className: "rounded-lg rounded-tl-none bg-white dark:bg-gray-700 px-3 py-2 text-sm text-gray-900 dark:text-gray-100 shadow-sm whitespace-pre-wrap break-words", children }),
117
- belowBubble
118
- ] }),
119
- footer
120
- ] });
121
- }
122
-
123
129
  export {
124
130
  TOOLTIP_ATTRIBUTE,
125
- TooltipLayer,
126
- WhatsAppMessagePreview
131
+ TooltipLayer
127
132
  };
@@ -233,6 +233,19 @@ function formatFileSize(bytes) {
233
233
  return `${formatted} ${FILE_SIZE_UNITS[exponent]}`;
234
234
  }
235
235
 
236
+ // src/audioRecorderFormat.ts
237
+ var DEFAULT_MAX_RECORDING_MILLISECONDS = 5 * 60 * 1e3;
238
+ var RECORDING_FORMATS = [
239
+ { mimeType: "audio/ogg;codecs=opus", uploadMimeType: "audio/ogg", extension: "ogg" },
240
+ { mimeType: "audio/mp4", uploadMimeType: "audio/mp4", extension: "m4a" },
241
+ { mimeType: "audio/webm", uploadMimeType: "audio/webm", extension: "webm" }
242
+ ];
243
+ function resolveRecordingFormat() {
244
+ if (typeof MediaRecorder === "undefined") return void 0;
245
+ if (typeof MediaRecorder.isTypeSupported !== "function") return RECORDING_FORMATS[0];
246
+ return RECORDING_FORMATS.find((format) => MediaRecorder.isTypeSupported(format.mimeType));
247
+ }
248
+
236
249
  export {
237
250
  formatPhone,
238
251
  phoneInitials,
@@ -251,5 +264,7 @@ export {
251
264
  formatTimestamp,
252
265
  formatDateTime,
253
266
  isSameDay,
254
- formatFileSize
267
+ formatFileSize,
268
+ DEFAULT_MAX_RECORDING_MILLISECONDS,
269
+ resolveRecordingFormat
255
270
  };
@@ -6,14 +6,16 @@ import {
6
6
  import {
7
7
  CONVERSATION_CHANNEL,
8
8
  DEFAULT_CONVERSATION_CHANNEL,
9
+ DEFAULT_MAX_RECORDING_MILLISECONDS,
9
10
  StatusTicks,
10
11
  channelCapabilityFor,
11
12
  formatDateTime,
12
13
  formatFileSize,
13
14
  formatPhone,
14
15
  formatTimestamp,
15
- isSameDay
16
- } from "./chunk-O6457XHK.js";
16
+ isSameDay,
17
+ resolveRecordingFormat
18
+ } from "./chunk-WCZNIJ3M.js";
17
19
 
18
20
  // src/ConversationLocalesProvider.tsx
19
21
  import { createContext, useContext } from "react";
@@ -1098,17 +1100,6 @@ var DEFAULT_AUDIO_RECORDER_BUTTON_LABELS = {
1098
1100
  discard: "Descartar \xE1udio",
1099
1101
  empty: "Nada foi captado pelo microfone."
1100
1102
  };
1101
- var DEFAULT_MAX_RECORDING_MILLISECONDS = 5 * 60 * 1e3;
1102
- var RECORDING_FORMATS = [
1103
- { mimeType: "audio/ogg;codecs=opus", uploadMimeType: "audio/ogg", extension: "ogg" },
1104
- { mimeType: "audio/mp4", uploadMimeType: "audio/mp4", extension: "m4a" },
1105
- { mimeType: "audio/webm", uploadMimeType: "audio/webm", extension: "webm" }
1106
- ];
1107
- function resolveRecordingFormat() {
1108
- if (typeof MediaRecorder === "undefined") return void 0;
1109
- if (typeof MediaRecorder.isTypeSupported !== "function") return RECORDING_FORMATS[0];
1110
- return RECORDING_FORMATS.find((format) => MediaRecorder.isTypeSupported(format.mimeType));
1111
- }
1112
1103
  function AudioRecorderButton({
1113
1104
  onRecorded,
1114
1105
  onFailure,
@@ -3047,7 +3038,6 @@ export {
3047
3038
  DEFAULT_EMOJI_PICKER_LABELS,
3048
3039
  EmojiPicker,
3049
3040
  DEFAULT_AUDIO_RECORDER_BUTTON_LABELS,
3050
- DEFAULT_MAX_RECORDING_MILLISECONDS,
3051
3041
  AudioRecorderButton,
3052
3042
  COMPOSER_BAR_CLASS,
3053
3043
  COMPOSER_TOOL_BUTTON_CLASS,
@@ -0,0 +1,19 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-PJNR6UMN.js";
4
+
5
+ // src/lib/WhatsAppMessagePreview.tsx
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ function WhatsAppMessagePreview({ children, belowBubble, footer, className }) {
8
+ return /* @__PURE__ */ jsxs("div", { className: cn("rounded-xl bg-[#e5ddd5] dark:bg-gray-900 p-3 space-y-1.5", className), children: [
9
+ /* @__PURE__ */ jsxs("div", { className: "max-w-[85%]", children: [
10
+ /* @__PURE__ */ jsx("div", { className: "rounded-lg rounded-tl-none bg-white dark:bg-gray-700 px-3 py-2 text-sm text-gray-900 dark:text-gray-100 shadow-sm whitespace-pre-wrap break-words", children }),
11
+ belowBubble
12
+ ] }),
13
+ footer
14
+ ] });
15
+ }
16
+
17
+ export {
18
+ WhatsAppMessagePreview
19
+ };
@@ -1,7 +1,9 @@
1
1
  import {
2
- TooltipLayer,
3
2
  WhatsAppMessagePreview
4
- } from "../chunk-HMCOTZAX.js";
3
+ } from "../chunk-ZSOD5AQT.js";
4
+ import {
5
+ TooltipLayer
6
+ } from "../chunk-NSOAUYNE.js";
5
7
  import {
6
8
  parseWhatsAppFormatting,
7
9
  useIsDarkTheme
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import * as react from 'react';
2
2
  import react__default, { ReactNode, CSSProperties, UIEvent, FormEvent, RefObject, KeyboardEvent } from 'react';
3
3
  import { M as MessagePayload, I as InteractiveSelection, a as MessageTranscription, C as ConversationChannel, e as InteractivePayload, f as ConversationsFeatures, Q as QuickReply$1, T as TranscriptionMode, g as QueuedAttachment, b as QuickReplyInput, c as QuickReplyAttachment, h as ConversationVariable, i as ChannelFilter, j as ChannelFilterOption } from './quickReply.types-DzWH3NYV.js';
4
4
  export { k as CHANNEL_CAPABILITIES, l as CHANNEL_FILTER_ALL, m as CONVERSATION_CHANNEL, n as ChannelCapabilities, d as ConversationsTheme, o as ConversationsUIConfig, D as DEFAULT_CONVERSATION_CHANNEL, F as FormatContactHandleParams, H as HANDLE_KIND, p as HandleKind, q as InteractiveOption, r as InteractiveSection, s as QUICK_REPLY_ATTACHMENT_LIMIT, R as REOPEN_MECHANISM, t as ReopenMechanism, S as StoredAttachmentSendResult, u as TranscriptionStatus, v as capabilitiesOf, w as channelFiltersFor, x as contactFlag, y as formatContactHandle } from './quickReply.types-DzWH3NYV.js';
5
- import { R as ResolveMediaUrl, C as ConversationSummary, L as ListConversationsParams, b as ConversationsApi, S as SSEProvider, Q as ListDocumentsParams, d as ConversationDocument, U as ConversationTemplate, k as ConversationSimulatorClient, m as ConversationSimulatorPanelLabels, P as PreviewUploadedMedia } from './ConversationSimulatorPanel-q-wVgBCN.js';
6
- export { A as AudioRecorderButton, g as AudioRecorderButtonLabels, h as AudioRecorderButtonProps, V as CompanyDocument, W as CompanyDocumentPage, X as ConversationDocumentPage, a as ConversationEventSource, c as ConversationPage, D as DEFAULT_AUDIO_RECORDER_BUTTON_LABELS, Y as DEFAULT_MAX_RECORDING_MILLISECONDS, Z as MediaRenderer, _ as MediaRendererProps, y as SendSimulatorMediaParams, z as SimulatorMediaKind } from './ConversationSimulatorPanel-q-wVgBCN.js';
5
+ import { R as ResolveMediaUrl, C as ConversationSummary, L as ListConversationsParams, b as ConversationsApi, S as SSEProvider, Q as ListDocumentsParams, d as ConversationDocument, U as ConversationTemplate, k as ConversationSimulatorClient, m as ConversationSimulatorPanelLabels, P as PreviewUploadedMedia } from './ConversationSimulatorPanel-P6eqTSAO.js';
6
+ export { A as AudioRecorderButton, g as AudioRecorderButtonLabels, h as AudioRecorderButtonProps, V as CompanyDocument, W as CompanyDocumentPage, X as ConversationDocumentPage, a as ConversationEventSource, c as ConversationPage, D as DEFAULT_AUDIO_RECORDER_BUTTON_LABELS, Y as MediaRenderer, Z as MediaRendererProps, y as SendSimulatorMediaParams, z as SimulatorMediaKind } from './ConversationSimulatorPanel-P6eqTSAO.js';
7
7
  import { ChannelCapability } from '@adatechnology/conversation-contracts';
8
8
  export { ChannelCapability } from '@adatechnology/conversation-contracts';
9
9
  import '@adatechnology/meta-whatsapp-contracts/testing';
@@ -487,6 +487,13 @@ interface RichMessageComposerProps {
487
487
  }
488
488
  declare const RichMessageComposer: react.ForwardRefExoticComponent<RichMessageComposerProps & react.RefAttributes<RichMessageComposerHandle>>;
489
489
 
490
+ /**
491
+ * Cinco minutos: com o codec de voz do WhatsApp isso dá menos de 3MB, folgado dentro do teto de
492
+ * 16MB que a Meta impõe a áudio, e é mais do que qualquer recado de cliente. O corte automático
493
+ * existe porque gravação esquecida aberta só se descobre no envio, com o arquivo inteiro perdido.
494
+ */
495
+ declare const DEFAULT_MAX_RECORDING_MILLISECONDS: number;
496
+
490
497
  interface WhatsAppMessageEditorLabels {
491
498
  bold: string;
492
499
  /** Tooltip da negrito — traz a sintaxe do WhatsApp junto, por isso é separado do `aria-label`. */
@@ -2314,4 +2321,4 @@ type QueuedAttachmentsListProps = {
2314
2321
  };
2315
2322
  declare function QueuedAttachmentsList({ items, statusOf, onRemove, onRetry, retryingKeys, getThumbnailUrl, labels, busy, }: QueuedAttachmentsListProps): react.JSX.Element | null;
2316
2323
 
2317
- export { type AsyncResourceState, type AttachmentFileRejection, AudioPlayer, type AudioPlayerProps, AudioTranscription, type AudioTranscriptionProps, Avatar, type AvatarLabels, type AvatarProps, type BotMessages, type BuildTranscriptTextParams, BulkActionBar, type BulkActionBarProps, CHANNEL_BRAND_COLOR, CONVERSATIONS_PER_PAGE, CONVERSATION_WINDOW, ChannelFilter, ChannelFilterOption, ChannelIcon, type ChannelIconProps, ConversationChannel, type ConversationContextEntry, ConversationContextPanel, type ConversationContextPanelClassNames, type ConversationContextPanelLabels, type ConversationContextPanelProps, type ConversationContextStatus, ConversationDocument, ConversationDocumentsPanel, type ConversationDocumentsPanelClassNames, type ConversationDocumentsPanelLabels, type ConversationDocumentsPanelProps, ConversationHeader, type ConversationHeaderClassNames, type ConversationHeaderLabels, type ConversationHeaderProps, type ConversationHeaderUtility, ConversationListItem, type ConversationListItemLabels, type ConversationListItemProps, type ConversationLocales, ConversationLocalesProvider, type ConversationLocalesProviderProps, ConversationPane, type ConversationPaneProps, type ConversationRealtimeHandler, ConversationRow, type ConversationRowClassNames, type ConversationRowProps, ConversationSimulatorClient, ConversationSummary, ConversationTemplate, ConversationVariable, ConversationWallpaper, type ConversationWallpaperProps, type ConversationWindow, ConversationsApi, ConversationsFeatures, ConversationsInboxList, type ConversationsInboxListProps, ConversationsProvider, ConversationsWorkspace, type ConversationsWorkspaceLabels, type ConversationsWorkspaceProps, type ConversationsWorkspaceSimulator, DEFAULT_ACCEPTED_FILE_TYPES, DEFAULT_AVATAR_LABELS, DEFAULT_CONVERSATIONS_WORKSPACE_LABELS, DEFAULT_CONVERSATION_CONTEXT_LABELS, DEFAULT_CONVERSATION_DOCUMENTS_LABELS, DEFAULT_CONVERSATION_HEADER_LABELS, DEFAULT_CONVERSATION_LIST_ITEM_LABELS, DEFAULT_DARK_MODE_TOGGLE_LABELS, DEFAULT_DOCUMENTS_LIBRARY_LABELS, DEFAULT_DOCUMENTS_WORKSPACE_LABELS, DEFAULT_EMOJI_PICKER_LABELS, DEFAULT_INTERACTIVE_MESSAGE_LABELS, DEFAULT_LIGHTBOX_LABELS, DEFAULT_MAX_ATTACHMENT_SIZE_BYTES, DEFAULT_MESSAGE_COMPOSER_LABELS, DEFAULT_QUICK_REPLIES_PICKER_LABELS, DEFAULT_QUICK_REPLIES_WORKSPACE_LABELS, DEFAULT_RICH_COMPOSER_TOOLTIPS, DEFAULT_TEMPLATES_SETTINGS_LABELS, DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS, DEFAULT_WINDOW_EXPIRED_LABELS, DOCUMENT_SOURCE_FILTER, DarkModeToggle, type DarkModeToggleLabels, type DarkModeToggleProps, DateDivider, type DateDividerClassNames, type DateDividerProps, type DocumentSourceFilter, type DocumentsFiltersContext, DocumentsLibrary, type DocumentsLibraryClassNames, type DocumentsLibraryLabels, type DocumentsLibraryProps, DocumentsWorkspace, type DocumentsWorkspaceClassNames, type DocumentsWorkspaceLabels, type DocumentsWorkspaceProps, EMOJI_CATEGORIES, type EmojiCategory, type EmojiEntry, EmojiPicker, type EmojiPickerLabels, type EmojiPickerProps, FileIcon, type FileIconProps, type FilterOption, type FilterQuickRepliesParams, InteractiveMessage, type InteractiveMessageLabels, type InteractiveMessageProps, InteractivePayload, InteractiveSelection, Lightbox, type LightboxLabels, type LightboxProps, ListConversationsParams, ListDocumentsParams, ListingPagination, type ListingPaginationProps, type MatchSegment, type MaxAttachmentSizeBytes, MessageBubble, type MessageBubbleProps, MessageComposer, type MessageComposerClassNames, type MessageComposerLabels, type MessageComposerProps, MessagePayload, MessageTail, MessageText, type MessageTextProps, MessageTimestamp, MessageTranscription, MessagesWorkspace, type MessagesWorkspaceApi, type MessagesWorkspaceLabels, type MessagesWorkspaceProps, type MessagesWorkspaceTemplateRole, MultiSelectFilter, type MultiSelectFilterProps, NARROW_MAX_WIDTH_PX, type OutgoingItems, QueuedAttachment, QueuedAttachmentsList, QuickRepliesPicker, type QuickRepliesPickerLabels, type QuickRepliesPickerProps, QuickRepliesWorkspace, type QuickRepliesWorkspaceLabels, type QuickRepliesWorkspaceProps, type QuickReply, QuickReplyAttachment, QuickReplyInput, REPLY_LATENCY, REPLY_LATENCY_CRITICAL_HOURS, REPLY_LATENCY_LATE_HOURS, RICH_COMPOSER_ACTION, type ReplyLatency, type ReplyLatencyParams, ResolveMediaUrl, type RichComposerAction, type RichComposerQuickReply, type RichComposerTooltips, type RichComposerVariable, RichMessageComposer, type RichMessageComposerHandle, type RichMessageComposerProps, SSEProvider, QuickReply$1 as SavedQuickReply, SimpleEmojiPicker, type SimpleEmojiPickerProps, type SimulatorTransportFactory, type SimulatorTransportParams, type SortDirection, SortableHead, type SortableHeadProps, StatusTicks, type StatusTicksProps, TEMPLATE_SETTINGS_TAB, TOOLTIP_ATTRIBUTE, type TemplateSettings, type TemplateSettingsTab, ToastProvider, TooltipLayer, type TopicItem, TopicsForm, type TopicsFormLabels, type TopicsFormProps, TranscriptionMode, type TranscriptionSettings, TranscriptionSettingsForm, type TranscriptionSettingsFormLabels, type TranscriptionSettingsFormProps, type UrlStateOptions, type UseConversationActionsResult, type UseConversationContextResult, type UseConversationDocumentsParams, type UseConversationDocumentsResult, type UseConversationListParams, type UseConversationListResult, type UseConversationMessagesResult, type UseConversationsInboxParams, type UseConversationsInboxResult, type UseInboxActionsResult, type UseScrollToLatestMessageParams, type UseScrollToLatestMessageResult, type UseWaitingNotificationsLabels, type UseWaitingNotificationsParams, type UseWaitingNotificationsResult, type ValidateAttachmentFilesResult, WHATSAPP_MARKER_BY_ACTION, WINDOW_FILTERS, WelcomeFarewellForm, type WelcomeFarewellFormLabels, type WelcomeFarewellFormProps, WhatsAppCreateTemplateForm, type WhatsAppCreateTemplateFormLabels, type WhatsAppCreateTemplateFormProps, type WhatsAppCreateTemplateResult, type WhatsAppCreateTemplateState, WhatsAppMessageEditor, type WhatsAppMessageEditorLabels, type WhatsAppMessageEditorProps, WhatsAppMessagePreview, type WhatsAppMessagePreviewProps, type WhatsAppTemplateHeaderType, WhatsAppTemplateSettingsForm, type WhatsAppTemplateSettingsFormLabels, type WhatsAppTemplateSettingsFormProps, type WhatsAppTemplateSummary, type WhatsAppTemplateVariableSuggestion, WhatsAppTemplatesSettings, type WhatsAppTemplatesSettingsLabels, type WhatsAppTemplatesSettingsProps, WindowExpiredNotice, type WindowExpiredNoticeLabels, type WindowExpiredNoticeProps, type WindowOfParams, applyQuickReplyVariables, buildTranscriptFilename, buildTranscriptText, channelCapabilityFor, createMediaUrlResolver, downloadTextFile, filterQuickReplies, formatDateTime, formatFileSize, formatPhone, formatStalledFor, formatTimestamp, highlightMatch, htmlToWA, isReplyOverdue, isSameDay, isWindowBlocking, normalizeForSearch, parseWhatsAppFormatting, phoneInitials, queuedAttachmentsFromQuickReply, replyLatencyOf, resolveMaxAttachmentSizeBytes, resolveQuickReply, searchEmojis, toast, useConversationActions, useConversationContext, useConversationDocuments, useConversationList, useConversationLocales, useConversationMessages, useConversationRealtime, useConversations, useConversationsInbox, useDarkMode, useDebouncedValue, useGlobalRealtime, useInboxActions, useIsDarkTheme, useIsNarrow, useScrollToLatestMessage, useToast, useUrlArrayState, useUrlNumberState, useUrlStringState, useWaitingNotifications, waToHTML, waToHTMLInline, windowOf };
2324
+ export { type AsyncResourceState, type AttachmentFileRejection, AudioPlayer, type AudioPlayerProps, AudioTranscription, type AudioTranscriptionProps, Avatar, type AvatarLabels, type AvatarProps, type BotMessages, type BuildTranscriptTextParams, BulkActionBar, type BulkActionBarProps, CHANNEL_BRAND_COLOR, CONVERSATIONS_PER_PAGE, CONVERSATION_WINDOW, ChannelFilter, ChannelFilterOption, ChannelIcon, type ChannelIconProps, ConversationChannel, type ConversationContextEntry, ConversationContextPanel, type ConversationContextPanelClassNames, type ConversationContextPanelLabels, type ConversationContextPanelProps, type ConversationContextStatus, ConversationDocument, ConversationDocumentsPanel, type ConversationDocumentsPanelClassNames, type ConversationDocumentsPanelLabels, type ConversationDocumentsPanelProps, ConversationHeader, type ConversationHeaderClassNames, type ConversationHeaderLabels, type ConversationHeaderProps, type ConversationHeaderUtility, ConversationListItem, type ConversationListItemLabels, type ConversationListItemProps, type ConversationLocales, ConversationLocalesProvider, type ConversationLocalesProviderProps, ConversationPane, type ConversationPaneProps, type ConversationRealtimeHandler, ConversationRow, type ConversationRowClassNames, type ConversationRowProps, ConversationSimulatorClient, ConversationSummary, ConversationTemplate, ConversationVariable, ConversationWallpaper, type ConversationWallpaperProps, type ConversationWindow, ConversationsApi, ConversationsFeatures, ConversationsInboxList, type ConversationsInboxListProps, ConversationsProvider, ConversationsWorkspace, type ConversationsWorkspaceLabels, type ConversationsWorkspaceProps, type ConversationsWorkspaceSimulator, DEFAULT_ACCEPTED_FILE_TYPES, DEFAULT_AVATAR_LABELS, DEFAULT_CONVERSATIONS_WORKSPACE_LABELS, DEFAULT_CONVERSATION_CONTEXT_LABELS, DEFAULT_CONVERSATION_DOCUMENTS_LABELS, DEFAULT_CONVERSATION_HEADER_LABELS, DEFAULT_CONVERSATION_LIST_ITEM_LABELS, DEFAULT_DARK_MODE_TOGGLE_LABELS, DEFAULT_DOCUMENTS_LIBRARY_LABELS, DEFAULT_DOCUMENTS_WORKSPACE_LABELS, DEFAULT_EMOJI_PICKER_LABELS, DEFAULT_INTERACTIVE_MESSAGE_LABELS, DEFAULT_LIGHTBOX_LABELS, DEFAULT_MAX_ATTACHMENT_SIZE_BYTES, DEFAULT_MAX_RECORDING_MILLISECONDS, DEFAULT_MESSAGE_COMPOSER_LABELS, DEFAULT_QUICK_REPLIES_PICKER_LABELS, DEFAULT_QUICK_REPLIES_WORKSPACE_LABELS, DEFAULT_RICH_COMPOSER_TOOLTIPS, DEFAULT_TEMPLATES_SETTINGS_LABELS, DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS, DEFAULT_WINDOW_EXPIRED_LABELS, DOCUMENT_SOURCE_FILTER, DarkModeToggle, type DarkModeToggleLabels, type DarkModeToggleProps, DateDivider, type DateDividerClassNames, type DateDividerProps, type DocumentSourceFilter, type DocumentsFiltersContext, DocumentsLibrary, type DocumentsLibraryClassNames, type DocumentsLibraryLabels, type DocumentsLibraryProps, DocumentsWorkspace, type DocumentsWorkspaceClassNames, type DocumentsWorkspaceLabels, type DocumentsWorkspaceProps, EMOJI_CATEGORIES, type EmojiCategory, type EmojiEntry, EmojiPicker, type EmojiPickerLabels, type EmojiPickerProps, FileIcon, type FileIconProps, type FilterOption, type FilterQuickRepliesParams, InteractiveMessage, type InteractiveMessageLabels, type InteractiveMessageProps, InteractivePayload, InteractiveSelection, Lightbox, type LightboxLabels, type LightboxProps, ListConversationsParams, ListDocumentsParams, ListingPagination, type ListingPaginationProps, type MatchSegment, type MaxAttachmentSizeBytes, MessageBubble, type MessageBubbleProps, MessageComposer, type MessageComposerClassNames, type MessageComposerLabels, type MessageComposerProps, MessagePayload, MessageTail, MessageText, type MessageTextProps, MessageTimestamp, MessageTranscription, MessagesWorkspace, type MessagesWorkspaceApi, type MessagesWorkspaceLabels, type MessagesWorkspaceProps, type MessagesWorkspaceTemplateRole, MultiSelectFilter, type MultiSelectFilterProps, NARROW_MAX_WIDTH_PX, type OutgoingItems, QueuedAttachment, QueuedAttachmentsList, QuickRepliesPicker, type QuickRepliesPickerLabels, type QuickRepliesPickerProps, QuickRepliesWorkspace, type QuickRepliesWorkspaceLabels, type QuickRepliesWorkspaceProps, type QuickReply, QuickReplyAttachment, QuickReplyInput, REPLY_LATENCY, REPLY_LATENCY_CRITICAL_HOURS, REPLY_LATENCY_LATE_HOURS, RICH_COMPOSER_ACTION, type ReplyLatency, type ReplyLatencyParams, ResolveMediaUrl, type RichComposerAction, type RichComposerQuickReply, type RichComposerTooltips, type RichComposerVariable, RichMessageComposer, type RichMessageComposerHandle, type RichMessageComposerProps, SSEProvider, QuickReply$1 as SavedQuickReply, SimpleEmojiPicker, type SimpleEmojiPickerProps, type SimulatorTransportFactory, type SimulatorTransportParams, type SortDirection, SortableHead, type SortableHeadProps, StatusTicks, type StatusTicksProps, TEMPLATE_SETTINGS_TAB, TOOLTIP_ATTRIBUTE, type TemplateSettings, type TemplateSettingsTab, ToastProvider, TooltipLayer, type TopicItem, TopicsForm, type TopicsFormLabels, type TopicsFormProps, TranscriptionMode, type TranscriptionSettings, TranscriptionSettingsForm, type TranscriptionSettingsFormLabels, type TranscriptionSettingsFormProps, type UrlStateOptions, type UseConversationActionsResult, type UseConversationContextResult, type UseConversationDocumentsParams, type UseConversationDocumentsResult, type UseConversationListParams, type UseConversationListResult, type UseConversationMessagesResult, type UseConversationsInboxParams, type UseConversationsInboxResult, type UseInboxActionsResult, type UseScrollToLatestMessageParams, type UseScrollToLatestMessageResult, type UseWaitingNotificationsLabels, type UseWaitingNotificationsParams, type UseWaitingNotificationsResult, type ValidateAttachmentFilesResult, WHATSAPP_MARKER_BY_ACTION, WINDOW_FILTERS, WelcomeFarewellForm, type WelcomeFarewellFormLabels, type WelcomeFarewellFormProps, WhatsAppCreateTemplateForm, type WhatsAppCreateTemplateFormLabels, type WhatsAppCreateTemplateFormProps, type WhatsAppCreateTemplateResult, type WhatsAppCreateTemplateState, WhatsAppMessageEditor, type WhatsAppMessageEditorLabels, type WhatsAppMessageEditorProps, WhatsAppMessagePreview, type WhatsAppMessagePreviewProps, type WhatsAppTemplateHeaderType, WhatsAppTemplateSettingsForm, type WhatsAppTemplateSettingsFormLabels, type WhatsAppTemplateSettingsFormProps, type WhatsAppTemplateSummary, type WhatsAppTemplateVariableSuggestion, WhatsAppTemplatesSettings, type WhatsAppTemplatesSettingsLabels, type WhatsAppTemplatesSettingsProps, WindowExpiredNotice, type WindowExpiredNoticeLabels, type WindowExpiredNoticeProps, type WindowOfParams, applyQuickReplyVariables, buildTranscriptFilename, buildTranscriptText, channelCapabilityFor, createMediaUrlResolver, downloadTextFile, filterQuickReplies, formatDateTime, formatFileSize, formatPhone, formatStalledFor, formatTimestamp, highlightMatch, htmlToWA, isReplyOverdue, isSameDay, isWindowBlocking, normalizeForSearch, parseWhatsAppFormatting, phoneInitials, queuedAttachmentsFromQuickReply, replyLatencyOf, resolveMaxAttachmentSizeBytes, resolveQuickReply, searchEmojis, toast, useConversationActions, useConversationContext, useConversationDocuments, useConversationList, useConversationLocales, useConversationMessages, useConversationRealtime, useConversations, useConversationsInbox, useDarkMode, useDebouncedValue, useGlobalRealtime, useInboxActions, useIsDarkTheme, useIsNarrow, useScrollToLatestMessage, useToast, useUrlArrayState, useUrlNumberState, useUrlStringState, useWaitingNotifications, waToHTML, waToHTMLInline, windowOf };
package/dist/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import {
2
- TOOLTIP_ATTRIBUTE,
3
- TooltipLayer,
4
2
  WhatsAppMessagePreview
5
- } from "./chunk-HMCOTZAX.js";
3
+ } from "./chunk-ZSOD5AQT.js";
4
+ import {
5
+ TOOLTIP_ATTRIBUTE,
6
+ TooltipLayer
7
+ } from "./chunk-NSOAUYNE.js";
6
8
  import {
7
9
  AudioPlayer,
8
10
  AudioRecorderButton,
@@ -25,7 +27,6 @@ import {
25
27
  DEFAULT_EMOJI_PICKER_LABELS,
26
28
  DEFAULT_INTERACTIVE_MESSAGE_LABELS,
27
29
  DEFAULT_LIGHTBOX_LABELS,
28
- DEFAULT_MAX_RECORDING_MILLISECONDS,
29
30
  DEFAULT_MESSAGE_COMPOSER_LABELS,
30
31
  DEFAULT_QUICK_REPLIES_PICKER_LABELS,
31
32
  DEFAULT_QUICK_REPLIES_WORKSPACE_LABELS,
@@ -59,7 +60,7 @@ import {
59
60
  useConversationLocales,
60
61
  useConversations,
61
62
  useQuickRepliesPicker
62
- } from "./chunk-L3OFAQPS.js";
63
+ } from "./chunk-Y326LLEP.js";
63
64
  import {
64
65
  ZERO_WIDTH_SPACE,
65
66
  cn,
@@ -75,6 +76,7 @@ import {
75
76
  CHANNEL_FILTER_ALL,
76
77
  CONVERSATION_CHANNEL,
77
78
  DEFAULT_CONVERSATION_CHANNEL,
79
+ DEFAULT_MAX_RECORDING_MILLISECONDS,
78
80
  HANDLE_KIND,
79
81
  REOPEN_MECHANISM,
80
82
  StatusTicks,
@@ -89,7 +91,7 @@ import {
89
91
  formatTimestamp,
90
92
  isSameDay,
91
93
  phoneInitials
92
- } from "./chunk-O6457XHK.js";
94
+ } from "./chunk-WCZNIJ3M.js";
93
95
 
94
96
  // src/RichMessageComposer.tsx
95
97
  import {
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import { ParticipantConversationSummary, ParticipantConversationPage, ParticipantSubjectRef, ParticipantMessage, ParticipantAttachment } from '@adatechnology/conversation-contracts';
4
- export { ParticipantAttachment, ParticipantConversationPage, ParticipantConversationSummary, ParticipantMessage, ParticipantSubjectRef } from '@adatechnology/conversation-contracts';
4
+ export { ParticipantAttachment, ParticipantConversationPage, ParticipantConversationSummary, ParticipantMessage, ParticipantSubjectRef, ParticipantTranscription } from '@adatechnology/conversation-contracts';
5
5
  import { C as ConversationChannel, d as ConversationsTheme, Q as QuickReply } from '../quickReply.types-DzWH3NYV.js';
6
6
 
7
7
  type ParticipantAuthorAvatarRenderer = (author: {
@@ -105,6 +105,50 @@ type ParticipantLocalPendingMessage = Omit<ParticipantPendingMessage, 'state'> &
105
105
  readonly state: 'sending' | 'queued' | 'failed' | 'sent';
106
106
  };
107
107
 
108
+ type ParticipantAudioRecordingOptions = {
109
+ /** Only lowers the default: a larger value is cut to DEFAULT_MAX_RECORDING_MILLISECONDS (5 min). */
110
+ readonly maxDurationMs?: number;
111
+ /** Only lowers the default: a larger value is cut to DEFAULT_MAX_RECORDING_BYTES (16 MiB, the app audio policy). */
112
+ readonly maxSizeBytes?: number;
113
+ /** True from `requesting` until it leaves `review`; the host feeds its capture registry. Never receives the audio. */
114
+ readonly onCaptureChange?: (isCapturing: boolean) => void;
115
+ };
116
+ declare const DEFAULT_MAX_RECORDING_BYTES: number;
117
+
118
+ type ParticipantAudioLabels = {
119
+ readonly recordAudio: string;
120
+ readonly recordingInProgress: string;
121
+ readonly stopRecording: string;
122
+ /** Uses the `{elapsed}` and `{limit}` placeholders. */
123
+ readonly recordingElapsed: string;
124
+ readonly reviewAudio: string;
125
+ readonly sendAudio: string;
126
+ readonly discardAudio: string;
127
+ readonly microphoneDenied: string;
128
+ readonly recordingUnsupported: string;
129
+ readonly audioEmpty: string;
130
+ readonly audioTooLarge: string;
131
+ readonly audioPlayer: string;
132
+ readonly playAudio: string;
133
+ readonly pauseAudio: string;
134
+ readonly audioPosition: string;
135
+ /** Uses the `{position}` and `{duration}` placeholders; without a duration only the position is spoken. */
136
+ readonly audioPositionValue: string;
137
+ /** Uses the `{rate}` placeholder. */
138
+ readonly playbackRate: string;
139
+ readonly audioUnavailable: string;
140
+ readonly transcribing: string;
141
+ /** Spoken by the thread's live region when a transcription finishes. */
142
+ readonly transcriptionReady: string;
143
+ readonly machineTranscription: string;
144
+ readonly emptyTranscription: string;
145
+ /** Uses the `{minutes}` placeholder, filled from the limit the server applied. */
146
+ readonly transcriptionTooLong: string;
147
+ readonly showFullTranscription: string;
148
+ readonly collapseTranscription: string;
149
+ };
150
+ declare const DEFAULT_PARTICIPANT_AUDIO_LABELS: ParticipantAudioLabels;
151
+
108
152
  type ParticipantConversationsLabels = {
109
153
  readonly inboxTitle: string;
110
154
  readonly sectionAwaiting: string;
@@ -140,9 +184,12 @@ type ParticipantConversationsLabels = {
140
184
  readonly statusRead: string;
141
185
  readonly statusFailed: string;
142
186
  readonly statusFailedShort: string;
187
+ /** @deprecated No longer rendered by the default view: the retry button is icon-only and named by `statusFailed`. */
143
188
  readonly retry: string;
144
189
  readonly discard: string;
145
190
  readonly edit: string;
191
+ /** Name of the menu button on a failed message. Optional; translated hosts should fill it, otherwise the English default shows. */
192
+ readonly messageOptions?: string;
146
193
  readonly notFound: string;
147
194
  readonly loading: string;
148
195
  readonly loadError: string;
@@ -167,7 +214,7 @@ type ParticipantConversationsLabels = {
167
214
  /** Prefix of the accessible name of the copy buttons: "Copy 529.982.247-25". */
168
215
  readonly copyValue: string;
169
216
  readonly valueCopied: string;
170
- };
217
+ } & Readonly<Partial<ParticipantAudioLabels>>;
171
218
  declare const DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS: ParticipantConversationsLabels;
172
219
 
173
220
  type ParticipantConversationsProps = {
@@ -195,6 +242,8 @@ type ParticipantConversationsProps = {
195
242
  renderAuthorAvatar?: ParticipantAuthorAvatarRenderer;
196
243
  /** Speech-bubble tail on the bottom corner; false removes it. Default true. */
197
244
  tail?: boolean;
245
+ /** Absent draws no microphone. Present lets the user record and send an audio as a message of its own. */
246
+ audioRecording?: ParticipantAudioRecordingOptions;
198
247
  };
199
248
  declare function ParticipantConversations(props: ParticipantConversationsProps): react.JSX.Element;
200
249
 
@@ -236,10 +285,12 @@ type ConversationThreadProps = {
236
285
  readonly tail?: boolean;
237
286
  readonly avatars?: 'initials';
238
287
  readonly renderAuthorAvatar?: ParticipantAuthorAvatarRenderer;
288
+ /** Absent draws no microphone. Present lets the user record and send an audio as a message of its own. */
289
+ readonly audioRecording?: ParticipantAudioRecordingOptions;
239
290
  };
240
291
  /** One conversation about one subject, drawn like the participant app and seen from either side. */
241
292
  declare function ConversationThread(props: ConversationThreadProps): react.JSX.Element;
242
293
 
243
294
  declare function groupParticipantConversations(params: GroupParticipantConversationsParams): ParticipantInboxView;
244
295
 
245
- export { ConversationThread, type ConversationThreadApi, type ConversationThreadProps, DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS, type GroupParticipantConversationsParams, type ParticipantAuthorAvatarRenderer, type ParticipantConversationEvent, ParticipantConversations, type ParticipantConversationsApi, type ParticipantConversationsClassNames, type ParticipantConversationsLabels, type ParticipantConversationsProps, type ParticipantInboxSection, type ParticipantInboxView, type ParticipantLocalPendingMessage, type ParticipantPendingMessage, type ParticipantPerspective, type ParticipantSendInput, type ParticipantSendResult, type ParticipantSubjectGroup, type ParticipantSubjectIconRenderer, groupParticipantConversations };
296
+ export { ConversationThread, type ConversationThreadApi, type ConversationThreadProps, DEFAULT_MAX_RECORDING_BYTES, DEFAULT_PARTICIPANT_AUDIO_LABELS, DEFAULT_PARTICIPANT_CONVERSATIONS_LABELS, type GroupParticipantConversationsParams, type ParticipantAudioLabels, type ParticipantAudioRecordingOptions, type ParticipantAuthorAvatarRenderer, type ParticipantConversationEvent, ParticipantConversations, type ParticipantConversationsApi, type ParticipantConversationsClassNames, type ParticipantConversationsLabels, type ParticipantConversationsProps, type ParticipantInboxSection, type ParticipantInboxView, type ParticipantLocalPendingMessage, type ParticipantPendingMessage, type ParticipantPerspective, type ParticipantSendInput, type ParticipantSendResult, type ParticipantSubjectGroup, type ParticipantSubjectIconRenderer, groupParticipantConversations };