@adatechnology/conversations-ui 0.1.0-rc.4 → 0.1.0-rc.5

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.
@@ -167,6 +167,15 @@ function AudioPlayer({ src, isMine = false }) {
167
167
 
168
168
  // src/FileIcon.tsx
169
169
  import { FileArchive, FileSpreadsheet, FileText, File as FileGeneric } from "lucide-react";
170
+
171
+ // src/lib/cn.ts
172
+ import { clsx } from "clsx";
173
+ import { twMerge } from "tailwind-merge";
174
+ function cn(...inputs) {
175
+ return twMerge(clsx(inputs));
176
+ }
177
+
178
+ // src/FileIcon.tsx
170
179
  import { jsx as jsx4 } from "react/jsx-runtime";
171
180
  var EXTENSION_STYLE = {
172
181
  pdf: { Icon: FileText, colorClass: "text-red-500" },
@@ -176,16 +185,16 @@ var EXTENSION_STYLE = {
176
185
  xlsx: { Icon: FileSpreadsheet, colorClass: "text-green-600" },
177
186
  zip: { Icon: FileArchive, colorClass: "text-orange-500" }
178
187
  };
179
- function getExtension(filename, mimeType) {
188
+ function resolveFileIconExtension(filename, mimeType) {
180
189
  const fromFilename = filename?.split(".").pop()?.toLowerCase();
181
190
  if (fromFilename && EXTENSION_STYLE[fromFilename]) return fromFilename;
182
191
  return mimeType?.split("/")[1]?.toLowerCase() ?? "";
183
192
  }
184
- function FileIcon({ filename, mimeType, size = 20, className = "" }) {
185
- const extension = getExtension(filename, mimeType);
193
+ function FileIcon({ filename, mimeType, size = 20, className }) {
194
+ const extension = resolveFileIconExtension(filename, mimeType);
186
195
  const style = EXTENSION_STYLE[extension] ?? { Icon: FileGeneric, colorClass: "text-gray-500" };
187
196
  const { Icon, colorClass } = style;
188
- return /* @__PURE__ */ jsx4(Icon, { size, className: `${colorClass} ${className}`.trim() });
197
+ return /* @__PURE__ */ jsx4(Icon, { size, className: cn(colorClass, className) });
189
198
  }
190
199
 
191
200
  // src/lib/format.ts
@@ -250,7 +259,7 @@ function useLazyMediaUrl(message, onResolveUrl) {
250
259
  };
251
260
  return { url, loading, error, load };
252
261
  }
253
- function MediaRenderer({ message, onLightbox, onResolveUrl }) {
262
+ function MediaRenderer({ message, onLightbox, onResolveUrl, className }) {
254
263
  const { bubble } = useConversationLocales();
255
264
  const eagerSrc = resolveMediaSource(message);
256
265
  const lazy = useLazyMediaUrl(message, onResolveUrl);
@@ -287,7 +296,7 @@ function MediaRenderer({ message, onLightbox, onResolveUrl }) {
287
296
  case "document": {
288
297
  const typeLabel = message.mimeType?.split("/")[1]?.toUpperCase() ?? "FILE";
289
298
  const sizeLabel = message.sizeBytes ? formatFileSize(message.sizeBytes) : null;
290
- return /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3 min-w-[200px]", children: [
299
+ return /* @__PURE__ */ jsxs3("div", { className: cn("flex items-center gap-3 min-w-[200px]", className), children: [
291
300
  /* @__PURE__ */ jsx5("div", { className: "w-10 h-10 bg-gray-200 rounded-lg flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx5(FileIcon, { filename: message.filename, mimeType: message.mimeType }) }),
292
301
  /* @__PURE__ */ jsxs3("div", { className: "flex-1 min-w-0", children: [
293
302
  /* @__PURE__ */ jsx5("p", { className: "text-sm font-medium truncate", children: message.filename ?? bubble.untitledDocument }),
@@ -332,15 +341,6 @@ function Lightbox({ imageUrl, caption, onClose }) {
332
341
  // src/MessageBubble.tsx
333
342
  import { useState as useState3 } from "react";
334
343
  import { Check } from "lucide-react";
335
-
336
- // src/lib/cn.ts
337
- import { clsx } from "clsx";
338
- import { twMerge } from "tailwind-merge";
339
- function cn(...inputs) {
340
- return twMerge(clsx(inputs));
341
- }
342
-
343
- // src/MessageBubble.tsx
344
344
  import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
345
345
  var BUBBLE_COLOR = {
346
346
  agent: "bg-[#d9fdd3] dark:bg-[#005c4b]",
@@ -712,12 +712,14 @@ export {
712
712
  useConversationLocales,
713
713
  StatusTicks,
714
714
  AudioPlayer,
715
+ cn,
715
716
  FileIcon,
716
717
  formatTimestamp,
718
+ formatDateTime,
719
+ isSameDay,
717
720
  formatFileSize,
718
721
  MediaRenderer,
719
722
  Lightbox,
720
- cn,
721
723
  MessageBubble,
722
724
  ConversationWallpaper,
723
725
  EmojiPicker,
package/dist/index.d.ts CHANGED
@@ -1,15 +1,17 @@
1
1
  import * as react from 'react';
2
2
  import react__default, { ReactNode, FormEvent } from 'react';
3
- import { M as MessagePayload, k as ConversationsFeatures, i as ConversationSummary, f as ConversationChannel, j as ConversationsApi, S as SSEProvider, g as ConversationDocument } from './types-C0PtaO7S.js';
4
- export { C as CHANNEL_CAPABILITIES, a as CHANNEL_FILTER_ALL, b as CONVERSATION_CHANNEL, c as ChannelCapabilities, d as ChannelFilter, e as ChannelFilterOption, h as ConversationEventSource, l as ConversationsTheme, m as ConversationsUIConfig, D as DEFAULT_CONVERSATION_CHANNEL, F as FormatContactHandleParams, H as HANDLE_KIND, n as HandleKind, R as REOPEN_MECHANISM, o as ReopenMechanism, p as capabilitiesOf, q as channelFiltersFor, r as contactFlag, s as formatContactHandle } from './types-C0PtaO7S.js';
3
+ import { M as MessagePayload, n as ConversationsFeatures, k as ConversationSummary, f as ConversationChannel, L as ListConversationsParams, m as ConversationsApi, S as SSEProvider, r as ListDocumentsParams, g as ConversationDocument, l as ConversationTemplate } from './types-C2Yexi8A.js';
4
+ export { C as CHANNEL_CAPABILITIES, a as CHANNEL_FILTER_ALL, b as CONVERSATION_CHANNEL, c as ChannelCapabilities, d as ChannelFilter, e as ChannelFilterOption, h as ConversationDocumentPage, i as ConversationEventSource, j as ConversationPage, o as ConversationsTheme, p as ConversationsUIConfig, D as DEFAULT_CONVERSATION_CHANNEL, F as FormatContactHandleParams, H as HANDLE_KIND, q as HandleKind, R as REOPEN_MECHANISM, s as ReopenMechanism, t as capabilitiesOf, u as channelFiltersFor, v as contactFlag, w as formatContactHandle } from './types-C2Yexi8A.js';
5
5
 
6
6
  type ResolveMediaUrl = (message: MessagePayload) => Promise<string | null>;
7
7
  interface MediaRendererProps {
8
8
  message: MessagePayload;
9
9
  onLightbox: (src: string) => void;
10
10
  onResolveUrl?: ResolveMediaUrl;
11
+ /** Aplicado no wrapper de cada tipo de mídia — imagem, vídeo, áudio e documento. */
12
+ className?: string;
11
13
  }
12
- declare function MediaRenderer({ message, onLightbox, onResolveUrl }: MediaRendererProps): react.JSX.Element | null;
14
+ declare function MediaRenderer({ message, onLightbox, onResolveUrl, className }: MediaRendererProps): react.JSX.Element | null;
13
15
 
14
16
  interface MessageBubbleProps {
15
17
  message: MessagePayload;
@@ -380,37 +382,69 @@ declare function WindowExpiredNotice({ onSendTemplate, disabled, labels: labelsO
380
382
  */
381
383
  declare function isWindowBlocking(window: ConversationWindow): boolean;
382
384
 
383
- /**
384
- * Arquivos trocados na conversa. Sai do transcript e vira lista própria porque anexo é o que o
385
- * atendente mais precisa reencontrar depois — rolar meses de mensagens para achar um comprovante é
386
- * o caso que a busca por documento existe para eliminar.
387
- *
388
- * Usa `useConversationDocuments`, então funciona com qualquer `ConversationsApi`. Host sem
389
- * biblioteca de documentos cai no estado vazio, sem quebrar.
390
- */
391
385
  interface ConversationDocumentsPanelLabels {
392
386
  toggle: string;
393
387
  title: string;
394
388
  searchPlaceholder: string;
395
389
  empty: string;
390
+ /** Distinto de `empty`: sem resultado POR CAUSA do filtro, e não conversa sem anexo nenhum. */
391
+ noResults: string;
396
392
  loading: string;
397
393
  failure: string;
398
394
  download: string;
395
+ view: string;
396
+ sourceFilterAll: string;
397
+ sourceFilterCustomer: string;
398
+ sourceFilterTeam: string;
399
+ sortMostRecent: string;
400
+ sortOldest: string;
401
+ clearFilters: string;
402
+ selectAll: string;
403
+ downloadSelected: (count: number) => string;
404
+ archiveFailed: string;
405
+ total: (count: number) => string;
406
+ page: (current: number, last: number) => string;
399
407
  }
400
408
  declare const DEFAULT_CONVERSATION_DOCUMENTS_LABELS: ConversationDocumentsPanelLabels;
409
+ /**
410
+ * Partes estilizáveis do painel, no mesmo contrato do `ConversationHeader`: `cn` funde por cima da
411
+ * base e conflito de utilitário (padding, tamanho de fonte, borda) fica com o valor do produto.
412
+ *
413
+ * `status` cobre carregando/erro/vazio de uma vez — são a mesma linha de texto auxiliar, e slots
414
+ * separados só multiplicariam chave para quem quer mudar a cor de aviso.
415
+ */
401
416
  interface ConversationDocumentsPanelClassNames {
402
417
  root: string;
403
418
  body: string;
419
+ title: string;
420
+ filters: string;
421
+ search: string;
422
+ sourceSelect: string;
423
+ sortButton: string;
424
+ clearButton: string;
425
+ status: string;
426
+ list: string;
427
+ item: string;
428
+ sourceBadge: string;
429
+ filename: string;
430
+ meta: string;
431
+ viewButton: string;
432
+ downloadButton: string;
433
+ pagination: string;
434
+ selectionBar: string;
435
+ checkbox: string;
404
436
  }
405
437
  interface ConversationDocumentsPanelProps {
406
438
  conversationId: string;
407
439
  /** Controlado de fora porque o gatilho vive no cabeçalho, junto das outras ações da conversa. */
408
440
  open: boolean;
441
+ /** Itens por página. O total vem do servidor; sem paginação no host, a barra não aparece. */
442
+ perPage?: number;
409
443
  labels?: Partial<ConversationDocumentsPanelLabels>;
410
444
  className?: string;
411
445
  classNames?: Partial<ConversationDocumentsPanelClassNames>;
412
446
  }
413
- declare function ConversationDocumentsPanel({ conversationId, open, labels: labelsOverride, className, classNames, }: ConversationDocumentsPanelProps): react.JSX.Element | null;
447
+ declare function ConversationDocumentsPanel({ conversationId, open, perPage, labels: labelsOverride, className, classNames, }: ConversationDocumentsPanelProps): react.JSX.Element | null;
414
448
 
415
449
  /**
416
450
  * Serialização do transcript para download. Fica no pacote porque o formato de um histórico de
@@ -461,11 +495,35 @@ declare function useDarkMode(): {
461
495
  declare const NARROW_MAX_WIDTH_PX = 1023;
462
496
  declare function useIsNarrow(): boolean;
463
497
 
498
+ interface UseWaitingNotificationsLabels {
499
+ /** Título da notificação do sistema. Recebe a conversa para o host escolher nome × número. */
500
+ title: (conversation: ConversationSummary) => string;
501
+ body: (conversation: ConversationSummary) => string;
502
+ }
503
+ interface UseWaitingNotificationsParams {
504
+ /**
505
+ * Repassado cru ao `fetchConversations`. É o que permite filtrar não lidas **no servidor** em
506
+ * vez de baixar a lista inteira e contar no cliente: um painel com milhares de conversas não
507
+ * pode paginar 50 por vez atrás de quem tem `unread > 0`.
508
+ */
509
+ readonly params?: ListConversationsParams;
510
+ readonly intervalMs?: number;
511
+ /** Desliga o polling sem desmontar quem chama — útil com a aba em segundo plano. */
512
+ readonly enabled?: boolean;
513
+ readonly icon?: string;
514
+ readonly labels?: Partial<UseWaitingNotificationsLabels>;
515
+ }
464
516
  interface UseWaitingNotificationsResult {
465
517
  unreadCount: number;
466
518
  conversations: ConversationSummary[];
519
+ /**
520
+ * Releitura sob demanda. Existe porque o polling é o piso, não o mecanismo: quem já recebe SSE
521
+ * ou acabou de marcar tudo como lido sabe da mudança antes do próximo tick, e esperar 10s para
522
+ * o contador acompanhar faz a interface parecer travada.
523
+ */
524
+ refresh: () => Promise<void>;
467
525
  }
468
- declare function useWaitingNotifications(): UseWaitingNotificationsResult;
526
+ declare function useWaitingNotifications(params?: UseWaitingNotificationsParams): UseWaitingNotificationsResult;
469
527
 
470
528
  interface ConversationsContextValue {
471
529
  api: ConversationsApi;
@@ -684,7 +742,7 @@ interface UseConversationMessagesResult {
684
742
  caption?: string;
685
743
  }) => Promise<MessagePayload>;
686
744
  sendTemplate: (data: {
687
- templateName: string;
745
+ templateName?: string;
688
746
  languageCode?: string;
689
747
  bodyParams?: string[];
690
748
  }) => Promise<void>;
@@ -695,14 +753,11 @@ declare function useConversationMessages(conversationId: string, params?: {
695
753
  before?: string;
696
754
  }): UseConversationMessagesResult;
697
755
 
698
- interface UseConversationListParams {
699
- page?: number;
700
- limit?: number;
701
- waitingHuman?: boolean;
702
- search?: string;
703
- }
756
+ type UseConversationListParams = ListConversationsParams;
704
757
  interface UseConversationListResult {
705
758
  conversations: ConversationSummary[];
759
+ /** Total no servidor. Cai para o tamanho da página quando a API devolve só o array. */
760
+ total: number;
706
761
  loading: boolean;
707
762
  error: Error | undefined;
708
763
  refetch: () => Promise<void>;
@@ -717,12 +772,11 @@ interface UseConversationContextResult {
717
772
  }
718
773
  declare function useConversationContext(conversationId: string): UseConversationContextResult;
719
774
 
720
- interface UseConversationDocumentsParams {
721
- search?: string;
722
- page?: number;
723
- }
775
+ type UseConversationDocumentsParams = ListDocumentsParams;
724
776
  interface UseConversationDocumentsResult {
725
777
  documents: ConversationDocument[];
778
+ /** Total no servidor. Cai para o tamanho da página quando a API devolve só o array. */
779
+ total: number;
726
780
  loading: boolean;
727
781
  error: Error | undefined;
728
782
  refetch: () => Promise<void>;
@@ -733,6 +787,27 @@ type ConversationRealtimeHandler = (event: MessageEvent) => void;
733
787
  declare function useConversationRealtime(conversationId: string | undefined, onEvent: ConversationRealtimeHandler): void;
734
788
  declare function useGlobalRealtime(onEvent: ConversationRealtimeHandler): void;
735
789
 
790
+ interface UseConversationActionsResult {
791
+ /** `undefined` quando a API do host não implementa a operação — a UI esconde a afordância. */
792
+ takeover: (() => Promise<void>) | undefined;
793
+ release: (() => Promise<void>) | undefined;
794
+ finalize: (() => Promise<void>) | undefined;
795
+ }
796
+ /**
797
+ * Ações de atendimento de UMA conversa, já ligadas ao id.
798
+ *
799
+ * Separado de `useConversationMessages` porque assumir e devolver conversa também acontece a
800
+ * partir da lista, onde nenhuma thread está aberta — embutir nas mensagens obrigaria a carregar
801
+ * a thread inteira só para desenhar um botão na linha.
802
+ */
803
+ declare function useConversationActions(conversationId: string): UseConversationActionsResult;
804
+ interface UseInboxActionsResult {
805
+ markAllRead: (() => Promise<void>) | undefined;
806
+ listTemplates: (() => Promise<ConversationTemplate[]>) | undefined;
807
+ }
808
+ /** Ações que valem para a caixa inteira, sem conversa selecionada. */
809
+ declare function useInboxActions(): UseInboxActionsResult;
810
+
736
811
  declare function parseWhatsAppFormatting(text: string): ReactNode[];
737
812
  declare function waToHTML(text: string): string;
738
813
  declare function htmlToWA(html: string): string;
@@ -742,6 +817,8 @@ declare function formatPhone(number: string): string;
742
817
  declare function phoneInitials(number: string): string;
743
818
 
744
819
  declare function formatTimestamp(timestamp: string): string;
820
+ declare function formatDateTime(iso: string): string;
821
+ declare function isSameDay(a: Date, b: Date): boolean;
745
822
  declare function formatFileSize(bytes: number): string;
746
823
 
747
824
  interface AsyncResourceState<T> {
@@ -751,4 +828,4 @@ interface AsyncResourceState<T> {
751
828
  refetch: () => Promise<void>;
752
829
  }
753
830
 
754
- export { type AsyncResourceState, AudioPlayer, type AudioPlayerProps, Avatar, type AvatarProps, type BuildTranscriptTextParams, CHANNEL_BRAND_COLOR, CONVERSATION_WINDOW, ChannelIcon, type ChannelIconProps, ConversationChannel, type ConversationContextEntry, ConversationContextPanel, type ConversationContextPanelClassNames, type ConversationContextPanelLabels, type ConversationContextPanelProps, ConversationDocument, ConversationDocumentsPanel, type ConversationDocumentsPanelClassNames, type ConversationDocumentsPanelLabels, type ConversationDocumentsPanelProps, ConversationHeader, type ConversationHeaderClassNames, type ConversationHeaderLabels, type ConversationHeaderProps, ConversationListItem, type ConversationListItemProps, type ConversationLocales, ConversationLocalesProvider, type ConversationLocalesProviderProps, type ConversationRealtimeHandler, ConversationRow, type ConversationRowClassNames, type ConversationRowProps, ConversationSummary, ConversationWallpaper, type ConversationWallpaperProps, type ConversationWindow, ConversationsApi, ConversationsFeatures, ConversationsProvider, DEFAULT_CONVERSATION_CONTEXT_LABELS, DEFAULT_CONVERSATION_DOCUMENTS_LABELS, DEFAULT_CONVERSATION_HEADER_LABELS, DEFAULT_TEMPLATES_SETTINGS_LABELS, DEFAULT_WINDOW_EXPIRED_LABELS, DateDivider, type DateDividerClassNames, type DateDividerProps, EmojiPicker, type EmojiPickerProps, FileIcon, type FileIconProps, Lightbox, type LightboxProps, MediaRenderer, type MediaRendererProps, MessageBubble, type MessageBubbleProps, MessageComposer, type MessageComposerClassNames, type MessageComposerProps, MessagePayload, MessageTail, MessageText, type MessageTextProps, MessageTimestamp, NARROW_MAX_WIDTH_PX, type ResolveMediaUrl, SSEProvider, SimpleEmojiPicker, type SimpleEmojiPickerProps, StatusTicks, type StatusTicksProps, TEMPLATE_SETTINGS_TAB, type TemplateSettingsTab, ToastProvider, type TopicItem, TopicsForm, type TopicsFormLabels, type TopicsFormProps, type UseConversationContextResult, type UseConversationDocumentsParams, type UseConversationDocumentsResult, type UseConversationListParams, type UseConversationListResult, type UseConversationMessagesResult, WINDOW_FILTERS, WelcomeFarewellForm, type WelcomeFarewellFormLabels, type WelcomeFarewellFormProps, WhatsAppCreateTemplateForm, type WhatsAppCreateTemplateFormLabels, type WhatsAppCreateTemplateFormProps, type WhatsAppCreateTemplateResult, type WhatsAppCreateTemplateState, WhatsAppMessageEditor, type WhatsAppMessageEditorProps, type WhatsAppTemplateHeaderType, WhatsAppTemplateSettingsForm, type WhatsAppTemplateSettingsFormLabels, type WhatsAppTemplateSettingsFormProps, type WhatsAppTemplateSummary, type WhatsAppTemplateVariableSuggestion, WhatsAppTemplatesSettings, type WhatsAppTemplatesSettingsLabels, type WhatsAppTemplatesSettingsProps, WindowExpiredNotice, type WindowExpiredNoticeLabels, type WindowExpiredNoticeProps, type WindowOfParams, buildTranscriptFilename, buildTranscriptText, downloadTextFile, formatFileSize, formatPhone, formatStalledFor, formatTimestamp, htmlToWA, isWindowBlocking, parseWhatsAppFormatting, phoneInitials, toast, useConversationContext, useConversationDocuments, useConversationList, useConversationLocales, useConversationMessages, useConversationRealtime, useConversations, useDarkMode, useGlobalRealtime, useIsDarkTheme, useIsNarrow, useToast, useWaitingNotifications, waToHTML, waToHTMLInline, windowOf };
831
+ export { type AsyncResourceState, AudioPlayer, type AudioPlayerProps, Avatar, type AvatarProps, type BuildTranscriptTextParams, CHANNEL_BRAND_COLOR, CONVERSATION_WINDOW, ChannelIcon, type ChannelIconProps, ConversationChannel, type ConversationContextEntry, ConversationContextPanel, type ConversationContextPanelClassNames, type ConversationContextPanelLabels, type ConversationContextPanelProps, ConversationDocument, ConversationDocumentsPanel, type ConversationDocumentsPanelClassNames, type ConversationDocumentsPanelLabels, type ConversationDocumentsPanelProps, ConversationHeader, type ConversationHeaderClassNames, type ConversationHeaderLabels, type ConversationHeaderProps, ConversationListItem, type ConversationListItemProps, type ConversationLocales, ConversationLocalesProvider, type ConversationLocalesProviderProps, type ConversationRealtimeHandler, ConversationRow, type ConversationRowClassNames, type ConversationRowProps, ConversationSummary, ConversationTemplate, ConversationWallpaper, type ConversationWallpaperProps, type ConversationWindow, ConversationsApi, ConversationsFeatures, ConversationsProvider, DEFAULT_CONVERSATION_CONTEXT_LABELS, DEFAULT_CONVERSATION_DOCUMENTS_LABELS, DEFAULT_CONVERSATION_HEADER_LABELS, DEFAULT_TEMPLATES_SETTINGS_LABELS, DEFAULT_WINDOW_EXPIRED_LABELS, DateDivider, type DateDividerClassNames, type DateDividerProps, EmojiPicker, type EmojiPickerProps, FileIcon, type FileIconProps, Lightbox, type LightboxProps, ListConversationsParams, ListDocumentsParams, MediaRenderer, type MediaRendererProps, MessageBubble, type MessageBubbleProps, MessageComposer, type MessageComposerClassNames, type MessageComposerProps, MessagePayload, MessageTail, MessageText, type MessageTextProps, MessageTimestamp, NARROW_MAX_WIDTH_PX, type ResolveMediaUrl, SSEProvider, SimpleEmojiPicker, type SimpleEmojiPickerProps, StatusTicks, type StatusTicksProps, TEMPLATE_SETTINGS_TAB, type TemplateSettingsTab, ToastProvider, type TopicItem, TopicsForm, type TopicsFormLabels, type TopicsFormProps, type UseConversationActionsResult, type UseConversationContextResult, type UseConversationDocumentsParams, type UseConversationDocumentsResult, type UseConversationListParams, type UseConversationListResult, type UseConversationMessagesResult, type UseInboxActionsResult, type UseWaitingNotificationsLabels, type UseWaitingNotificationsParams, type UseWaitingNotificationsResult, WINDOW_FILTERS, WelcomeFarewellForm, type WelcomeFarewellFormLabels, type WelcomeFarewellFormProps, WhatsAppCreateTemplateForm, type WhatsAppCreateTemplateFormLabels, type WhatsAppCreateTemplateFormProps, type WhatsAppCreateTemplateResult, type WhatsAppCreateTemplateState, WhatsAppMessageEditor, type WhatsAppMessageEditorProps, type WhatsAppTemplateHeaderType, WhatsAppTemplateSettingsForm, type WhatsAppTemplateSettingsFormLabels, type WhatsAppTemplateSettingsFormProps, type WhatsAppTemplateSummary, type WhatsAppTemplateVariableSuggestion, WhatsAppTemplatesSettings, type WhatsAppTemplatesSettingsLabels, type WhatsAppTemplatesSettingsProps, WindowExpiredNotice, type WindowExpiredNoticeLabels, type WindowExpiredNoticeProps, type WindowOfParams, buildTranscriptFilename, buildTranscriptText, downloadTextFile, formatDateTime, formatFileSize, formatPhone, formatStalledFor, formatTimestamp, htmlToWA, isSameDay, isWindowBlocking, parseWhatsAppFormatting, phoneInitials, toast, useConversationActions, useConversationContext, useConversationDocuments, useConversationList, useConversationLocales, useConversationMessages, useConversationRealtime, useConversations, useDarkMode, useGlobalRealtime, useInboxActions, useIsDarkTheme, useIsNarrow, useToast, useWaitingNotifications, waToHTML, waToHTMLInline, windowOf };