@adatechnology/notification-ui 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -611,6 +611,7 @@ function MessageBodyField({ value, rows = 5, onChange, onSelect, onFocus, labelO
|
|
|
611
611
|
}
|
|
612
612
|
|
|
613
613
|
// src/components/TemplatePreview.tsx
|
|
614
|
+
import { parseWhatsAppFormatting } from "@adatechnology/conversations-ui";
|
|
614
615
|
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
615
616
|
function StatusIcons() {
|
|
616
617
|
return /* @__PURE__ */ jsxs9("span", { className: "adn-preview-status__icons", children: [
|
|
@@ -860,7 +861,7 @@ function WhatsAppPreview({
|
|
|
860
861
|
/* @__PURE__ */ jsx9("div", { className: "adn-preview-wa__day", children: labels.today }),
|
|
861
862
|
/* @__PURE__ */ jsxs9("div", { className: "adn-preview-wa__bubble", children: [
|
|
862
863
|
attachment ? /* @__PURE__ */ jsx9(AttachmentCard, { attachment, block: "adn-preview-attachment--wa" }) : null,
|
|
863
|
-
/* @__PURE__ */ jsx9("div", { className: "adn-preview-wa__text", children: rendered.body }),
|
|
864
|
+
/* @__PURE__ */ jsx9("div", { className: "adn-preview-wa__text", children: parseWhatsAppFormatting(rendered.body) }),
|
|
864
865
|
/* @__PURE__ */ jsx9("div", { className: "adn-preview-wa__time", children: labels.now })
|
|
865
866
|
] })
|
|
866
867
|
] }),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/NotificationBell.tsx","../src/components/NotificationList.tsx","../src/components/NotificationItem.tsx","../src/components/PreferencesPanel.tsx","../src/components/NotificationsWorkspace.tsx","../src/components/NotificationSettingsWorkspace.tsx","../src/components/HtmlCodeField.tsx","../src/htmlHighlight.util.ts","../src/components/MessageBodyField.tsx","../src/messageFormat.util.ts","../src/components/MessageToolbar.tsx","../src/messageFormat.constant.ts","../src/components/TemplatePreview.tsx"],"sourcesContent":["/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n */\n\nimport { Bell } from 'lucide-react'\nimport clsx from 'clsx'\n\nimport { useNotificationContext } from '../NotificationProvider'\nimport { useUnreadCount } from '../hooks/useNotifications'\n\nexport type NotificationBellProps = {\n readonly onClick?: () => void\n readonly className?: string\n /** Acima disso o badge mostra `99+`; um número de 4 dígitos estoura o desenho do badge. */\n readonly maxBadgeCount?: number\n}\n\nconst DEFAULT_MAX_BADGE_COUNT = 99\n\nexport function NotificationBell({\n onClick,\n className,\n maxBadgeCount = DEFAULT_MAX_BADGE_COUNT,\n}: NotificationBellProps) {\n const { messages, theme } = useNotificationContext()\n const { data: unreadCount = 0 } = useUnreadCount()\n\n const hasUnread = unreadCount > 0\n const badgeLabel = unreadCount > maxBadgeCount ? `${maxBadgeCount}+` : String(unreadCount)\n const accessibleLabel = hasUnread\n ? `${messages['bell.label']}: ${unreadCount} ${messages['bell.unreadSuffix']}`\n : messages['bell.label']\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={clsx('adn-bell', theme.rootClassName, className)}\n // Botão só-ícone exige rótulo acessível (regra de ícones, `web.md` §9).\n aria-label={accessibleLabel}\n >\n {/* Decorativo: o rótulo acessível já está no botão, e anunciar o ícone repetiria a ação. */}\n <Bell className=\"adn-bell__icon\" aria-hidden=\"true\" />\n {hasUnread ? (\n // `aria-live` para leitor de tela anunciar a mudança do contador sem o usuário reabrir\n // o menu; `polite` porque notificação nova não deve interromper o que ele está lendo.\n <span className=\"adn-bell__badge\" aria-live=\"polite\">\n {badgeLabel}\n </span>\n ) : null}\n </button>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n */\n\nimport { CheckCheck, Inbox, RotateCw } from 'lucide-react'\nimport clsx from 'clsx'\nimport type { ReactNode } from 'react'\nimport type { NotificationSummary } from '@adatechnology/notification-contracts'\n\nimport { useNotificationContext } from '../NotificationProvider'\nimport { flattenNotificationPages, useMarkAllAsRead, useNotifications, useUnreadCount } from '../hooks/useNotifications'\nimport { NotificationItem } from './NotificationItem'\n\n/** Três linhas: o bastante para a lista já ter a forma dela antes de ter conteúdo. */\nconst SKELETON_ROWS = [0, 1, 2]\n\nexport type NotificationListProps = {\n readonly category?: string\n readonly onSelect?: (notification: NotificationSummary) => void\n readonly className?: string\n /**\n * Substitui o vazio padrão. Quem decide se está vazio é a lista — o host que desenhava o próprio\n * vazio ao lado dela mostrava \"nada por aqui\" embaixo das notificações que estavam ali.\n */\n readonly renderEmpty?: () => ReactNode\n /** Slot: o host troca a linha sem reimplementar a lista (regra §4.3, slots e overrides). */\n readonly components?: { readonly Item?: typeof NotificationItem }\n}\n\nexport function NotificationList({ category, onSelect, className, renderEmpty, components }: NotificationListProps) {\n const { messages, theme } = useNotificationContext()\n const query = useNotifications({ category })\n const { data: unreadCount = 0 } = useUnreadCount()\n const markAllAsRead = useMarkAllAsRead()\n\n const Item = components?.Item ?? NotificationItem\n const notifications = flattenNotificationPages(query.data?.pages)\n const isEmpty = !query.isPending && !query.isError && notifications.length === 0\n\n return (\n <section className={clsx('adn-list', theme.rootClassName, className)} aria-label={messages['list.title']}>\n <header className=\"adn-list__header\">\n <div className=\"adn-list__heading\">\n <h2 className=\"adn-list__title\">{messages['list.title']}</h2>\n {/* O contador estava só no sino. Quem abriu a tela pelo menu lateral não passou pelo sino,\n e ficava sem saber quantas ainda pedem atenção. */}\n {unreadCount > 0 ? (\n <span className=\"adn-list__count\" role=\"status\" aria-label={`${unreadCount} ${messages['list.unread']}`}>\n {unreadCount}\n </span>\n ) : null}\n </div>\n\n {unreadCount > 0 ? (\n <button\n type=\"button\"\n className=\"adn-list__bulk-action\"\n onClick={() => markAllAsRead.mutate()}\n disabled={markAllAsRead.isPending}\n >\n <CheckCheck className=\"adn-list__bulk-icon\" aria-hidden=\"true\" />\n {messages['list.markAllAsRead']}\n </button>\n ) : null}\n </header>\n\n {/* Esqueleto com a forma da linha real, em vez de \"Carregando…\" centralizado: o texto some e o\n conteúdo entra de altura diferente, e a tela pisca a cada carregamento. */}\n {query.isPending ? (\n <div className=\"adn-list__skeleton\" role=\"status\" aria-label={messages['list.loading']}>\n {SKELETON_ROWS.map((row) => (\n <span key={row} className=\"adn-list__skeleton-row\" />\n ))}\n </div>\n ) : null}\n\n {query.isError ? (\n <div className=\"adn-list__state adn-list__state--error\" role=\"alert\">\n <p>{messages['list.error']}</p>\n <button type=\"button\" className=\"adn-list__retry\" onClick={() => void query.refetch()}>\n <RotateCw className=\"adn-list__retry-icon\" aria-hidden=\"true\" />\n {messages['list.retry']}\n </button>\n </div>\n ) : null}\n\n {isEmpty\n ? (renderEmpty?.() ?? (\n <div className=\"adn-list__state adn-list__state--empty\">\n <Inbox className=\"adn-list__empty-icon\" aria-hidden=\"true\" />\n <p>{messages['list.empty']}</p>\n </div>\n ))\n : null}\n\n {notifications.length > 0 ? (\n <ul className=\"adn-list__items\">\n {notifications.map((notification) => (\n <Item key={notification.id} notification={notification} onSelect={onSelect} />\n ))}\n </ul>\n ) : null}\n\n {query.hasNextPage ? (\n <div className=\"adn-list__footer\">\n <button\n type=\"button\"\n className=\"adn-list__load-more\"\n onClick={() => void query.fetchNextPage()}\n disabled={query.isFetchingNextPage}\n >\n {messages['list.loadMore']}\n </button>\n </div>\n ) : null}\n </section>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n */\n\nimport { Check, Trash2 } from 'lucide-react'\nimport clsx from 'clsx'\nimport type { NotificationSummary } from '@adatechnology/notification-contracts'\n\nimport { useNotificationContext } from '../NotificationProvider'\nimport { formatNotificationTime, formatNotificationTimestamp } from '../format/notificationTime'\nimport { useDeleteNotification, useMarkAsRead } from '../hooks/useNotifications'\n\nexport type NotificationItemProps = {\n readonly notification: NotificationSummary\n readonly onSelect?: (notification: NotificationSummary) => void\n readonly className?: string\n}\n\nexport function NotificationItem({ notification, onSelect, className }: NotificationItemProps) {\n const { locale, messages } = useNotificationContext()\n const markAsRead = useMarkAsRead()\n const deleteNotification = useDeleteNotification()\n\n const isUnread = notification.readAt === undefined\n\n function handleSelect(): void {\n if (isUnread) markAsRead.mutate(notification.id)\n onSelect?.(notification)\n }\n\n return (\n <li className={clsx('adn-item', isUnread && 'adn-item--unread', className)}>\n {/* Semântico: a linha inteira é clicável e precisa ser alcançável por teclado — `button`\n entrega Enter, Espaço e foco de graça, e um `div` com onClick não (web.md §Acessibilidade). */}\n <button type=\"button\" className=\"adn-item__main\" onClick={handleSelect}>\n <span className=\"adn-item__heading\">\n {/* Marcador à esquerda, na altura do título: sobreposto ao canto, ele cobria a última\n palavra do texto em linha comprida. */}\n {isUnread ? <span className=\"adn-item__unread-dot\" aria-label={messages['item.unread']} /> : null}\n <span className=\"adn-item__title\">{notification.title}</span>\n {/* `<time>` e não `<span>`: a data legível por máquina é o que um leitor de tela e um\n agregador conseguem interpretar; o texto visível é o relativo, que é o que se lê. */}\n <time\n className=\"adn-item__time\"\n dateTime={notification.createdAt}\n title={formatNotificationTimestamp(notification.createdAt, locale)}\n >\n {formatNotificationTime(notification.createdAt, locale, new Date())}\n </time>\n </span>\n <span className=\"adn-item__body\">{notification.body}</span>\n </button>\n\n <div className=\"adn-item__actions\">\n {isUnread ? (\n <button\n type=\"button\"\n className=\"adn-item__action\"\n onClick={() => markAsRead.mutate(notification.id)}\n disabled={markAsRead.isPending}\n aria-label={messages['item.markAsRead']}\n title={messages['item.markAsRead']}\n >\n <Check className=\"adn-item__action-icon\" aria-hidden=\"true\" />\n </button>\n ) : null}\n\n <button\n type=\"button\"\n className=\"adn-item__action adn-item__action--danger\"\n onClick={() => deleteNotification.mutate(notification.id)}\n disabled={deleteNotification.isPending}\n aria-label={messages['item.delete']}\n title={messages['item.delete']}\n >\n {/* Ação destrutiva: ícone reforça o peso antes do clique (regra de ícones). */}\n <Trash2 className=\"adn-item__action-icon\" aria-hidden=\"true\" />\n </button>\n </div>\n </li>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n */\n\nimport { useState } from 'react'\nimport { Save } from 'lucide-react'\nimport clsx from 'clsx'\nimport type { NotificationPreference } from '@adatechnology/notification-contracts'\n\nimport { useNotificationContext } from '../NotificationProvider'\nimport { usePreferences, useUpdatePreferences } from '../hooks/usePreferences'\n\nexport type PreferencesPanelProps = {\n readonly className?: string\n}\n\nfunction channelLabelKey(channel: string): string {\n return `channel.${channel}`\n}\n\nexport function PreferencesPanel({ className }: PreferencesPanelProps) {\n const { messages, theme } = useNotificationContext()\n const { data: saved = [], isPending } = usePreferences()\n const updatePreferences = useUpdatePreferences()\n\n // Rascunho local só existe entre abrir e salvar: `undefined` significa \"ainda não mexeu\", e é o\n // que faz o painel refletir o servidor sem sobrescrever edição em andamento a cada refetch.\n const [draft, setDraft] = useState<NotificationPreference[] | undefined>(undefined)\n const preferences = draft ?? saved\n\n function toggleChannel(target: NotificationPreference): void {\n setDraft(\n preferences.map((preference) =>\n preference.category === target.category && preference.channel === target.channel\n ? { ...preference, enabled: !preference.enabled }\n : preference,\n ),\n )\n }\n\n function handleSave(): void {\n updatePreferences.mutate(preferences, { onSuccess: () => setDraft(undefined) })\n }\n\n if (isPending) return <p className=\"adn-preferences__state\">{messages['list.loading']}</p>\n\n return (\n <section className={clsx('adn-preferences', theme.rootClassName, className)}>\n <header className=\"adn-preferences__header\">\n <h2 className=\"adn-preferences__title\">{messages['preferences.title']}</h2>\n <p className=\"adn-preferences__description\">{messages['preferences.description']}</p>\n </header>\n\n {preferences.length === 0 ? (\n <p className=\"adn-preferences__state\">{messages['preferences.empty']}</p>\n ) : (\n <ul className=\"adn-preferences__items\">\n {preferences.map((preference) => {\n const inputId = `adn-pref-${preference.category}-${preference.channel}`\n return (\n <li key={inputId} className=\"adn-preferences__item\">\n {/* `label` associado por `htmlFor`: aumenta a área de toque e é o que faz o\n leitor de tela anunciar canal e estado juntos. */}\n <label className=\"adn-preferences__label\" htmlFor={inputId}>\n <input\n id={inputId}\n type=\"checkbox\"\n className=\"adn-preferences__checkbox\"\n checked={preference.enabled}\n onChange={() => toggleChannel(preference)}\n />\n <span className=\"adn-preferences__category\">{preference.category}</span>\n <span className=\"adn-preferences__channel\">\n {messages[channelLabelKey(preference.channel) as keyof typeof messages] ?? preference.channel}\n </span>\n </label>\n\n {preference.quietHoursStart && preference.quietHoursEnd ? (\n <span className=\"adn-preferences__quiet-hours\">\n {messages['preferences.quietHours']} {preference.quietHoursStart}{' '}\n {messages['preferences.quietHoursTo']} {preference.quietHoursEnd}\n </span>\n ) : null}\n </li>\n )\n })}\n </ul>\n )}\n\n <footer className=\"adn-preferences__footer\">\n {/* Ação primária de formulário com convenção clara → ícone (regra de ícones, web.md §9). */}\n <button\n type=\"button\"\n className=\"adn-preferences__save\"\n onClick={handleSave}\n disabled={updatePreferences.isPending || draft === undefined}\n >\n <Save className=\"adn-preferences__save-icon\" aria-hidden=\"true\" />\n {messages['preferences.save']}\n </button>\n\n {updatePreferences.isSuccess && draft === undefined ? (\n <span className=\"adn-preferences__feedback\" role=\"status\">\n {messages['preferences.saved']}\n </span>\n ) : null}\n {updatePreferences.isError ? (\n <span className=\"adn-preferences__feedback adn-preferences__feedback--error\" role=\"alert\">\n {messages['preferences.error']}\n </span>\n ) : null}\n </footer>\n </section>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * A tela de notificações COMPOSTA, no molde do `ConversationsWorkspace`.\n *\n * O pacote exportava só as peças (`NotificationList`, `PreferencesPanel`), e o primeiro consumidor\n * remontou o grid à mão — 56 linhas na página da inbox e 221 na de configuração, contra 35 da página\n * de Documentos, que consome workspace. É exatamente o que a regra de módulos plugáveis (§4) rejeita:\n * cada produto remontando o layout é como as telas divergiram antes.\n *\n * Customização por contrato, nunca por fork:\n * - vocabulário → `labels`\n * - UI do produto → slots `renderHeaderActions`, `renderAboveList`, `renderEmpty`\n * - regra de negócio → callbacks (`onSelectNotification`)\n * - **capacidade por ausência**: sem `settingsHref` não aparece link de configuração, sem\n * `showPreferences` não aparece a coluna. Nunca flag `hasX`.\n */\n\nimport type { ReactNode } from 'react'\nimport type { NotificationSummary } from '@adatechnology/notification-contracts'\n\nimport { useNotificationContext } from '../NotificationProvider'\nimport { NotificationList } from './NotificationList'\nimport { PreferencesPanel } from './PreferencesPanel'\n\nexport type NotificationsWorkspaceProps = {\n /** Sobrescreve textos pontuais sem trocar o locale inteiro. */\n readonly labels?: Partial<Record<string, string>>\n /** Filtra a inbox por assunto. Ausente, mostra tudo. */\n readonly category?: string\n /**\n * Coluna de preferências ao lado da inbox.\n *\n * Ligada por padrão porque é o caso comum; um produto que gerencia preferência noutra tela passa\n * `false` e fica só com a inbox, em largura cheia.\n */\n readonly showPreferences?: boolean\n /** Ausente, o link de configuração não aparece — o produto pode não ter essa tela. */\n readonly settingsHref?: string | undefined\n /** Clique numa notificação. Ausente, a linha não é clicável. */\n readonly onSelectNotification?: (notification: NotificationSummary) => void\n /**\n * Substitui o cabeçalho padrão inteiro.\n *\n * O workspace desenha um `<h1>` porque ele é a tela; a página que já tem o título dela passava a\n * ter dois `<h1>` dizendo a mesma palavra, e para leitor de tela duas primeiras manchetes é o\n * mesmo que nenhuma. Ausente, o padrão continua desenhando — slot é substituição, não interruptor.\n */\n readonly renderHeader?: () => ReactNode\n /** Ações do produto no cabeçalho, ao lado do link de configuração. */\n readonly renderHeaderActions?: () => ReactNode\n /** Aviso ou filtro do produto, entre o cabeçalho e a lista. */\n readonly renderAboveList?: () => ReactNode\n /** Substitui o vazio padrão — útil quando o produto sabe explicar por que está vazio. */\n readonly renderEmpty?: () => ReactNode\n readonly className?: string\n}\n\nexport function NotificationsWorkspace({\n labels: labelsOverride,\n category,\n showPreferences = true,\n settingsHref,\n onSelectNotification,\n renderHeader,\n renderHeaderActions,\n renderAboveList,\n renderEmpty,\n className,\n}: NotificationsWorkspaceProps) {\n const { messages } = useNotificationContext()\n const label = (key: string): string => labelsOverride?.[key] ?? (messages as Record<string, string>)[key] ?? key\n\n return (\n <div className={`adn-workspace ${className ?? ''}`}>\n {renderHeader ? (\n renderHeader()\n ) : (\n <header className=\"adn-workspace__header\">\n <div>\n <h1 className=\"adn-workspace__title\">{label('workspace.title')}</h1>\n <p className=\"adn-workspace__description\">{label('workspace.description')}</p>\n </div>\n\n <div className=\"adn-workspace__actions\">\n {renderHeaderActions?.()}\n {/* Capacidade por ausência: sem href, sem link. */}\n {settingsHref && (\n <a href={settingsHref} className=\"adn-button adn-button--outline\">\n {label('workspace.settingsLink')}\n </a>\n )}\n </div>\n </header>\n )}\n\n {renderAboveList?.()}\n\n <div className={showPreferences ? 'adn-workspace__grid' : 'adn-workspace__grid--single'}>\n <section className=\"adn-workspace__inbox\">\n {/* O vazio desce para a lista, que é quem sabe se está vazia. Desenhado aqui, ele aparecia\n ao lado das notificações — \"nada por aqui\" embaixo do que estava ali. */}\n <NotificationList\n {...(category ? { category } : {})}\n {...(onSelectNotification ? { onSelect: onSelectNotification } : {})}\n {...(renderEmpty ? { renderEmpty } : {})}\n />\n </section>\n\n {showPreferences && (\n <aside className=\"adn-workspace__aside\">\n <PreferencesPanel />\n </aside>\n )}\n </div>\n </div>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * A tela de configuração COMPOSTA: canais por assunto e editor de mensagem com preview.\n *\n * Substitui as 221 linhas de página + 207 de hook que o primeiro consumidor escreveu. O que sobra\n * para o produto é dizer quais canais e assuntos existem — o resto é layout, e layout duplicado é\n * como as telas divergem.\n *\n * `channels` e `categories` são OBRIGATÓRIOS e vêm do produto porque o pacote não tem opinião sobre\n * eles: uma loja avisa status de pedido por WhatsApp, um banco avisa vencimento por e-mail, e o\n * `hint` de cada canal (\"exige template aprovado\", \"exige aparelho registrado\") é conhecimento do\n * produto sobre a própria operação.\n */\n\nimport { Plus, Trash2, X } from 'lucide-react'\nimport { Fragment, useState } from 'react'\nimport type { CSSProperties, ReactNode } from 'react'\nimport type { NotificationPreference, NotificationTemplate } from '@adatechnology/notification-contracts'\n\nimport {\n SORT_DIRECTIONS,\n TEMPLATE_COLUMNS,\n TEMPLATE_VIEWS,\n type TemplateSortField,\n} from '../templateList.constant'\nimport { useNotificationContext } from '../NotificationProvider'\nimport { usePreferences, useUpdatePreferences } from '../hooks/usePreferences'\nimport { useCategoryPolicies } from '../hooks/useCategoryPolicies'\nimport { HtmlCodeField } from './HtmlCodeField'\nimport { MessageBodyField } from './MessageBodyField'\nimport { TemplatePreview } from './TemplatePreview'\nimport { useTemplateEditor } from '../hooks/useTemplateEditor'\nimport { isStandardEmailKey } from '../standardEmail.util'\nimport type { TemplateDraftField } from '../hooks/useTemplateEditor'\n\nexport type NotificationChannelOption = {\n readonly id: string\n readonly label: string\n /** O custo do canal, em uma linha. É o que faz alguém decidir em vez de chutar. */\n readonly hint?: string\n}\n\nexport type NotificationCategoryOption = {\n readonly id: string\n readonly label: string\n readonly hint?: string\n}\n\n/** O laudo do validador, na forma mínima que a tela precisa desenhar. */\nexport type EmailHtmlReport = {\n readonly isValid: boolean\n readonly problems: readonly {\n readonly code: string\n readonly severity: string\n readonly message: string\n }[]\n}\n\nexport type NotificationSettingsWorkspaceProps = {\n readonly labels?: Partial<Record<string, string>>\n /** Os canais que ESTE produto oferece — o pacote despacha em cinco e não opina sobre quais usar. */\n readonly channels: readonly NotificationChannelOption[]\n /** Os assuntos que este produto dispara. */\n readonly categories: readonly NotificationCategoryOption[]\n /**\n * Valores de exemplo do preview, por assunto do template. Ausente, o preview mostra campo vazio —\n * que é honesto, mas menos útil para quem está escrevendo o texto.\n */\n readonly previewPayload?: Readonly<Record<string, unknown>>\n /** Traduz `order.status.preparing` no rótulo que o produto usa. Ausente, mostra a chave crua. */\n readonly templateLabelOf?: (template: NotificationTemplate) => string\n /**\n * Campo extra por canal — é onde entra o nome do template aprovado na Meta, que só o WhatsApp tem.\n * Ausente, nenhum campo extra aparece.\n */\n readonly renderChannelFields?: (params: {\n readonly channel: string\n readonly value: string\n readonly onChange: (value: string) => void\n }) => ReactNode\n /**\n * Confere o documento contra o que cliente de e-mail realmente faz (script, folha externa, imagem\n * em `data:`, tabela desbalanceada). Ausente, nenhum aviso aparece.\n */\n readonly validateEmailHtml?: (html: string) => EmailHtmlReport\n /**\n * Ações do produto no cabeçalho do EDITOR, ao lado de Fechar — recebe a chave do template aberto.\n *\n * É onde entra \"Enviar teste\": provar que a mensagem chega é operação do produto, não do pacote.\n * O pacote não sabe para quem mandar, por qual rota, nem o que fazer com o resultado; ele sabe\n * qual template está aberto, e é só isso que o slot precisa entregar.\n */\n readonly renderEditorActions?: (params: { readonly templateKey: string }) => ReactNode\n /** Substitui o cabeçalho padrão — a página que já tem título próprio evita o segundo `<h1>`. */\n readonly renderHeader?: () => ReactNode\n /** Ações do produto no cabeçalho. */\n readonly renderHeaderActions?: () => ReactNode\n readonly className?: string\n /**\n * Nome do produto no preview: e o remetente do e-mail e o app do push. O pacote nao sabe de\n * quem e a marca, e \"Aviso\" generico faria o preview mentir sobre o que a pessoa ve.\n */\n readonly senderName?: string\n /** Rótulo humano de uma categoria (`auth` → \"Acesso\"). Ausente, mostra a própria chave. */\n readonly categoryLabelOf?: (category: string) => string\n}\n\n/**\n * O laudo do e-mail, so quando ha o que dizer.\n *\n * Documento limpo nao ganha selo verde: um aviso permanente de \"tudo certo\" e ruido que treina a\n * pessoa a nao ler a area — e ai o aviso de verdade passa batido junto.\n */\n/**\n * O campo vira editor de codigo quando o texto TEM marcacao, e nao quando o canal e e-mail: a\n * maioria dos avisos e texto simples, e transformar o campo deles num editor com numeracao de linha\n * cobra complexidade de quem so queria escrever uma frase.\n */\nfunction isHtmlBody(body: string): boolean {\n return /<\\/?[a-zA-Z][\\w:-]*(\\s|>|\\/)/.test(body)\n}\n\nfunction renderEmailProblems(report: EmailHtmlReport): ReactNode {\n if (report.problems.length === 0) return null\n\n return (\n <ul className=\"adn-settings__email-report\">\n {report.problems.map((problem) => (\n <li key={problem.code} className={`adn-settings__email-problem adn-settings__email-problem--${problem.severity}`}>\n {problem.message}\n </li>\n ))}\n </ul>\n )\n}\n\nexport function NotificationSettingsWorkspace({\n labels: labelsOverride,\n channels,\n categories,\n previewPayload,\n templateLabelOf,\n renderChannelFields,\n renderEditorActions,\n validateEmailHtml,\n renderHeader,\n renderHeaderActions,\n className,\n senderName,\n categoryLabelOf,\n}: NotificationSettingsWorkspaceProps) {\n const { messages } = useNotificationContext()\n const label = (key: string): string => labelsOverride?.[key] ?? (messages as Record<string, string>)[key] ?? key\n\n const preferencesQuery = usePreferences()\n const updatePreferences = useUpdatePreferences()\n const editor = useTemplateEditor({\n ...(previewPayload ? { previewPayload } : {}),\n ...(channels[0] ? { defaultChannel: channels[0].id } : {}),\n })\n\n /**\n * Onde inserir a variável. Guardado no `onSelect` dos campos porque o hook não pode conhecer o\n * DOM — e sem isso o clique na variável só saberia concatenar no fim, que é justamente o lugar\n * errado quando se está corrigindo o meio de uma frase.\n */\n const [cursor, setCursor] = useState<{ field: TemplateDraftField; cursorIndex: number }>({\n field: 'body',\n cursorIndex: 0,\n })\n\n /** Em qual canal o cursor estava: com um editor por canal, inserir variavel precisa saber onde. */\n const [cursorChannel, setCursorChannel] = useState<string | undefined>(undefined)\n /** Aba de canal aberta. `undefined` cai no primeiro marcado, para nunca abrir em branco. */\n const [activeChannel, setActiveChannel] = useState<string | undefined>(undefined)\n\n function rememberCursor(field: TemplateDraftField, cursorIndex: number | null): void {\n setCursor({ field, cursorIndex: cursorIndex ?? 0 })\n }\n\n const policies = useCategoryPolicies()\n const [tab, setTab] = useState<'messages' | 'routing'>('messages')\n\n /**\n * Preferência ausente é o estado inicial normal — o módulo devolve só o que foi gravado. O default\n * é ligado: comportamento de fábrica é avisar, e um destinatário que não recebeu porque a linha não\n * existia é pior que um que recebeu demais.\n */\n function isEnabled(category: string, channel: string): boolean {\n const row = (preferencesQuery.data ?? []).find(\n (preference) => preference.category === category && preference.channel === channel,\n )\n return row?.enabled ?? true\n }\n\n function toggle(category: string, channel: string): void {\n // Conjunto inteiro: a rota é `PUT` em lote, e enviar só o que mudou apagaria o resto.\n const next: NotificationPreference[] = categories.flatMap((eachCategory) =>\n channels.map((eachChannel) => ({\n category: eachCategory.id,\n channel: eachChannel.id as NotificationPreference['channel'],\n enabled:\n eachCategory.id === category && eachChannel.id === channel\n ? !isEnabled(category, channel)\n : isEnabled(eachCategory.id, eachChannel.id),\n })),\n )\n updatePreferences.mutate(next)\n }\n\n /**\n * Três estados no cabeçalho (web.md §7): a seta neutra diz que a coluna ORDENA, e é por isso que\n * ela aparece antes de qualquer clique.\n */\n function sortMarkOf(field: TemplateSortField): string {\n if (editor.sort?.field !== field) return '↕'\n return editor.sort.direction === SORT_DIRECTIONS.ASC ? '↑' : '↓'\n }\n\n function ariaSortOf(field: TemplateSortField): 'ascending' | 'descending' | 'none' {\n if (editor.sort?.field !== field) return 'none'\n return editor.sort.direction === SORT_DIRECTIONS.ASC ? 'ascending' : 'descending'\n }\n\n return (\n <div className={`adn-settings ${className ?? ''}`}>\n {renderHeader ? (\n renderHeader()\n ) : (\n <header className=\"adn-settings__header\">\n <div>\n <h1 className=\"adn-settings__title\">{label('settings.title')}</h1>\n <p className=\"adn-settings__description\">{label('settings.description')}</p>\n </div>\n {renderHeaderActions?.()}\n </header>\n )}\n\n <div className=\"adn-settings__tabs\" role=\"tablist\">\n {(['messages', 'routing'] as const).map((id) => (\n <button\n key={id}\n type=\"button\"\n role=\"tab\"\n aria-selected={tab === id}\n className={tab === id ? 'adn-settings__tab adn-settings__tab--active' : 'adn-settings__tab'}\n onClick={() => setTab(id)}\n >\n {label(`settings.tab.${id}`)}\n </button>\n ))}\n </div>\n\n {tab === 'routing' && (\n <section className=\"adn-settings__policies\">\n <h2 className=\"adn-settings__section-title\">{label('settings.policiesTitle')}</h2>\n <p className=\"adn-settings__hint\">{label('settings.policiesHint')}</p>\n\n {categories.map((category) => (\n <div key={category.id} className=\"adn-settings__category\">\n <p className=\"adn-settings__category-title\">{category.label}</p>\n <div className=\"adn-settings__category-channels\">\n {channels.map((channel) => (\n <label key={channel.id} className=\"adn-settings__toggle\">\n <input\n type=\"checkbox\"\n checked={policies.isAllowed({ category: category.id, channel: channel.id })}\n onChange={() => policies.toggle({ category: category.id, channel: channel.id })}\n />\n <span className=\"adn-settings__channel-label\">{channel.label}</span>\n </label>\n ))}\n </div>\n </div>\n ))}\n\n {policies.error && <p className=\"adn-settings__error\">{policies.error}</p>}\n\n <div className=\"adn-settings__actions\">\n <button type=\"button\" onClick={policies.save} disabled={!policies.isDirty || policies.isSaving}>\n {policies.isSaving ? label('settings.saving') : label('settings.savePolicies')}\n </button>\n {policies.isDirty && (\n <button type=\"button\" onClick={policies.reset}>\n {label('settings.discard')}\n </button>\n )}\n </div>\n </section>\n )}\n\n {tab === 'routing' && (\n <section className=\"adn-settings__channels\">\n <h2 className=\"adn-settings__section-title\">{label('settings.channelsTitle')}</h2>\n <p className=\"adn-settings__hint\">{label('settings.channelsHint')}</p>\n\n {categories.map((category) => (\n <div key={category.id} className=\"adn-settings__category\">\n <p className=\"adn-settings__category-label\">{category.label}</p>\n {category.hint && <p className=\"adn-settings__hint\">{category.hint}</p>}\n\n <div className=\"adn-settings__channel-grid\">\n {channels.map((channel) => (\n <label key={channel.id} className=\"adn-settings__channel\">\n <input\n type=\"checkbox\"\n checked={isEnabled(category.id, channel.id)}\n disabled={updatePreferences.isPending}\n onChange={() => toggle(category.id, channel.id)}\n />\n <span>\n <span className=\"adn-settings__channel-label\">{channel.label}</span>\n {channel.hint && <span className=\"adn-settings__hint\">{channel.hint}</span>}\n </span>\n </label>\n ))}\n </div>\n </div>\n ))}\n </section>\n )}\n\n {/* Sem rascunho a coluna do editor nao existe: a lista fica com a largura inteira. Reservar\n 2/3 da tela para \"escolha uma mensagem\" e cobrar espaco por uma instrucao. */}\n {tab === 'messages' && (\n <div className={editor.draft ? 'adn-settings__templates' : 'adn-settings__templates adn-settings__templates--browsing'}>\n <section className=\"adn-settings__template-list\">\n <header className=\"adn-settings__list-header\">\n {/* Titulo e acao na MESMA linha; a explicacao desce inteira embaixo. Com os tres lado a\n lado numa coluna de 320px a explicacao quebrava em tres linhas e empurrava o botao. */}\n <div className=\"adn-settings__list-header-row\">\n <h2 className=\"adn-settings__section-title\">{label('settings.templatesTitle')}</h2>\n <div className=\"adn-settings__list-header-actions\">\n {/* Duas leituras da mesma colecao: a tabela compara, a lista reconhece o texto. */}\n <div className=\"adn-settings__view-switch\" role=\"group\" aria-label={label('settings.viewLabel')}>\n {[TEMPLATE_VIEWS.TABLE, TEMPLATE_VIEWS.LIST].map((view) => (\n <button\n key={view}\n type=\"button\"\n aria-pressed={editor.view === view}\n className={\n editor.view === view\n ? 'adn-settings__view adn-settings__view--on'\n : 'adn-settings__view'\n }\n onClick={() => editor.setView(view)}\n >\n {label(`settings.view.${view}`)}\n </button>\n ))}\n </div>\n <button type=\"button\" className=\"adn-settings__new\" onClick={editor.startNew}>\n {/* Decorativo: o rotulo ao lado ja diz a acao, e o leitor de tela nao repete. */}\n <Plus className=\"adn-settings__button-icon\" aria-hidden=\"true\" />\n {label('settings.newTemplate')}\n </button>\n </div>\n </div>\n </header>\n\n {/* Busca sobre chave E texto: quem procura costuma lembrar do que a mensagem diz, não\n da chave técnica. */}\n <div className=\"adn-settings__list-filters\">\n <label className=\"adn-settings__search\">\n <span className=\"adn-settings__field-label adn-settings__visually-hidden\">\n {label('settings.searchLabel')}\n </span>\n <input\n type=\"search\"\n value={editor.search}\n placeholder={label('settings.searchPlaceholder')}\n onChange={(event) => editor.setSearch(event.target.value)}\n />\n </label>\n\n {editor.categories.length > 1 && (\n <div className=\"adn-settings__filter-row\">\n {editor.categories.map((category) => (\n <button\n key={category}\n type=\"button\"\n aria-pressed={editor.categoryFilter.includes(category)}\n className={\n editor.categoryFilter.includes(category)\n ? 'adn-settings__filter adn-settings__filter--on'\n : 'adn-settings__filter'\n }\n onClick={() => editor.toggleCategoryFilter(category)}\n >\n {categoryLabelOf?.(category) ?? category}\n </button>\n ))}\n </div>\n )}\n\n <div className=\"adn-settings__filter-row\">\n {channels.map((channel) => (\n <button\n key={channel.id}\n type=\"button\"\n aria-pressed={editor.channelFilter.includes(channel.id)}\n className={\n editor.channelFilter.includes(channel.id)\n ? 'adn-settings__filter adn-settings__filter--on'\n : 'adn-settings__filter'\n }\n onClick={() => editor.toggleChannelFilter(channel.id)}\n >\n {channel.label}\n </button>\n ))}\n </div>\n\n {/* Só aparece quando há o que limpar (web.md §7). */}\n {editor.hasFilters && (\n <button type=\"button\" className=\"adn-settings__clear\" onClick={editor.clearFilters}>\n {label('settings.clearFilters')}\n </button>\n )}\n </div>\n\n {editor.isLoading && <p className=\"adn-settings__hint\">{label('list.loading')}</p>}\n\n {/* \"Nada cadastrado\" e \"nada encontrado\" são estados diferentes: o primeiro pede criar,\n o segundo pede afrouxar o filtro. */}\n {!editor.isLoading && editor.totalCount === 0 && (\n <p className=\"adn-settings__hint\">{label('settings.templatesEmpty')}</p>\n )}\n {!editor.isLoading && editor.totalCount > 0 && editor.templates.length === 0 && (\n <p className=\"adn-settings__hint\">{label('settings.noResults')}</p>\n )}\n\n {editor.view === TEMPLATE_VIEWS.TABLE && editor.templates.length > 0 && (\n /* `overflow-x` no contêiner: a página nunca rola na horizontal (web.md §10). */\n <div className=\"adn-settings__table-scroll\">\n <table className=\"adn-settings__table\">\n <thead>\n <tr>\n {TEMPLATE_COLUMNS.map(({ labelKey, field, headerHidden }) => (\n <th key={labelKey} scope=\"col\" aria-sort={field ? ariaSortOf(field) : undefined}>\n {field ? (\n <button type=\"button\" onClick={() => editor.toggleSort(field)}>\n {label(labelKey)}\n <span aria-hidden=\"true\" className=\"adn-settings__sort-mark\">\n {sortMarkOf(field)}\n </span>\n </button>\n ) : (\n <span className={headerHidden ? 'adn-settings__visually-hidden' : undefined}>\n {label(labelKey)}\n </span>\n )}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {editor.templates.map((template) => (\n /* A linha inteira abre o template: na tabela so a celula da chave era clicavel,\n e o alvo real de quem varre a lista e a linha. O botao da chave continua\n existindo — e ele que recebe o foco pelo teclado. */\n <tr\n key={template.id}\n onClick={() => editor.select(template)}\n className={\n editor.selected?.id === template.id\n ? 'adn-settings__table-row adn-settings__table-row--active'\n : 'adn-settings__table-row'\n }\n >\n <td>\n <button\n type=\"button\"\n className=\"adn-settings__table-key\"\n onClick={() => editor.select(template)}\n >\n {templateLabelOf?.(template) ?? template.key}\n </button>\n </td>\n <td className=\"adn-settings__table-body\">{template.body}</td>\n <td>\n <span className={`adn-settings__badge adn-settings__badge--${template.channel}`}>\n {label(`channel.${template.channel}`)}\n </span>\n </td>\n <td className=\"adn-settings__version\">\n {label('settings.version')}\n {template.version}\n </td>\n <td>\n {isStandardEmailKey(template.key) ? (\n /* Modelo do sistema não se remove: o servidor recusa e o envio depende dele. */\n <span className=\"adn-settings__badge\">{label('settings.systemTemplate')}</span>\n ) : (\n <button\n type=\"button\"\n className=\"adn-settings__remove\"\n aria-label={`${label('settings.remove')} ${template.key}`}\n disabled={editor.isDeactivating}\n /* Sem parar a propagacao, remover tambem abriria o template no editor. */\n onClick={(event) => {\n event.stopPropagation()\n editor.deactivate(template.id)\n }}\n >\n <Trash2 className=\"adn-settings__button-icon\" aria-hidden=\"true\" />\n {label('settings.remove')}\n </button>\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n {editor.view === TEMPLATE_VIEWS.LIST &&\n editor.groups.map((group) => (\n <div key={group.category} className=\"adn-settings__group\">\n <p className=\"adn-settings__group-title\">\n {categoryLabelOf?.(group.category) ?? group.category}\n <span className=\"adn-settings__group-count\">{group.templates.length}</span>\n </p>\n <ul>\n {group.templates.map((template) => (\n <li key={template.id} className=\"adn-settings__row\">\n <button\n type=\"button\"\n onClick={() => editor.select(template)}\n className={editor.selected?.id === template.id ? 'adn-settings__row--active' : undefined}\n >\n <span className=\"adn-settings__row-main\">\n <span className=\"adn-settings__row-title\">{templateLabelOf?.(template) ?? template.key}</span>\n <span className=\"adn-settings__row-body\">{template.body}</span>\n </span>\n <span className={`adn-settings__badge adn-settings__badge--${template.channel}`}>\n {label(`channel.${template.channel}`)}\n </span>\n <span className=\"adn-settings__version\">\n {label('settings.version')}\n {template.version}\n </span>\n </button>\n {isStandardEmailKey(template.key) ? (\n <span className=\"adn-settings__badge\">{label('settings.systemTemplate')}</span>\n ) : (\n <button\n type=\"button\"\n className=\"adn-settings__remove\"\n aria-label={`${label('settings.remove')} ${template.key}`}\n disabled={editor.isDeactivating}\n onClick={() => editor.deactivate(template.id)}\n >\n <Trash2 className=\"adn-settings__button-icon\" aria-hidden=\"true\" />\n {label('settings.remove')}\n </button>\n )}\n </li>\n ))}\n </ul>\n </div>\n ))}\n </section>\n\n {editor.draft && (\n <section className=\"adn-settings__editor\">\n {(\n <>\n <header className=\"adn-settings__editor-header\">\n <div>\n <h2 className=\"adn-settings__section-title\">\n {editor.selected ? (templateLabelOf?.(editor.selected) ?? editor.selected.key) : ''}\n {editor.isStandardEmail && (\n <span className=\"adn-settings__badge\">{label('settings.systemTemplate')}</span>\n )}\n </h2>\n <p className=\"adn-settings__hint\">\n {editor.draft.channels.join(' · ')} · {editor.draft.locale} · {label('settings.version')}\n {editor.selected?.version}\n </p>\n </div>\n <div className=\"adn-settings__editor-actions\">\n {/* Antes do Fechar: a ação do produto é o que a pessoa procura ali; Fechar é saída. */}\n {editor.selected && renderEditorActions?.({ templateKey: editor.selected.key })}\n {editor.isStandardEmail && editor.selected && (\n <button\n type=\"button\"\n className=\"adn-settings__restore\"\n disabled={editor.isRestoring}\n onClick={() => editor.selected && editor.restoreDefault(editor.selected.id)}\n >\n {editor.isRestoring ? label('settings.restoring') : label('settings.restoreDefault')}\n </button>\n )}\n <button type=\"button\" className=\"adn-settings__close\" onClick={editor.clear}>\n <X className=\"adn-settings__button-icon\" aria-hidden=\"true\" />\n {label('settings.close')}\n </button>\n </div>\n </header>\n\n {!editor.isIdentityLocked && (\n <div className=\"adn-settings__identity\">\n <label className=\"adn-settings__field\">\n <span className=\"adn-settings__field-label\">{label('settings.key')}</span>\n <span className=\"adn-settings__hint\">{label('settings.keyHint')}</span>\n <input value={editor.draft.key} onChange={(event) => editor.update({ key: event.target.value })} />\n </label>\n\n {/* Multipla escolha, e nao `select`: o mesmo aviso costuma sair por mais de um\n canal, e escolher um de cada vez obrigaria a reescrever o texto. */}\n <fieldset className=\"adn-settings__field adn-settings__field--channels\">\n <legend className=\"adn-settings__field-label\">{label('settings.channel')}</legend>\n <span className=\"adn-settings__hint\">{label('settings.channelHint')}</span>\n <div className=\"adn-settings__channel-picker\">\n {channels.map((channel) => (\n <label key={channel.id} className=\"adn-settings__channel-chip\">\n <input\n type=\"checkbox\"\n checked={editor.draft?.channels.includes(channel.id) ?? false}\n onChange={() => {\n editor.toggleChannel(channel.id)\n /* Marcar um canal abre a aba dele: senao a pessoa marca e nada muda na tela. */\n if (!editor.draft?.channels.includes(channel.id)) setActiveChannel(channel.id)\n }}\n />\n <span>{channel.label}</span>\n </label>\n ))}\n </div>\n </fieldset>\n\n <label className=\"adn-settings__field\">\n <span className=\"adn-settings__field-label\">{label('settings.locale')}</span>\n <input\n value={editor.draft.locale}\n onChange={(event) => editor.update({ locale: event.target.value })}\n />\n </label>\n </div>\n )}\n\n {editor.variables.length > 0 && (\n <div className=\"adn-settings__variables\">\n <p className=\"adn-settings__field-label\">{label('settings.variablesTitle')}</p>\n <p className=\"adn-settings__hint\">{label('settings.variablesHint')}</p>\n <ul>\n {editor.variables.map((variable) => {\n const used = editor.variableDiff.used.includes(variable.name)\n const missing = editor.variableDiff.missingRequired.includes(variable.name)\n return (\n <li key={variable.name}>\n <button\n type=\"button\"\n className={[\n 'adn-settings__variable',\n used ? 'adn-settings__variable--used' : '',\n missing ? 'adn-settings__variable--missing' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n onClick={() =>\n editor.insertVariable({\n ...cursor,\n name: variable.name,\n channel: cursorChannel ?? editor.draft?.channels[0] ?? '',\n })\n }\n >\n <span className=\"adn-settings__variable-name\">{`{{${variable.name}}}`}</span>\n <span className=\"adn-settings__hint\">{variable.example}</span>\n </button>\n </li>\n )\n })}\n </ul>\n </div>\n )}\n\n {editor.variableDiff.unknown.length > 0 && (\n <p className=\"adn-settings__error\">\n {label('settings.unknownVariables')} {editor.variableDiff.unknown.join(', ')}\n </p>\n )}\n\n {/**\n * Um bloco por canal: texto, campos do canal e o preview dele, juntos.\n *\n * Os canais nao sao o mesmo recado em molduras diferentes — o WhatsApp ignora o\n * assunto, o SMS cobra por segmento e encurta. Com um editor so, escrever para o\n * pior canal e mandar isso a todos era a unica saida.\n */}\n {/**\n * Abas por canal, e nao blocos empilhados.\n *\n * Com tres canais marcados, empilhado obriga a rolar por tres aparelhos do e-mail\n * para chegar ao WhatsApp. A aba mantem o preview grande e o trabalho focado num\n * canal por vez — e a comparacao que importa (entre APARELHOS) continua lado a lado\n * dentro da aba.\n *\n * O ponto no rotulo e o que impede o efeito colateral: canal sem texto, ou com\n * variavel desconhecida, bloqueia o salvar — e escondido atras de uma aba fechada,\n * bloquearia sem explicar. */}\n <div className=\"adn-settings__channel-tabs\" role=\"tablist\">\n {channels\n .filter((channel) => editor.draft?.channels.includes(channel.id))\n .map((channel) => {\n const vazio = (editor.draft?.byChannel[channel.id]?.body ?? '').length === 0\n const ativo = (activeChannel ?? editor.draft?.channels[0]) === channel.id\n\n return (\n <button\n key={channel.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={ativo}\n className={ativo ? 'adn-settings__tab adn-settings__tab--active' : 'adn-settings__tab'}\n onClick={() => setActiveChannel(channel.id)}\n >\n {channel.label}\n {vazio && <span className=\"adn-settings__tab-dot\" aria-hidden=\"true\" />}\n </button>\n )\n })}\n </div>\n\n {channels\n .filter((channel) => editor.draft?.channels.includes(channel.id))\n .filter((channel) => (activeChannel ?? editor.draft?.channels[0]) === channel.id)\n .map((channel) => {\n const content = editor.draft?.byChannel[channel.id]\n const frames = editor.previews.filter((frame) => frame.channel === channel.id)\n\n return (\n <section key={channel.id} className=\"adn-settings__channel-block\">\n <header className=\"adn-settings__channel-block-header\">\n <h3 className=\"adn-settings__preview-channel\">{channel.label}</h3>\n {channel.hint && <span className=\"adn-settings__hint\">{channel.hint}</span>}\n </header>\n\n {editor.isStandardEmail ? (\n <p className=\"adn-settings__hint\">{label('settings.standardEmailHint')}</p>\n ) : (\n <label className=\"adn-settings__field\">\n <span className=\"adn-settings__field-label\">{label('settings.subject')}</span>\n <span className=\"adn-settings__hint\">{label('settings.subjectHint')}</span>\n <input\n value={content?.subject ?? ''}\n onChange={(event) => editor.updateChannel(channel.id, { subject: event.target.value })}\n onSelect={(event) => rememberCursor('subject', event.currentTarget.selectionStart)}\n onFocus={() => setCursorChannel(channel.id)}\n />\n </label>\n )}\n\n <label className=\"adn-settings__field\">\n <span className=\"adn-settings__field-label\">{label('settings.body')}</span>\n {/* Editor de codigo so onde HTML significa alguma coisa. WhatsApp, SMS e push\n recebem texto puro — realce ali sugeriria uma marcacao que o canal nao\n entende, e a sugestao vira erro na entrega. */}\n {channel.id === 'email' && isHtmlBody(content?.body ?? '') ? (\n <HtmlCodeField\n value={content?.body ?? ''}\n onChange={(next) => editor.updateChannel(channel.id, { body: next })}\n onSelect={(cursorIndex) => rememberCursor('body', cursorIndex)}\n onFocus={() => setCursorChannel(channel.id)}\n {...(validateEmailHtml && !editor.isStandardEmail\n ? { problems: validateEmailHtml(content?.body ?? '').problems }\n : {})}\n />\n ) : (\n <MessageBodyField\n value={content?.body ?? ''}\n onChange={(next) => editor.updateChannel(channel.id, { body: next })}\n onSelect={(cursorIndex) => rememberCursor('body', cursorIndex)}\n onFocus={() => setCursorChannel(channel.id)}\n labelOf={label}\n />\n )}\n </label>\n\n {/* O modelo padrão se valida inteiro, pelo mesmo `assess` do servidor: as obrigatórias\n e o HTML inseguro, sem depender de a área de mensagem existir. */}\n {editor.isStandardEmail && editor.standardAssessment && !editor.standardAssessment.usable && (\n <ul className=\"adn-settings__email-report\" role=\"alert\">\n {editor.standardAssessment.missing.length > 0 && (\n <li className=\"adn-settings__email-problem adn-settings__email-problem--error\">\n {label('settings.standardMissing')}{' '}\n {editor.standardAssessment.missing.map((name) => `{{${name}}}`).join(', ')}\n </li>\n )}\n {editor.standardAssessment.unsafe.length > 0 && (\n <li className=\"adn-settings__email-problem adn-settings__email-problem--error\">\n {label('settings.standardUnsafe')}{' '}\n {editor.standardAssessment.unsafe\n .map((rule) => label(`settings.standardUnsafe.${rule}`))\n .join(', ')}\n </li>\n )}\n </ul>\n )}\n\n {/* Slot do host: campo que só um canal tem, e que o pacote não conhece por nome. */}\n {renderChannelFields?.({\n channel: channel.id,\n value: content?.whatsappTemplateName ?? '',\n onChange: (value) => editor.updateChannel(channel.id, { whatsappTemplateName: value }),\n })}\n\n {frames.length > 0 && (\n <div className=\"adn-settings__previews\">\n <p className=\"adn-settings__preview-title\">{label('settings.previewTitle')}</p>\n <div className=\"adn-settings__preview-frames\">\n {frames.map((frame) => (\n <figure key={`${frame.channel}:${frame.viewport}`} className=\"adn-settings__preview\">\n <figcaption className=\"adn-settings__hint\">\n {label(`settings.viewport.${frame.viewport}`)} · {frame.width}px\n </figcaption>\n <div\n className=\"adn-settings__preview-frame\"\n style={{ '--adn-preview-width': `${frame.width}px` } as CSSProperties}\n >\n {/* O HTML do preview e o QUE ESTA NO CAMPO, nao uma moldura que o\n painel enfia por fora: se a pessoa escreveu HTML, e o HTML\n dela que precisa aparecer. Corpo sem marcacao segue texto. */}\n <TemplatePreview\n channel={frame.channel}\n viewport={frame.viewport}\n rendered={frame.rendered}\n {...(frame.channel === 'email' && editor.standardPreviewHtml !== undefined\n ? { emailHtml: editor.standardPreviewHtml }\n : frame.channel === 'email' &&\n !editor.isStandardEmail &&\n isHtmlBody(content?.body ?? '')\n ? { emailHtml: content?.body ?? '' }\n : {})}\n labels={{\n to: label('preview.to'),\n now: label('preview.now'),\n mailbox: label('preview.mailbox'),\n time: label('preview.time'),\n address: label('preview.address'),\n counter: label('preview.counter'),\n folder: label('preview.folder'),\n senderAddress: label('preview.senderAddress'),\n unsubscribe: label('preview.unsubscribe'),\n online: label('preview.online'),\n today: label('preview.today'),\n compose: label('preview.compose'),\n reply: label('preview.reply'),\n forward: label('preview.forward'),\n replyAll: label('preview.replyAll'),\n }}\n {...(senderName ? { senderName } : {})}\n />\n </div>\n {frame.rendered.constraints\n .filter((constraint) => constraint.exceeded)\n .map((constraint) => (\n <p key={constraint.field} className=\"adn-settings__preview-warning\">\n {label(`settings.constraint.${constraint.field}`)} {constraint.actual}/\n {constraint.limit}\n </p>\n ))}\n </figure>\n ))}\n </div>\n </div>\n )}\n </section>\n )\n })}\n\n {editor.error && <p className=\"adn-settings__error\">{editor.error}</p>}\n\n <div className=\"adn-settings__actions\">\n <button type=\"button\" onClick={editor.save} disabled={!editor.isDirty || !editor.canSave || editor.isSaving}>\n {editor.isSaving ? label('settings.saving') : label('settings.save')}\n </button>\n {/* Diz por que está desabilitado, em vez de deixar o botão inerte sem explicação. */}\n {!editor.isDirty && <span className=\"adn-settings__hint\">{label('settings.unchanged')}</span>}\n </div>\n </>\n )}\n </section>\n )}\n </div>\n )}\n </div>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * Campo de código com realce, numeração de linha e laudo do linter.\n *\n * Técnica de sobreposição, e não um editor de verdade: um `<pre>` colorido embaixo e o `<textarea>`\n * transparente em cima, com a MESMA métrica de texto e a rolagem sincronizada. Custa alinhamento\n * milimétrico, e paga não trazendo um CodeMirror (~200KB) para dentro de um pacote de UI que hoje\n * pesa duas dependências — e não perdendo nada do `<textarea>`: seleção, desfazer, corretor,\n * leitor de tela e o cursor que o editor usa para inserir variável continuam nativos.\n */\n\nimport { useRef } from 'react'\nimport type { UIEvent } from 'react'\n\nimport { tokenizeHtml } from '../htmlHighlight.util'\n\nexport type HtmlCodeFieldProblem = {\n readonly code: string\n readonly severity: string\n readonly message: string\n}\n\nexport type HtmlCodeFieldProps = {\n readonly value: string\n readonly rows?: number\n readonly onChange: (value: string) => void\n readonly onSelect?: (cursorIndex: number) => void\n readonly onFocus?: () => void\n /** Ausente, nenhum laudo aparece — o campo vira só realce. */\n readonly problems?: readonly HtmlCodeFieldProblem[]\n}\n\nexport function HtmlCodeField({ value, rows = 12, onChange, onSelect, onFocus, problems }: HtmlCodeFieldProps) {\n const highlightRef = useRef<HTMLPreElement>(null)\n\n /**\n * O `<pre>` não rola sozinho: ele segue o `<textarea>`. Sem isto, o realce descola do texto no\n * primeiro documento que passa da altura do campo — que é todo documento de e-mail.\n */\n function handleScroll(event: UIEvent<HTMLTextAreaElement>): void {\n const pre = highlightRef.current\n if (!pre) return\n pre.scrollTop = event.currentTarget.scrollTop\n pre.scrollLeft = event.currentTarget.scrollLeft\n }\n\n const lineCount = value.split('\\n').length\n\n return (\n <div className=\"adn-code\">\n <div className=\"adn-code__editor\">\n <div className=\"adn-code__gutter\" aria-hidden=\"true\">\n {Array.from({ length: lineCount }, (_, index) => (\n <span key={index}>{index + 1}</span>\n ))}\n </div>\n\n <div className=\"adn-code__surface\">\n {/* Decorativo: o texto de verdade está no `<textarea>` em cima, e é ele que o leitor de\n tela lê. Anunciar os dois faria o conteúdo aparecer duplicado. */}\n <pre ref={highlightRef} className=\"adn-code__highlight\" aria-hidden=\"true\">\n {tokenizeHtml(value).map((token, index) => (\n <span key={index} className={`adn-code__token adn-code__token--${token.kind}`}>\n {token.text}\n </span>\n ))}\n {/* Linha vazia final: sem ela o realce não acompanha o cursor na última quebra. */}\n {'\\n'}\n </pre>\n\n <textarea\n className=\"adn-code__input\"\n spellCheck={false}\n rows={rows}\n value={value}\n onChange={(event) => onChange(event.target.value)}\n onScroll={handleScroll}\n onSelect={(event) => onSelect?.(event.currentTarget.selectionStart)}\n onFocus={onFocus}\n />\n </div>\n </div>\n\n {problems && problems.length > 0 && (\n <ul className=\"adn-settings__email-report\">\n {problems.map((problem) => (\n <li\n key={problem.code}\n className={`adn-settings__email-problem adn-settings__email-problem--${problem.severity}`}\n >\n {problem.message}\n </li>\n ))}\n </ul>\n )}\n </div>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * Realce de HTML como DADOS, nunca como string de markup.\n *\n * A tentação aqui é montar `<span class=...>` numa string e jogar em `dangerouslySetInnerHTML` —\n * é o caminho mais curto e é como quase toda biblioteca de realce faz. Num editor esse caminho\n * passa por cima do texto que a pessoa acabou de digitar: o realce vira o vetor de injeção do\n * próprio conteúdo que ele deveria só colorir. Devolver tokens deixa o React criar nó de texto, e\n * a questão simplesmente não existe.\n */\n\nexport const HTML_TOKEN = {\n TAG: 'tag',\n NAME: 'name',\n ATTRIBUTE: 'attribute',\n VALUE: 'value',\n COMMENT: 'comment',\n DOCTYPE: 'doctype',\n VARIABLE: 'variable',\n TEXT: 'text',\n} as const\nexport type HtmlTokenKind = (typeof HTML_TOKEN)[keyof typeof HTML_TOKEN]\n\nexport type HtmlToken = {\n readonly kind: HtmlTokenKind\n readonly text: string\n}\n\n/**\n * Um scanner, não um parser: ele não monta árvore nem valida aninhamento — quem reclama de tag\n * desbalanceada é o `validateEmailHtml`. Aqui só interessa onde começa e termina cada pedaço, e\n * um scanner erra de forma inofensiva (colore de menos), enquanto um parser meia-boca erra\n * escondendo texto.\n */\nconst SCANNER =\n /(<!--[\\s\\S]*?-->)|(<!doctype[^>]*>)|(<\\/?)([a-zA-Z][\\w:-]*)((?:[^>\"']|\"[^\"]*\"|'[^']*')*?)(\\/?>)|(\\{\\{\\s*[\\w.]+\\s*\\}\\})/gi\n\nexport function tokenizeHtml(source: string): readonly HtmlToken[] {\n const tokens: HtmlToken[] = []\n let cursor = 0\n\n for (const match of source.matchAll(SCANNER)) {\n const start = match.index\n if (start > cursor) push(tokens, HTML_TOKEN.TEXT, source.slice(cursor, start))\n\n const [whole, comment, doctype, open, name, attributes, close, variable] = match\n\n if (comment) push(tokens, HTML_TOKEN.COMMENT, comment)\n else if (doctype) push(tokens, HTML_TOKEN.DOCTYPE, doctype)\n else if (variable) push(tokens, HTML_TOKEN.VARIABLE, variable)\n else if (name) {\n push(tokens, HTML_TOKEN.TAG, open ?? '<')\n push(tokens, HTML_TOKEN.NAME, name)\n tokens.push(...tokenizeAttributes(attributes ?? ''))\n push(tokens, HTML_TOKEN.TAG, close ?? '>')\n }\n\n cursor = start + whole.length\n }\n\n if (cursor < source.length) push(tokens, HTML_TOKEN.TEXT, source.slice(cursor))\n return tokens\n}\n\nconst ATTRIBUTE_SCANNER = /([\\w:@.-]+)(\\s*=\\s*)(\"[^\"]*\"|'[^']*'|[^\\s>]+)?/g\n\nfunction tokenizeAttributes(source: string): readonly HtmlToken[] {\n const tokens: HtmlToken[] = []\n let cursor = 0\n\n for (const match of source.matchAll(ATTRIBUTE_SCANNER)) {\n const start = match.index\n if (start > cursor) push(tokens, HTML_TOKEN.TEXT, source.slice(cursor, start))\n\n const [whole, attribute, equals, value] = match\n push(tokens, HTML_TOKEN.ATTRIBUTE, attribute ?? '')\n push(tokens, HTML_TOKEN.TEXT, equals ?? '')\n push(tokens, HTML_TOKEN.VALUE, value ?? '')\n\n cursor = start + whole.length\n }\n\n if (cursor < source.length) push(tokens, HTML_TOKEN.TEXT, source.slice(cursor))\n return tokens\n}\n\nfunction push(tokens: HtmlToken[], kind: HtmlTokenKind, text: string): void {\n if (text) tokens.push({ kind, text })\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * A caixa de mensagem com barra de formatação.\n *\n * A seleção é assunto do DOM, e por isso ela mora aqui e não no `useTemplateEditor`: o hook guarda\n * o rascunho, este componente guarda onde o cursor está. Depois de cada botão a seleção é\n * reposicionada à mão — sem isso o cursor pula para o fim do texto a cada clique, e quem estava\n * corrigindo o meio de uma frase perde o lugar.\n */\n\nimport { useLayoutEffect, useRef, useState } from 'react'\n\nimport { applyMark, insertAt } from '../messageFormat.util'\nimport { MessageToolbar } from './MessageToolbar'\n\nexport type MessageBodyFieldProps = {\n readonly value: string\n readonly rows?: number\n readonly onChange: (value: string) => void\n readonly onSelect?: (cursorIndex: number) => void\n readonly onFocus?: () => void\n readonly labelOf: (key: string) => string\n}\n\nexport function MessageBodyField({ value, rows = 5, onChange, onSelect, onFocus, labelOf }: MessageBodyFieldProps) {\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n const [pendingSelection, setPendingSelection] = useState<readonly [number, number]>()\n\n /**\n * `useLayoutEffect` e não `useEffect`: a seleção precisa ser reposta ANTES da pintura, senão o\n * cursor aparece por um quadro no lugar errado — e num campo de texto esse piscar é visível.\n */\n useLayoutEffect(() => {\n if (!pendingSelection) return\n const textarea = textareaRef.current\n if (!textarea) return\n\n textarea.focus()\n textarea.setSelectionRange(pendingSelection[0], pendingSelection[1])\n setPendingSelection(undefined)\n }, [pendingSelection])\n\n function currentRange(): readonly [number, number] {\n const textarea = textareaRef.current\n if (!textarea) return [value.length, value.length]\n return [textarea.selectionStart, textarea.selectionEnd]\n }\n\n function handleMark(delimiter: string): void {\n const [selectionStart, selectionEnd] = currentRange()\n const result = applyMark({ text: value, delimiter, selectionStart, selectionEnd })\n\n onChange(result.text)\n setPendingSelection([result.selectionStart, result.selectionEnd])\n }\n\n function handleInsert(insertion: string): void {\n const [selectionStart, selectionEnd] = currentRange()\n const result = insertAt({ text: value, insertion, selectionStart, selectionEnd })\n\n onChange(result.text)\n setPendingSelection([result.selectionStart, result.selectionEnd])\n }\n\n return (\n <div className=\"adn-message-field\">\n <MessageToolbar onMark={handleMark} onInsert={handleInsert} labelOf={labelOf} />\n <textarea\n ref={textareaRef}\n rows={rows}\n value={value}\n onChange={(event) => onChange(event.target.value)}\n onSelect={(event) => onSelect?.(event.currentTarget.selectionStart)}\n onFocus={onFocus}\n />\n </div>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n */\n\nexport type ApplyMarkParams = {\n readonly text: string\n readonly delimiter: string\n readonly selectionStart: number\n readonly selectionEnd: number\n}\n\nexport type ApplyMarkResult = {\n readonly text: string\n /** Onde o cursor precisa ficar depois — sem isto, ele volta para o começo a cada clique. */\n readonly selectionStart: number\n readonly selectionEnd: number\n}\n\n/**\n * Envolve a seleção com o delimitador — ou DESFAZ, se ela já estiver envolvida.\n *\n * O botão alterna, e não acumula: clicar duas vezes em negrito com o mesmo trecho selecionado\n * devolve o texto original. Sem isso, `**texto**` vira literal na conversa, porque a convenção do\n * WhatsApp não aninha — o segundo par cancela o primeiro e o cliente mostra os asteriscos.\n *\n * Seleção vazia insere o par e põe o cursor no meio: é o comportamento de quem clica em negrito\n * ANTES de escrever, que é metade das vezes.\n */\nexport function applyMark({ text, delimiter, selectionStart, selectionEnd }: ApplyMarkParams): ApplyMarkResult {\n const start = clamp(selectionStart, text.length)\n const end = clamp(Math.max(selectionEnd, selectionStart), text.length)\n\n const selected = text.slice(start, end)\n const size = delimiter.length\n\n const wrappedInside = selected.startsWith(delimiter) && selected.endsWith(delimiter) && selected.length > size * 2\n if (wrappedInside) {\n const bare = selected.slice(size, -size)\n return {\n text: `${text.slice(0, start)}${bare}${text.slice(end)}`,\n selectionStart: start,\n selectionEnd: start + bare.length,\n }\n }\n\n const wrappedOutside = text.slice(start - size, start) === delimiter && text.slice(end, end + size) === delimiter\n if (wrappedOutside) {\n return {\n text: `${text.slice(0, start - size)}${selected}${text.slice(end + size)}`,\n selectionStart: start - size,\n selectionEnd: start - size + selected.length,\n }\n }\n\n return {\n text: `${text.slice(0, start)}${delimiter}${selected}${delimiter}${text.slice(end)}`,\n selectionStart: start + size,\n selectionEnd: start + size + selected.length,\n }\n}\n\n/** Insere no cursor, substituindo o que estiver selecionado — o que todo campo de texto faz. */\nexport function insertAt({\n text,\n insertion,\n selectionStart,\n selectionEnd,\n}: {\n readonly text: string\n readonly insertion: string\n readonly selectionStart: number\n readonly selectionEnd: number\n}): ApplyMarkResult {\n const start = clamp(selectionStart, text.length)\n const end = clamp(Math.max(selectionEnd, selectionStart), text.length)\n const next = start + insertion.length\n\n return {\n text: `${text.slice(0, start)}${insertion}${text.slice(end)}`,\n selectionStart: next,\n selectionEnd: next,\n }\n}\n\nfunction clamp(value: number, max: number): number {\n return Math.min(Math.max(value, 0), max)\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * A barra da caixa de mensagem: negrito, itálico, tachado, monoespaçado e emoji.\n *\n * Ela escreve MARCAÇÃO no texto, não HTML. A convenção é a do WhatsApp (`conversation-flow.md` §4)\n * e vale para todos os canais — quem escreve o fluxo escreve uma vez, e o canal que não a entende\n * nativamente traduz na renderização. Um editor rico que cuspisse `<b>` obrigaria o mesmo texto a\n * existir duas vezes, e a segunda cópia sempre atrasa em relação à primeira.\n */\n\nimport { Bold, Code, Italic, Smile, Strikethrough } from 'lucide-react'\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\n\nimport { MESSAGE_EMOJI, MESSAGE_FORMAT, MESSAGE_FORMAT_MARKS } from '../messageFormat.constant'\nimport type { MessageFormat } from '../messageFormat.constant'\n\nexport type MessageToolbarProps = {\n /** Aplica o delimitador na seleção corrente do campo. */\n readonly onMark: (delimiter: string) => void\n readonly onInsert: (text: string) => void\n /** Rótulos acessíveis, por formato. Nada aqui é literal (web.md §6). */\n readonly labelOf: (key: string) => string\n}\n\nconst FORMAT_ICON: Readonly<Record<MessageFormat, ReactNode>> = {\n [MESSAGE_FORMAT.BOLD]: <Bold aria-hidden=\"true\" className=\"adn-settings__button-icon\" />,\n [MESSAGE_FORMAT.ITALIC]: <Italic aria-hidden=\"true\" className=\"adn-settings__button-icon\" />,\n [MESSAGE_FORMAT.STRIKETHROUGH]: <Strikethrough aria-hidden=\"true\" className=\"adn-settings__button-icon\" />,\n [MESSAGE_FORMAT.MONOSPACE]: <Code aria-hidden=\"true\" className=\"adn-settings__button-icon\" />,\n}\n\nexport function MessageToolbar({ onMark, onInsert, labelOf }: MessageToolbarProps) {\n const [isEmojiOpen, setIsEmojiOpen] = useState(false)\n\n return (\n <div className=\"adn-toolbar\">\n {MESSAGE_FORMAT_MARKS.map(({ format, delimiter }) => (\n <button\n key={format}\n type=\"button\"\n className=\"adn-toolbar__button\"\n title={labelOf(`toolbar.${format}`)}\n aria-label={labelOf(`toolbar.${format}`)}\n /**\n * `onMouseDown` e não `onClick`: clicar tira o foco do campo, e com ele a seleção que a\n * barra precisa envolver. Prevenir o padrão mantém o cursor onde estava.\n */\n onMouseDown={(event) => {\n event.preventDefault()\n onMark(delimiter)\n }}\n >\n {FORMAT_ICON[format]}\n </button>\n ))}\n\n <span className=\"adn-toolbar__divider\" aria-hidden=\"true\" />\n\n <div className=\"adn-toolbar__emoji\">\n <button\n type=\"button\"\n className=\"adn-toolbar__button\"\n title={labelOf('toolbar.emoji')}\n aria-label={labelOf('toolbar.emoji')}\n aria-expanded={isEmojiOpen}\n onMouseDown={(event) => {\n event.preventDefault()\n setIsEmojiOpen((current) => !current)\n }}\n >\n <Smile aria-hidden=\"true\" className=\"adn-settings__button-icon\" />\n </button>\n\n {isEmojiOpen && (\n <div className=\"adn-toolbar__palette\" role=\"group\" aria-label={labelOf('toolbar.emoji')}>\n {MESSAGE_EMOJI.map((emoji) => (\n <button\n key={emoji}\n type=\"button\"\n className=\"adn-toolbar__emoji-button\"\n onMouseDown={(event) => {\n event.preventDefault()\n onInsert(emoji)\n setIsEmojiOpen(false)\n }}\n >\n {emoji}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * Formatação e emoji da caixa de mensagem.\n *\n * A marcação é a do WhatsApp — `*negrito*`, `_itálico_` — e ela é ÚNICA para todos os canais\n * (`conversation-flow.md` §4): quem escreve o fluxo escreve uma vez, e o canal que não entende a\n * convenção nativamente traduz na renderização. Um editor rico que cuspisse `<b>` obrigaria o texto\n * a existir duas vezes, e a segunda sempre atrasa em relação à primeira.\n *\n * Os delimitadores são simétricos de propósito: envolver a seleção e desfazer o envolvimento é a\n * mesma operação com o mesmo par, e é isso que deixa o botão alternar em vez de acumular asterisco.\n */\n\nexport const MESSAGE_FORMAT = {\n BOLD: 'bold',\n ITALIC: 'italic',\n STRIKETHROUGH: 'strikethrough',\n MONOSPACE: 'monospace',\n} as const\nexport type MessageFormat = (typeof MESSAGE_FORMAT)[keyof typeof MESSAGE_FORMAT]\n\nexport type MessageFormatMark = {\n readonly format: MessageFormat\n readonly delimiter: string\n}\n\nexport const MESSAGE_FORMAT_MARKS: readonly MessageFormatMark[] = [\n { format: MESSAGE_FORMAT.BOLD, delimiter: '*' },\n { format: MESSAGE_FORMAT.ITALIC, delimiter: '_' },\n { format: MESSAGE_FORMAT.STRIKETHROUGH, delimiter: '~' },\n { format: MESSAGE_FORMAT.MONOSPACE, delimiter: '```' },\n]\n\n/**\n * Paleta curada, e não um seletor com todos os emoji do Unicode.\n *\n * O mesmo emoji precisa significar a mesma coisa em todo o produto (`conversation-flow.md` §3), e\n * uma grade infinita garante o contrário: cada pessoa escolhe um símbolo diferente para \"confirmar\".\n * Vinte e quatro cobrem aviso, dinheiro, prazo e atendimento — o que estes produtos realmente dizem.\n */\nexport const MESSAGE_EMOJI: readonly string[] = [\n '✅',\n '❌',\n '⚠️',\n 'ℹ️',\n '📅',\n '⏰',\n '⏳',\n '🔔',\n '💬',\n '📞',\n '📧',\n '🙋',\n '💰',\n '💳',\n '🧾',\n '📊',\n '📦',\n '🚚',\n '📍',\n '🔗',\n '🙂',\n '🎉',\n '🙏',\n '👋',\n]\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * O preview com a moldura do canal, e não uma caixa branca igual para todos.\n *\n * Duas caixas idênticas rotuladas \"600px\" e \"375px\" não respondem a pergunta que alguém tem ao\n * escrever a mensagem: *como isso chega?* Um e-mail chega numa caixa de entrada, com remetente e\n * assunto acima do texto; um WhatsApp chega como balão sobre o papel de parede da conversa; um SMS\n * chega sem assunto nenhum, contado em segmentos de 160; um push chega como cartão na tela\n * bloqueada, cortado em duas linhas. O corte e o enquadramento SÃO a informação — sem eles o\n * preview só prova que o texto existe.\n *\n * Nada aqui usa `dangerouslySetInnerHTML`: o corpo entra como nó de texto, mesmo já escapado pelo\n * renderer do `notification-contracts`. Quando o produto injeta a moldura de e-mail (`emailHtml`),\n * o documento vai para um `<iframe sandbox srcDoc>` — nunca para o DOM do painel. O sandbox vazio\n * corta script e mesma-origem, e de quebra isola o CSS do e-mail do CSS da tela.\n */\n\nimport type { RenderedTemplatePreview } from '@adatechnology/notification-contracts'\n\nexport type TemplatePreviewProps = {\n readonly channel: string\n readonly viewport: string\n readonly rendered: RenderedTemplatePreview\n /**\n * O documento de e-mail COMPLETO, já com a moldura da marca em volta do corpo. Vem do produto:\n * o pacote não conhece logo, cartão de usuário nem rodapé. Ausente, o corpo aparece como texto.\n */\n readonly emailHtml?: string\n /** Nome do produto, para o cabeçalho do e-mail e o do push. O pacote não sabe de quem é a marca. */\n readonly senderName?: string\n /**\n * Arquivo que segue com a mensagem (ex.: o PDF do boleto). Aparece como cartão de documento no\n * balão do WhatsApp e como chip no fim do e-mail. O nome e o tamanho vêm do produto.\n */\n readonly attachment?: PreviewAttachment\n /** Os textos da moldura. Nada aqui é hardcoded — nem \"para você\", nem \"agora\" (web.md §6). */\n readonly labels: PreviewLabels\n}\n\nexport type PreviewAttachment = {\n readonly name: string\n /** Já formatado pelo produto (ex.: \"4,4 KB · PDF\"). Ausente, só o nome. */\n readonly detail?: string\n}\n\nexport type PreviewLabels = {\n readonly to: string\n readonly now: string\n readonly mailbox: string\n /** Hora da barra de status do aparelho. */\n readonly time: string\n readonly address: string\n readonly counter: string\n readonly folder: string\n readonly senderAddress: string\n readonly unsubscribe: string\n readonly online: string\n readonly today: string\n readonly compose: string\n readonly reply: string\n readonly forward: string\n readonly replyAll: string\n}\n\n/**\n * O aparelho. `os` muda mais que a largura: o raio da moldura, o raio dos balões e o desenho do\n * cartão de push são diferentes em cada sistema, e é por isso que os dois aparecem lado a lado.\n *\n * Sem barra de status falsa: no aparelho real ela é desenhada por cima, e a pintada fica dobrada.\n */\n/** Sinal, wi-fi e bateria da barra de status. Desenhados, nunca emoji — escalam e herdam a cor. */\nfunction StatusIcons() {\n return (\n <span className=\"adn-preview-status__icons\">\n <svg width=\"15\" height=\"10\" viewBox=\"0 0 15 10\" aria-hidden=\"true\">\n <rect x=\"0\" y=\"6\" width=\"2.5\" height=\"4\" rx=\"0.6\" fill=\"currentColor\" />\n <rect x=\"4\" y=\"4\" width=\"2.5\" height=\"6\" rx=\"0.6\" fill=\"currentColor\" />\n <rect x=\"8\" y=\"2\" width=\"2.5\" height=\"8\" rx=\"0.6\" fill=\"currentColor\" />\n <rect x=\"12\" y=\"0\" width=\"2.5\" height=\"10\" rx=\"0.6\" fill=\"currentColor\" />\n </svg>\n <svg width=\"13\" height=\"10\" viewBox=\"0 0 13 10\" aria-hidden=\"true\">\n <path d=\"M6.5 9.2 1 3.6a7.8 7.8 0 0 1 11 0Z\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.3\" />\n <circle cx=\"6.5\" cy=\"8\" r=\"1\" fill=\"currentColor\" />\n </svg>\n <svg width=\"20\" height=\"10\" viewBox=\"0 0 20 10\" aria-hidden=\"true\">\n <rect x=\"0.5\" y=\"0.5\" width=\"16\" height=\"9\" rx=\"2.5\" fill=\"none\" stroke=\"currentColor\" opacity=\"0.5\" />\n <rect x=\"2\" y=\"2\" width=\"11\" height=\"6\" rx=\"1.2\" fill=\"currentColor\" />\n <rect x=\"18\" y=\"3.5\" width=\"1.6\" height=\"3\" rx=\"0.8\" fill=\"currentColor\" opacity=\"0.5\" />\n </svg>\n </span>\n )\n}\n\n/**\n * O aparelho inteiro: moldura, barra de status, recorte da câmera e a barra de gesto embaixo.\n *\n * `os` muda mais que a largura — no iOS o recorte é a ilha central e os cantos são bem\n * arredondados; no Android é o furo à esquerda e a moldura é mais reta. É o que faz reconhecer o\n * aparelho de relance, e é onde a mesma mensagem quebra em pontos diferentes.\n */\nfunction Phone({ children, os, tone, time }: { children: React.ReactNode; os: string; tone?: 'dark'; time: string }) {\n const android = os === 'android'\n const classes = ['adn-preview-phone', `adn-preview-phone--${android ? 'android' : 'ios'}`]\n if (tone === 'dark') classes.push('adn-preview-phone--dark')\n\n return (\n <div className={classes.join(' ')}>\n {/* Botoes laterais: e o que faz a silhueta parecer um aparelho e nao um retangulo. */}\n <span className=\"adn-preview-phone__btn adn-preview-phone__btn--mute\" />\n <span className=\"adn-preview-phone__btn adn-preview-phone__btn--up\" />\n <span className=\"adn-preview-phone__btn adn-preview-phone__btn--down\" />\n <span className=\"adn-preview-phone__btn adn-preview-phone__btn--power\" />\n <div className=\"adn-preview-phone__screen\">\n <div className=\"adn-preview-status\">\n <span className=\"adn-preview-status__time\">{time}</span>\n {android ? <span className=\"adn-preview-phone__punch\" /> : <span className=\"adn-preview-phone__island\" />}\n <StatusIcons />\n </div>\n <div className=\"adn-preview-phone__content\">{children}</div>\n <div className=\"adn-preview-phone__gesture\" />\n </div>\n </div>\n )\n}\n\n/** Ícone traçado de 20px, no mesmo estilo do resto — nunca emoji (web.md §9). */\nfunction Icon({ d, size = 16 }: { d: string; size?: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.7\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d={d} />\n </svg>\n )\n}\n\nconst ICON = {\n back: 'M19 12H5M12 19l-7-7 7-7',\n archive: 'M3 8h18v12H3zM3 4h18v4H3M10 12h4',\n report: 'M12 8v5M12 16.5v.01M12 3 2 20h20Z',\n trash: 'M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6',\n unread: 'M3 5h18v14H3zM3 5l9 7 9-7',\n move: 'M3 7h6l2 2h10v10H3zM3 7V5h6l2 2',\n more: 'M12 6v.01M12 12v.01M12 18v.01',\n prev: 'M15 19l-7-7 7-7',\n next: 'M9 5l7 7-7 7',\n print: 'M6 9V3h12v6M6 18H4v-6h16v6h-2M8 14h8v7H8z',\n popout: 'M14 4h6v6M20 4l-9 9M18 14v6H4V6h6',\n star: 'm12 3 2.9 5.9 6.5.9-4.7 4.6 1.1 6.5L12 17.8 6.2 20.9l1.1-6.5L2.6 9.8l6.5-.9Z',\n reply: 'M9 17H4V7M4 7l7 7M20 17v-3a6 6 0 0 0-6-6H4',\n pencil: 'M16.5 3.5a2.1 2.1 0 0 1 3 3L8 18l-4 1 1-4Z',\n inbox: 'M3 12h5l2 3h4l2-3h5M3 12l2-7h14l2 7v7H3z',\n search: 'M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14M20 20l-3.5-3.5',\n help: 'M12 17v.01M9.5 9a2.5 2.5 0 1 1 3.5 2.3c-.6.3-1 .9-1 1.7',\n video: 'M3 7h11v10H3zM14 10l7-3v10l-7-3',\n call: 'M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a1 1 0 0 1-1 1A16 16 0 0 1 4 5a1 1 0 0 1 1-1',\n mic: 'M12 3a3 3 0 0 1 3 3v5a3 3 0 0 1-6 0V6a3 3 0 0 1 3-3M5 11a7 7 0 0 0 14 0M12 18v3',\n forward: 'M15 17h5V7M20 7l-7 7M4 17v-3a6 6 0 0 1 6-6h10',\n replyAll: 'M7 17H3V9M3 9l5 5M11 17H8V9M8 9l5 5M20 17v-3a6 6 0 0 0-6-6H8',\n chevron: 'm6 9 6 6 6-6',\n file: 'M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8zM14 3v5h5',\n settings:\n 'M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6M19 12a7 7 0 0 0-.1-1l2-1.5-2-3.4-2.3 1a7 7 0 0 0-1.7-1L14.5 3h-4l-.4 2.6a7 7 0 0 0-1.7 1l-2.3-1-2 3.4L6.1 11a7 7 0 0 0 0 2l-2 1.5 2 3.4 2.3-1a7 7 0 0 0 1.7 1l.4 2.6h4l.4-2.6a7 7 0 0 0 1.7-1l2.3 1 2-3.4-2-1.5c.1-.3.1-.7.1-1',\n} as const\n\n/**\n * A mensagem aberta num leitor de e-mail no computador.\n *\n * A anatomia é a que todo cliente compartilha — trilho de ações à esquerda, barra de ferramentas\n * da mensagem, contador de posição, assunto grande com o rótulo da pasta, e a linha do remetente\n * com endereço, horário e ações. Nenhuma marca de terceiro é reproduzida: sem logotipo, sem\n * wordmark, sem a paleta de nenhum produto.\n */\nfunction EmailDesktop({\n rendered,\n emailHtml,\n senderName,\n labels,\n attachment,\n}: {\n rendered: RenderedTemplatePreview\n emailHtml: string | undefined\n senderName: string\n labels: PreviewLabels\n attachment: PreviewAttachment | undefined\n}) {\n return (\n <div className=\"adn-preview-browser\">\n <div className=\"adn-preview-browser__bar\">\n <span className=\"adn-preview-browser__dot\" />\n <span className=\"adn-preview-browser__dot\" />\n <span className=\"adn-preview-browser__dot\" />\n <div className=\"adn-preview-browser__address\">{labels.address}</div>\n </div>\n\n <div className=\"adn-preview-mailapp\">\n <div className=\"adn-preview-mailapp__bar\">\n <span className=\"adn-preview-mailapp__menu\" aria-hidden=\"true\">\n <span />\n <span />\n <span />\n </span>\n <div className=\"adn-preview-mailapp__search\">\n <Icon d={ICON.search} size={15} />\n <span>{labels.mailbox}</span>\n </div>\n <span className=\"adn-preview-mailapp__account\">\n <Icon d={ICON.help} size={15} />\n <Icon d={ICON.settings} size={15} />\n <span className=\"adn-preview-avatar adn-preview-avatar--small\">{senderName.slice(0, 1)}</span>\n </span>\n </div>\n\n <div className=\"adn-preview-mailapp__split\">\n <nav className=\"adn-preview-mailapp__rail\" aria-hidden=\"true\">\n <span className=\"adn-preview-mailapp__compose\">\n <Icon d={ICON.pencil} size={16} />\n </span>\n <span className=\"adn-preview-mailapp__rail-item adn-preview-mailapp__rail-item--active\">\n <Icon d={ICON.inbox} size={16} />\n </span>\n <span className=\"adn-preview-mailapp__rail-item\">\n <Icon d={ICON.star} size={16} />\n </span>\n </nav>\n\n <div className=\"adn-preview-browser__viewport\">\n <div className=\"adn-preview-mailapp__toolbar\">\n <Icon d={ICON.back} />\n <span className=\"adn-preview-mailapp__divider\" />\n <Icon d={ICON.archive} />\n <Icon d={ICON.report} />\n <Icon d={ICON.trash} />\n <span className=\"adn-preview-mailapp__divider\" />\n <Icon d={ICON.unread} />\n <Icon d={ICON.move} />\n <Icon d={ICON.more} />\n <span className=\"adn-preview-mailapp__spacer\" />\n <span className=\"adn-preview-mailapp__counter\">{labels.counter}</span>\n <Icon d={ICON.prev} size={14} />\n <Icon d={ICON.next} size={14} />\n </div>\n\n <div className=\"adn-preview-mail\">\n <div className=\"adn-preview-mail__subject-row\">\n <div className=\"adn-preview-mail__subject\">{rendered.title}</div>\n <span className=\"adn-preview-mail__folder\">{labels.folder}</span>\n <span className=\"adn-preview-mail__subject-actions\">\n <Icon d={ICON.print} size={15} />\n <Icon d={ICON.popout} size={15} />\n </span>\n </div>\n\n <div className=\"adn-preview-mail__from\">\n <span className=\"adn-preview-avatar\">{senderName.slice(0, 1)}</span>\n <span className=\"adn-preview-mail__identity\">\n <span className=\"adn-preview-mail__sender-row\">\n <span className=\"adn-preview-mail__sender\">{senderName}</span>\n <span className=\"adn-preview-mail__address\">{labels.senderAddress}</span>\n <span className=\"adn-preview-mail__unsubscribe\">{labels.unsubscribe}</span>\n </span>\n <span className=\"adn-preview-mail__to\">{labels.to}</span>\n </span>\n <span className=\"adn-preview-mail__from-actions\">\n <span className=\"adn-preview-mail__time\">{labels.now}</span>\n <Icon d={ICON.star} size={15} />\n <Icon d={ICON.reply} size={15} />\n <Icon d={ICON.more} size={15} />\n </span>\n </div>\n\n <MailBody html={emailHtml} text={rendered.body} />\n {attachment ? <AttachmentCard attachment={attachment} block=\"adn-preview-attachment--mail\" /> : null}\n </div>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * A mensagem aberta no app de e-mail do aparelho.\n *\n * Não é a tela do navegador encolhida — a anatomia é outra: a barra de ações fica fixa no topo, o\n * assunto vem antes do remetente, a linha do remetente traz avatar grande, horário e estrela na\n * mesma altura, o destinatário fica numa linha que se expande, e as ações de resposta ficam no fim\n * da mensagem em vez de numa barra lateral.\n */\nfunction EmailMobile({\n rendered,\n emailHtml,\n senderName,\n os,\n labels,\n attachment,\n}: {\n rendered: RenderedTemplatePreview\n emailHtml: string | undefined\n senderName: string\n os: string\n labels: PreviewLabels\n attachment: PreviewAttachment | undefined\n}) {\n return (\n <Phone os={os} time={labels.time}>\n <div className=\"adn-preview-mailapp__actions\">\n <Icon d={ICON.back} size={18} />\n <span className=\"adn-preview-mailapp__spacer\" />\n <Icon d={ICON.archive} size={18} />\n <Icon d={ICON.trash} size={18} />\n <Icon d={ICON.unread} size={18} />\n <Icon d={ICON.more} size={18} />\n </div>\n\n <div className=\"adn-preview-mailapp__scroll\">\n <div className=\"adn-preview-mail adn-preview-mail--compact\">\n <div className=\"adn-preview-mail__subject-row\">\n <div className=\"adn-preview-mail__subject\">{rendered.title}</div>\n </div>\n <span className=\"adn-preview-mail__folder\">{labels.folder}</span>\n\n <div className=\"adn-preview-mail__from adn-preview-mail__from--mobile\">\n <span className=\"adn-preview-avatar adn-preview-avatar--large\">{senderName.slice(0, 1)}</span>\n <span className=\"adn-preview-mail__identity\">\n <span className=\"adn-preview-mail__sender-row\">\n <span className=\"adn-preview-mail__sender\">{senderName}</span>\n <span className=\"adn-preview-mail__time\">{labels.now}</span>\n </span>\n {/* Linha do destinatário que expande — é assim que o app esconde os detalhes. */}\n <span className=\"adn-preview-mail__recipients\">\n {labels.to}\n <Icon d={ICON.chevron} size={12} />\n </span>\n </span>\n <span className=\"adn-preview-mail__from-actions\">\n <Icon d={ICON.star} size={17} />\n </span>\n </div>\n\n <MailBody html={emailHtml} text={rendered.body} />\n {attachment ? <AttachmentCard attachment={attachment} block=\"adn-preview-attachment--mail\" /> : null}\n\n <div className=\"adn-preview-mail__reply\">\n <span className=\"adn-preview-mail__reply-button\">\n <Icon d={ICON.reply} size={14} />\n {labels.reply}\n </span>\n <span className=\"adn-preview-mail__reply-button\">\n <Icon d={ICON.replyAll} size={14} />\n {labels.replyAll}\n </span>\n <span className=\"adn-preview-mail__reply-button\">\n <Icon d={ICON.forward} size={14} />\n {labels.forward}\n </span>\n </div>\n </div>\n </div>\n </Phone>\n )\n}\n\n/**\n * A tela da conversa, e não um balão solto.\n *\n * O balão sozinho não diz como a mensagem chega: quem escreve precisa ver o cabeçalho com o\n * remetente, o balão recebido com a ponta à esquerda sobre o papel de parede, e a barra de digitar\n * embaixo — é isso que enquadra o texto no tamanho real que ele ocupa na conversa.\n */\nfunction WhatsAppPreview({\n rendered,\n labels,\n os,\n senderName,\n attachment,\n}: {\n rendered: RenderedTemplatePreview\n labels: PreviewLabels\n os: string\n senderName: string\n attachment: PreviewAttachment | undefined\n}) {\n return (\n <Phone os={os} time={labels.time}>\n <div className=\"adn-preview-wa__header\">\n <Icon d={ICON.back} size={18} />\n <span className=\"adn-preview-wa__avatar\">{senderName.slice(0, 1)}</span>\n <span className=\"adn-preview-wa__contact\">\n <span className=\"adn-preview-wa__name\">{senderName}</span>\n <span className=\"adn-preview-wa__status\">{labels.online}</span>\n </span>\n <span className=\"adn-preview-wa__header-actions\">\n <Icon d={ICON.video} size={17} />\n <Icon d={ICON.call} size={17} />\n <Icon d={ICON.more} size={17} />\n </span>\n </div>\n\n <div className=\"adn-preview-wa\">\n <div className=\"adn-preview-wa__day\">{labels.today}</div>\n <div className=\"adn-preview-wa__bubble\">\n {attachment ? <AttachmentCard attachment={attachment} block=\"adn-preview-attachment--wa\" /> : null}\n <div className=\"adn-preview-wa__text\">{rendered.body}</div>\n <div className=\"adn-preview-wa__time\">{labels.now}</div>\n </div>\n </div>\n\n <div className=\"adn-preview-wa__composer\">\n <span className=\"adn-preview-wa__input\">{labels.compose}</span>\n <span className=\"adn-preview-wa__send\">\n <Icon d={ICON.mic} size={16} />\n </span>\n </div>\n </Phone>\n )\n}\n\nfunction SmsPreview({\n rendered,\n os,\n labels,\n}: {\n rendered: RenderedTemplatePreview\n os: string\n labels: PreviewLabels\n}) {\n return (\n <Phone os={os} time={labels.time}>\n <div className=\"adn-preview-sms\">\n <div className=\"adn-preview-sms__bubble\">{rendered.body}</div>\n </div>\n </Phone>\n )\n}\n\n/** Tela bloqueada: título e corpo cortados, que é onde o limite do canal aparece de verdade. */\nfunction PushPreview({\n rendered,\n senderName,\n labels,\n os,\n}: {\n rendered: RenderedTemplatePreview\n senderName: string\n labels: PreviewLabels\n os: string\n}) {\n return (\n <Phone os={os} tone=\"dark\" time={labels.time}>\n <div className=\"adn-preview-push\">\n <div className=\"adn-preview-push__card\">\n <div className=\"adn-preview-push__app\">\n <span className=\"adn-preview-avatar adn-preview-avatar--small\">{senderName.slice(0, 1)}</span>\n <span>{senderName}</span>\n <span className=\"adn-preview-push__time\">{labels.now}</span>\n </div>\n <div className=\"adn-preview-push__title\">{rendered.title}</div>\n <div className=\"adn-preview-push__body\">{rendered.body}</div>\n </div>\n </div>\n </Phone>\n )\n}\n\n/** O aviso dentro do próprio produto — o cartão da lista de notificações. */\nfunction InboxPreview({ rendered }: { rendered: RenderedTemplatePreview }) {\n return (\n <div className=\"adn-preview-inbox\">\n <span className=\"adn-preview-inbox__dot\" />\n <div className=\"adn-preview-inbox__text\">\n <div className=\"adn-preview-inbox__title\">{rendered.title}</div>\n <div className=\"adn-preview-inbox__body\">{rendered.body}</div>\n </div>\n </div>\n )\n}\n\n/** O arquivo anexo: mesmo cartão nos canais que o mostram, só a moldura em volta muda. */\nfunction AttachmentCard({ attachment, block }: { attachment: PreviewAttachment; block: string }) {\n return (\n <div className={`adn-preview-attachment ${block}`}>\n <Icon d={ICON.file} size={18} />\n <span className=\"adn-preview-attachment__text\">\n <span className=\"adn-preview-attachment__name\">{attachment.name}</span>\n {attachment.detail ? <span className=\"adn-preview-attachment__detail\">{attachment.detail}</span> : null}\n </span>\n </div>\n )\n}\n\n/**\n * O corpo do e-mail. Com `html`, um documento inteiro dentro de `<iframe sandbox=\"\" srcDoc>`:\n * sandbox vazio é o mais restrito que existe — sem script, sem mesma-origem, sem formulário — e o\n * CSS do e-mail não vaza para o painel nem herda o dele. Sem `html`, o nó de texto de sempre.\n *\n * Altura fixa com rolagem interna: `sandbox=\"\"` impede ler `contentDocument`, então medir o\n * conteúdo não é possível — e um iframe que se auto-mede exigiria devolver a mesma-origem.\n */\nfunction MailBody({ html, text }: { html: string | undefined; text: string }) {\n if (!html) return <div className=\"adn-preview-mail__body\">{text}</div>\n\n return (\n <iframe\n className=\"adn-preview-mail__body adn-preview-mail__frame\"\n sandbox=\"\"\n srcDoc={html}\n title={text.slice(0, 60)}\n />\n )\n}\n\nexport function TemplatePreview({\n channel,\n viewport,\n rendered,\n emailHtml,\n senderName,\n attachment,\n labels,\n}: TemplatePreviewProps) {\n /** Sem nome do produto, o remetente vira a inicial do assunto — nunca um literal inventado. */\n const sender = senderName ?? rendered.title.slice(0, 1).toUpperCase()\n\n if (channel === 'whatsapp') {\n return (\n <WhatsAppPreview rendered={rendered} labels={labels} os={viewport} senderName={sender} attachment={attachment} />\n )\n }\n if (channel === 'sms') return <SmsPreview rendered={rendered} os={viewport} labels={labels} />\n if (channel === 'push') {\n return <PushPreview rendered={rendered} senderName={sender} labels={labels} os={viewport} />\n }\n if (channel === 'inbox') return <InboxPreview rendered={rendered} />\n\n return viewport === 'browser' ? (\n <EmailDesktop\n rendered={rendered}\n emailHtml={emailHtml}\n senderName={sender}\n labels={labels}\n attachment={attachment}\n />\n ) : (\n <EmailMobile\n rendered={rendered}\n emailHtml={emailHtml}\n senderName={sender}\n os={viewport}\n labels={labels}\n attachment={attachment}\n />\n )\n}\n"],"mappings":"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","names":["clsx","clsx","jsx","jsxs","clsx","jsx","jsxs","clsx","clsx","jsx","jsxs","clsx","jsx","jsxs","Trash2","useState","jsx","jsxs","useRef","useState","useState","jsx","jsxs","useState","jsx","jsxs","useRef","useState","jsx","jsxs","Fragment","jsx","jsxs","useState","jsxs","jsx","Trash2","Fragment"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/NotificationBell.tsx","../src/components/NotificationList.tsx","../src/components/NotificationItem.tsx","../src/components/PreferencesPanel.tsx","../src/components/NotificationsWorkspace.tsx","../src/components/NotificationSettingsWorkspace.tsx","../src/components/HtmlCodeField.tsx","../src/htmlHighlight.util.ts","../src/components/MessageBodyField.tsx","../src/messageFormat.util.ts","../src/components/MessageToolbar.tsx","../src/messageFormat.constant.ts","../src/components/TemplatePreview.tsx"],"sourcesContent":["/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n */\n\nimport { Bell } from 'lucide-react'\nimport clsx from 'clsx'\n\nimport { useNotificationContext } from '../NotificationProvider'\nimport { useUnreadCount } from '../hooks/useNotifications'\n\nexport type NotificationBellProps = {\n readonly onClick?: () => void\n readonly className?: string\n /** Acima disso o badge mostra `99+`; um número de 4 dígitos estoura o desenho do badge. */\n readonly maxBadgeCount?: number\n}\n\nconst DEFAULT_MAX_BADGE_COUNT = 99\n\nexport function NotificationBell({\n onClick,\n className,\n maxBadgeCount = DEFAULT_MAX_BADGE_COUNT,\n}: NotificationBellProps) {\n const { messages, theme } = useNotificationContext()\n const { data: unreadCount = 0 } = useUnreadCount()\n\n const hasUnread = unreadCount > 0\n const badgeLabel = unreadCount > maxBadgeCount ? `${maxBadgeCount}+` : String(unreadCount)\n const accessibleLabel = hasUnread\n ? `${messages['bell.label']}: ${unreadCount} ${messages['bell.unreadSuffix']}`\n : messages['bell.label']\n\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={clsx('adn-bell', theme.rootClassName, className)}\n // Botão só-ícone exige rótulo acessível (regra de ícones, `web.md` §9).\n aria-label={accessibleLabel}\n >\n {/* Decorativo: o rótulo acessível já está no botão, e anunciar o ícone repetiria a ação. */}\n <Bell className=\"adn-bell__icon\" aria-hidden=\"true\" />\n {hasUnread ? (\n // `aria-live` para leitor de tela anunciar a mudança do contador sem o usuário reabrir\n // o menu; `polite` porque notificação nova não deve interromper o que ele está lendo.\n <span className=\"adn-bell__badge\" aria-live=\"polite\">\n {badgeLabel}\n </span>\n ) : null}\n </button>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n */\n\nimport { CheckCheck, Inbox, RotateCw } from 'lucide-react'\nimport clsx from 'clsx'\nimport type { ReactNode } from 'react'\nimport type { NotificationSummary } from '@adatechnology/notification-contracts'\n\nimport { useNotificationContext } from '../NotificationProvider'\nimport { flattenNotificationPages, useMarkAllAsRead, useNotifications, useUnreadCount } from '../hooks/useNotifications'\nimport { NotificationItem } from './NotificationItem'\n\n/** Três linhas: o bastante para a lista já ter a forma dela antes de ter conteúdo. */\nconst SKELETON_ROWS = [0, 1, 2]\n\nexport type NotificationListProps = {\n readonly category?: string\n readonly onSelect?: (notification: NotificationSummary) => void\n readonly className?: string\n /**\n * Substitui o vazio padrão. Quem decide se está vazio é a lista — o host que desenhava o próprio\n * vazio ao lado dela mostrava \"nada por aqui\" embaixo das notificações que estavam ali.\n */\n readonly renderEmpty?: () => ReactNode\n /** Slot: o host troca a linha sem reimplementar a lista (regra §4.3, slots e overrides). */\n readonly components?: { readonly Item?: typeof NotificationItem }\n}\n\nexport function NotificationList({ category, onSelect, className, renderEmpty, components }: NotificationListProps) {\n const { messages, theme } = useNotificationContext()\n const query = useNotifications({ category })\n const { data: unreadCount = 0 } = useUnreadCount()\n const markAllAsRead = useMarkAllAsRead()\n\n const Item = components?.Item ?? NotificationItem\n const notifications = flattenNotificationPages(query.data?.pages)\n const isEmpty = !query.isPending && !query.isError && notifications.length === 0\n\n return (\n <section className={clsx('adn-list', theme.rootClassName, className)} aria-label={messages['list.title']}>\n <header className=\"adn-list__header\">\n <div className=\"adn-list__heading\">\n <h2 className=\"adn-list__title\">{messages['list.title']}</h2>\n {/* O contador estava só no sino. Quem abriu a tela pelo menu lateral não passou pelo sino,\n e ficava sem saber quantas ainda pedem atenção. */}\n {unreadCount > 0 ? (\n <span className=\"adn-list__count\" role=\"status\" aria-label={`${unreadCount} ${messages['list.unread']}`}>\n {unreadCount}\n </span>\n ) : null}\n </div>\n\n {unreadCount > 0 ? (\n <button\n type=\"button\"\n className=\"adn-list__bulk-action\"\n onClick={() => markAllAsRead.mutate()}\n disabled={markAllAsRead.isPending}\n >\n <CheckCheck className=\"adn-list__bulk-icon\" aria-hidden=\"true\" />\n {messages['list.markAllAsRead']}\n </button>\n ) : null}\n </header>\n\n {/* Esqueleto com a forma da linha real, em vez de \"Carregando…\" centralizado: o texto some e o\n conteúdo entra de altura diferente, e a tela pisca a cada carregamento. */}\n {query.isPending ? (\n <div className=\"adn-list__skeleton\" role=\"status\" aria-label={messages['list.loading']}>\n {SKELETON_ROWS.map((row) => (\n <span key={row} className=\"adn-list__skeleton-row\" />\n ))}\n </div>\n ) : null}\n\n {query.isError ? (\n <div className=\"adn-list__state adn-list__state--error\" role=\"alert\">\n <p>{messages['list.error']}</p>\n <button type=\"button\" className=\"adn-list__retry\" onClick={() => void query.refetch()}>\n <RotateCw className=\"adn-list__retry-icon\" aria-hidden=\"true\" />\n {messages['list.retry']}\n </button>\n </div>\n ) : null}\n\n {isEmpty\n ? (renderEmpty?.() ?? (\n <div className=\"adn-list__state adn-list__state--empty\">\n <Inbox className=\"adn-list__empty-icon\" aria-hidden=\"true\" />\n <p>{messages['list.empty']}</p>\n </div>\n ))\n : null}\n\n {notifications.length > 0 ? (\n <ul className=\"adn-list__items\">\n {notifications.map((notification) => (\n <Item key={notification.id} notification={notification} onSelect={onSelect} />\n ))}\n </ul>\n ) : null}\n\n {query.hasNextPage ? (\n <div className=\"adn-list__footer\">\n <button\n type=\"button\"\n className=\"adn-list__load-more\"\n onClick={() => void query.fetchNextPage()}\n disabled={query.isFetchingNextPage}\n >\n {messages['list.loadMore']}\n </button>\n </div>\n ) : null}\n </section>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n */\n\nimport { Check, Trash2 } from 'lucide-react'\nimport clsx from 'clsx'\nimport type { NotificationSummary } from '@adatechnology/notification-contracts'\n\nimport { useNotificationContext } from '../NotificationProvider'\nimport { formatNotificationTime, formatNotificationTimestamp } from '../format/notificationTime'\nimport { useDeleteNotification, useMarkAsRead } from '../hooks/useNotifications'\n\nexport type NotificationItemProps = {\n readonly notification: NotificationSummary\n readonly onSelect?: (notification: NotificationSummary) => void\n readonly className?: string\n}\n\nexport function NotificationItem({ notification, onSelect, className }: NotificationItemProps) {\n const { locale, messages } = useNotificationContext()\n const markAsRead = useMarkAsRead()\n const deleteNotification = useDeleteNotification()\n\n const isUnread = notification.readAt === undefined\n\n function handleSelect(): void {\n if (isUnread) markAsRead.mutate(notification.id)\n onSelect?.(notification)\n }\n\n return (\n <li className={clsx('adn-item', isUnread && 'adn-item--unread', className)}>\n {/* Semântico: a linha inteira é clicável e precisa ser alcançável por teclado — `button`\n entrega Enter, Espaço e foco de graça, e um `div` com onClick não (web.md §Acessibilidade). */}\n <button type=\"button\" className=\"adn-item__main\" onClick={handleSelect}>\n <span className=\"adn-item__heading\">\n {/* Marcador à esquerda, na altura do título: sobreposto ao canto, ele cobria a última\n palavra do texto em linha comprida. */}\n {isUnread ? <span className=\"adn-item__unread-dot\" aria-label={messages['item.unread']} /> : null}\n <span className=\"adn-item__title\">{notification.title}</span>\n {/* `<time>` e não `<span>`: a data legível por máquina é o que um leitor de tela e um\n agregador conseguem interpretar; o texto visível é o relativo, que é o que se lê. */}\n <time\n className=\"adn-item__time\"\n dateTime={notification.createdAt}\n title={formatNotificationTimestamp(notification.createdAt, locale)}\n >\n {formatNotificationTime(notification.createdAt, locale, new Date())}\n </time>\n </span>\n <span className=\"adn-item__body\">{notification.body}</span>\n </button>\n\n <div className=\"adn-item__actions\">\n {isUnread ? (\n <button\n type=\"button\"\n className=\"adn-item__action\"\n onClick={() => markAsRead.mutate(notification.id)}\n disabled={markAsRead.isPending}\n aria-label={messages['item.markAsRead']}\n title={messages['item.markAsRead']}\n >\n <Check className=\"adn-item__action-icon\" aria-hidden=\"true\" />\n </button>\n ) : null}\n\n <button\n type=\"button\"\n className=\"adn-item__action adn-item__action--danger\"\n onClick={() => deleteNotification.mutate(notification.id)}\n disabled={deleteNotification.isPending}\n aria-label={messages['item.delete']}\n title={messages['item.delete']}\n >\n {/* Ação destrutiva: ícone reforça o peso antes do clique (regra de ícones). */}\n <Trash2 className=\"adn-item__action-icon\" aria-hidden=\"true\" />\n </button>\n </div>\n </li>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n */\n\nimport { useState } from 'react'\nimport { Save } from 'lucide-react'\nimport clsx from 'clsx'\nimport type { NotificationPreference } from '@adatechnology/notification-contracts'\n\nimport { useNotificationContext } from '../NotificationProvider'\nimport { usePreferences, useUpdatePreferences } from '../hooks/usePreferences'\n\nexport type PreferencesPanelProps = {\n readonly className?: string\n}\n\nfunction channelLabelKey(channel: string): string {\n return `channel.${channel}`\n}\n\nexport function PreferencesPanel({ className }: PreferencesPanelProps) {\n const { messages, theme } = useNotificationContext()\n const { data: saved = [], isPending } = usePreferences()\n const updatePreferences = useUpdatePreferences()\n\n // Rascunho local só existe entre abrir e salvar: `undefined` significa \"ainda não mexeu\", e é o\n // que faz o painel refletir o servidor sem sobrescrever edição em andamento a cada refetch.\n const [draft, setDraft] = useState<NotificationPreference[] | undefined>(undefined)\n const preferences = draft ?? saved\n\n function toggleChannel(target: NotificationPreference): void {\n setDraft(\n preferences.map((preference) =>\n preference.category === target.category && preference.channel === target.channel\n ? { ...preference, enabled: !preference.enabled }\n : preference,\n ),\n )\n }\n\n function handleSave(): void {\n updatePreferences.mutate(preferences, { onSuccess: () => setDraft(undefined) })\n }\n\n if (isPending) return <p className=\"adn-preferences__state\">{messages['list.loading']}</p>\n\n return (\n <section className={clsx('adn-preferences', theme.rootClassName, className)}>\n <header className=\"adn-preferences__header\">\n <h2 className=\"adn-preferences__title\">{messages['preferences.title']}</h2>\n <p className=\"adn-preferences__description\">{messages['preferences.description']}</p>\n </header>\n\n {preferences.length === 0 ? (\n <p className=\"adn-preferences__state\">{messages['preferences.empty']}</p>\n ) : (\n <ul className=\"adn-preferences__items\">\n {preferences.map((preference) => {\n const inputId = `adn-pref-${preference.category}-${preference.channel}`\n return (\n <li key={inputId} className=\"adn-preferences__item\">\n {/* `label` associado por `htmlFor`: aumenta a área de toque e é o que faz o\n leitor de tela anunciar canal e estado juntos. */}\n <label className=\"adn-preferences__label\" htmlFor={inputId}>\n <input\n id={inputId}\n type=\"checkbox\"\n className=\"adn-preferences__checkbox\"\n checked={preference.enabled}\n onChange={() => toggleChannel(preference)}\n />\n <span className=\"adn-preferences__category\">{preference.category}</span>\n <span className=\"adn-preferences__channel\">\n {messages[channelLabelKey(preference.channel) as keyof typeof messages] ?? preference.channel}\n </span>\n </label>\n\n {preference.quietHoursStart && preference.quietHoursEnd ? (\n <span className=\"adn-preferences__quiet-hours\">\n {messages['preferences.quietHours']} {preference.quietHoursStart}{' '}\n {messages['preferences.quietHoursTo']} {preference.quietHoursEnd}\n </span>\n ) : null}\n </li>\n )\n })}\n </ul>\n )}\n\n <footer className=\"adn-preferences__footer\">\n {/* Ação primária de formulário com convenção clara → ícone (regra de ícones, web.md §9). */}\n <button\n type=\"button\"\n className=\"adn-preferences__save\"\n onClick={handleSave}\n disabled={updatePreferences.isPending || draft === undefined}\n >\n <Save className=\"adn-preferences__save-icon\" aria-hidden=\"true\" />\n {messages['preferences.save']}\n </button>\n\n {updatePreferences.isSuccess && draft === undefined ? (\n <span className=\"adn-preferences__feedback\" role=\"status\">\n {messages['preferences.saved']}\n </span>\n ) : null}\n {updatePreferences.isError ? (\n <span className=\"adn-preferences__feedback adn-preferences__feedback--error\" role=\"alert\">\n {messages['preferences.error']}\n </span>\n ) : null}\n </footer>\n </section>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * A tela de notificações COMPOSTA, no molde do `ConversationsWorkspace`.\n *\n * O pacote exportava só as peças (`NotificationList`, `PreferencesPanel`), e o primeiro consumidor\n * remontou o grid à mão — 56 linhas na página da inbox e 221 na de configuração, contra 35 da página\n * de Documentos, que consome workspace. É exatamente o que a regra de módulos plugáveis (§4) rejeita:\n * cada produto remontando o layout é como as telas divergiram antes.\n *\n * Customização por contrato, nunca por fork:\n * - vocabulário → `labels`\n * - UI do produto → slots `renderHeaderActions`, `renderAboveList`, `renderEmpty`\n * - regra de negócio → callbacks (`onSelectNotification`)\n * - **capacidade por ausência**: sem `settingsHref` não aparece link de configuração, sem\n * `showPreferences` não aparece a coluna. Nunca flag `hasX`.\n */\n\nimport type { ReactNode } from 'react'\nimport type { NotificationSummary } from '@adatechnology/notification-contracts'\n\nimport { useNotificationContext } from '../NotificationProvider'\nimport { NotificationList } from './NotificationList'\nimport { PreferencesPanel } from './PreferencesPanel'\n\nexport type NotificationsWorkspaceProps = {\n /** Sobrescreve textos pontuais sem trocar o locale inteiro. */\n readonly labels?: Partial<Record<string, string>>\n /** Filtra a inbox por assunto. Ausente, mostra tudo. */\n readonly category?: string\n /**\n * Coluna de preferências ao lado da inbox.\n *\n * Ligada por padrão porque é o caso comum; um produto que gerencia preferência noutra tela passa\n * `false` e fica só com a inbox, em largura cheia.\n */\n readonly showPreferences?: boolean\n /** Ausente, o link de configuração não aparece — o produto pode não ter essa tela. */\n readonly settingsHref?: string | undefined\n /** Clique numa notificação. Ausente, a linha não é clicável. */\n readonly onSelectNotification?: (notification: NotificationSummary) => void\n /**\n * Substitui o cabeçalho padrão inteiro.\n *\n * O workspace desenha um `<h1>` porque ele é a tela; a página que já tem o título dela passava a\n * ter dois `<h1>` dizendo a mesma palavra, e para leitor de tela duas primeiras manchetes é o\n * mesmo que nenhuma. Ausente, o padrão continua desenhando — slot é substituição, não interruptor.\n */\n readonly renderHeader?: () => ReactNode\n /** Ações do produto no cabeçalho, ao lado do link de configuração. */\n readonly renderHeaderActions?: () => ReactNode\n /** Aviso ou filtro do produto, entre o cabeçalho e a lista. */\n readonly renderAboveList?: () => ReactNode\n /** Substitui o vazio padrão — útil quando o produto sabe explicar por que está vazio. */\n readonly renderEmpty?: () => ReactNode\n readonly className?: string\n}\n\nexport function NotificationsWorkspace({\n labels: labelsOverride,\n category,\n showPreferences = true,\n settingsHref,\n onSelectNotification,\n renderHeader,\n renderHeaderActions,\n renderAboveList,\n renderEmpty,\n className,\n}: NotificationsWorkspaceProps) {\n const { messages } = useNotificationContext()\n const label = (key: string): string => labelsOverride?.[key] ?? (messages as Record<string, string>)[key] ?? key\n\n return (\n <div className={`adn-workspace ${className ?? ''}`}>\n {renderHeader ? (\n renderHeader()\n ) : (\n <header className=\"adn-workspace__header\">\n <div>\n <h1 className=\"adn-workspace__title\">{label('workspace.title')}</h1>\n <p className=\"adn-workspace__description\">{label('workspace.description')}</p>\n </div>\n\n <div className=\"adn-workspace__actions\">\n {renderHeaderActions?.()}\n {/* Capacidade por ausência: sem href, sem link. */}\n {settingsHref && (\n <a href={settingsHref} className=\"adn-button adn-button--outline\">\n {label('workspace.settingsLink')}\n </a>\n )}\n </div>\n </header>\n )}\n\n {renderAboveList?.()}\n\n <div className={showPreferences ? 'adn-workspace__grid' : 'adn-workspace__grid--single'}>\n <section className=\"adn-workspace__inbox\">\n {/* O vazio desce para a lista, que é quem sabe se está vazia. Desenhado aqui, ele aparecia\n ao lado das notificações — \"nada por aqui\" embaixo do que estava ali. */}\n <NotificationList\n {...(category ? { category } : {})}\n {...(onSelectNotification ? { onSelect: onSelectNotification } : {})}\n {...(renderEmpty ? { renderEmpty } : {})}\n />\n </section>\n\n {showPreferences && (\n <aside className=\"adn-workspace__aside\">\n <PreferencesPanel />\n </aside>\n )}\n </div>\n </div>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * A tela de configuração COMPOSTA: canais por assunto e editor de mensagem com preview.\n *\n * Substitui as 221 linhas de página + 207 de hook que o primeiro consumidor escreveu. O que sobra\n * para o produto é dizer quais canais e assuntos existem — o resto é layout, e layout duplicado é\n * como as telas divergem.\n *\n * `channels` e `categories` são OBRIGATÓRIOS e vêm do produto porque o pacote não tem opinião sobre\n * eles: uma loja avisa status de pedido por WhatsApp, um banco avisa vencimento por e-mail, e o\n * `hint` de cada canal (\"exige template aprovado\", \"exige aparelho registrado\") é conhecimento do\n * produto sobre a própria operação.\n */\n\nimport { Plus, Trash2, X } from 'lucide-react'\nimport { Fragment, useState } from 'react'\nimport type { CSSProperties, ReactNode } from 'react'\nimport type { NotificationPreference, NotificationTemplate } from '@adatechnology/notification-contracts'\n\nimport {\n SORT_DIRECTIONS,\n TEMPLATE_COLUMNS,\n TEMPLATE_VIEWS,\n type TemplateSortField,\n} from '../templateList.constant'\nimport { useNotificationContext } from '../NotificationProvider'\nimport { usePreferences, useUpdatePreferences } from '../hooks/usePreferences'\nimport { useCategoryPolicies } from '../hooks/useCategoryPolicies'\nimport { HtmlCodeField } from './HtmlCodeField'\nimport { MessageBodyField } from './MessageBodyField'\nimport { TemplatePreview } from './TemplatePreview'\nimport { useTemplateEditor } from '../hooks/useTemplateEditor'\nimport { isStandardEmailKey } from '../standardEmail.util'\nimport type { TemplateDraftField } from '../hooks/useTemplateEditor'\n\nexport type NotificationChannelOption = {\n readonly id: string\n readonly label: string\n /** O custo do canal, em uma linha. É o que faz alguém decidir em vez de chutar. */\n readonly hint?: string\n}\n\nexport type NotificationCategoryOption = {\n readonly id: string\n readonly label: string\n readonly hint?: string\n}\n\n/** O laudo do validador, na forma mínima que a tela precisa desenhar. */\nexport type EmailHtmlReport = {\n readonly isValid: boolean\n readonly problems: readonly {\n readonly code: string\n readonly severity: string\n readonly message: string\n }[]\n}\n\nexport type NotificationSettingsWorkspaceProps = {\n readonly labels?: Partial<Record<string, string>>\n /** Os canais que ESTE produto oferece — o pacote despacha em cinco e não opina sobre quais usar. */\n readonly channels: readonly NotificationChannelOption[]\n /** Os assuntos que este produto dispara. */\n readonly categories: readonly NotificationCategoryOption[]\n /**\n * Valores de exemplo do preview, por assunto do template. Ausente, o preview mostra campo vazio —\n * que é honesto, mas menos útil para quem está escrevendo o texto.\n */\n readonly previewPayload?: Readonly<Record<string, unknown>>\n /** Traduz `order.status.preparing` no rótulo que o produto usa. Ausente, mostra a chave crua. */\n readonly templateLabelOf?: (template: NotificationTemplate) => string\n /**\n * Campo extra por canal — é onde entra o nome do template aprovado na Meta, que só o WhatsApp tem.\n * Ausente, nenhum campo extra aparece.\n */\n readonly renderChannelFields?: (params: {\n readonly channel: string\n readonly value: string\n readonly onChange: (value: string) => void\n }) => ReactNode\n /**\n * Confere o documento contra o que cliente de e-mail realmente faz (script, folha externa, imagem\n * em `data:`, tabela desbalanceada). Ausente, nenhum aviso aparece.\n */\n readonly validateEmailHtml?: (html: string) => EmailHtmlReport\n /**\n * Ações do produto no cabeçalho do EDITOR, ao lado de Fechar — recebe a chave do template aberto.\n *\n * É onde entra \"Enviar teste\": provar que a mensagem chega é operação do produto, não do pacote.\n * O pacote não sabe para quem mandar, por qual rota, nem o que fazer com o resultado; ele sabe\n * qual template está aberto, e é só isso que o slot precisa entregar.\n */\n readonly renderEditorActions?: (params: { readonly templateKey: string }) => ReactNode\n /** Substitui o cabeçalho padrão — a página que já tem título próprio evita o segundo `<h1>`. */\n readonly renderHeader?: () => ReactNode\n /** Ações do produto no cabeçalho. */\n readonly renderHeaderActions?: () => ReactNode\n readonly className?: string\n /**\n * Nome do produto no preview: e o remetente do e-mail e o app do push. O pacote nao sabe de\n * quem e a marca, e \"Aviso\" generico faria o preview mentir sobre o que a pessoa ve.\n */\n readonly senderName?: string\n /** Rótulo humano de uma categoria (`auth` → \"Acesso\"). Ausente, mostra a própria chave. */\n readonly categoryLabelOf?: (category: string) => string\n}\n\n/**\n * O laudo do e-mail, so quando ha o que dizer.\n *\n * Documento limpo nao ganha selo verde: um aviso permanente de \"tudo certo\" e ruido que treina a\n * pessoa a nao ler a area — e ai o aviso de verdade passa batido junto.\n */\n/**\n * O campo vira editor de codigo quando o texto TEM marcacao, e nao quando o canal e e-mail: a\n * maioria dos avisos e texto simples, e transformar o campo deles num editor com numeracao de linha\n * cobra complexidade de quem so queria escrever uma frase.\n */\nfunction isHtmlBody(body: string): boolean {\n return /<\\/?[a-zA-Z][\\w:-]*(\\s|>|\\/)/.test(body)\n}\n\nfunction renderEmailProblems(report: EmailHtmlReport): ReactNode {\n if (report.problems.length === 0) return null\n\n return (\n <ul className=\"adn-settings__email-report\">\n {report.problems.map((problem) => (\n <li key={problem.code} className={`adn-settings__email-problem adn-settings__email-problem--${problem.severity}`}>\n {problem.message}\n </li>\n ))}\n </ul>\n )\n}\n\nexport function NotificationSettingsWorkspace({\n labels: labelsOverride,\n channels,\n categories,\n previewPayload,\n templateLabelOf,\n renderChannelFields,\n renderEditorActions,\n validateEmailHtml,\n renderHeader,\n renderHeaderActions,\n className,\n senderName,\n categoryLabelOf,\n}: NotificationSettingsWorkspaceProps) {\n const { messages } = useNotificationContext()\n const label = (key: string): string => labelsOverride?.[key] ?? (messages as Record<string, string>)[key] ?? key\n\n const preferencesQuery = usePreferences()\n const updatePreferences = useUpdatePreferences()\n const editor = useTemplateEditor({\n ...(previewPayload ? { previewPayload } : {}),\n ...(channels[0] ? { defaultChannel: channels[0].id } : {}),\n })\n\n /**\n * Onde inserir a variável. Guardado no `onSelect` dos campos porque o hook não pode conhecer o\n * DOM — e sem isso o clique na variável só saberia concatenar no fim, que é justamente o lugar\n * errado quando se está corrigindo o meio de uma frase.\n */\n const [cursor, setCursor] = useState<{ field: TemplateDraftField; cursorIndex: number }>({\n field: 'body',\n cursorIndex: 0,\n })\n\n /** Em qual canal o cursor estava: com um editor por canal, inserir variavel precisa saber onde. */\n const [cursorChannel, setCursorChannel] = useState<string | undefined>(undefined)\n /** Aba de canal aberta. `undefined` cai no primeiro marcado, para nunca abrir em branco. */\n const [activeChannel, setActiveChannel] = useState<string | undefined>(undefined)\n\n function rememberCursor(field: TemplateDraftField, cursorIndex: number | null): void {\n setCursor({ field, cursorIndex: cursorIndex ?? 0 })\n }\n\n const policies = useCategoryPolicies()\n const [tab, setTab] = useState<'messages' | 'routing'>('messages')\n\n /**\n * Preferência ausente é o estado inicial normal — o módulo devolve só o que foi gravado. O default\n * é ligado: comportamento de fábrica é avisar, e um destinatário que não recebeu porque a linha não\n * existia é pior que um que recebeu demais.\n */\n function isEnabled(category: string, channel: string): boolean {\n const row = (preferencesQuery.data ?? []).find(\n (preference) => preference.category === category && preference.channel === channel,\n )\n return row?.enabled ?? true\n }\n\n function toggle(category: string, channel: string): void {\n // Conjunto inteiro: a rota é `PUT` em lote, e enviar só o que mudou apagaria o resto.\n const next: NotificationPreference[] = categories.flatMap((eachCategory) =>\n channels.map((eachChannel) => ({\n category: eachCategory.id,\n channel: eachChannel.id as NotificationPreference['channel'],\n enabled:\n eachCategory.id === category && eachChannel.id === channel\n ? !isEnabled(category, channel)\n : isEnabled(eachCategory.id, eachChannel.id),\n })),\n )\n updatePreferences.mutate(next)\n }\n\n /**\n * Três estados no cabeçalho (web.md §7): a seta neutra diz que a coluna ORDENA, e é por isso que\n * ela aparece antes de qualquer clique.\n */\n function sortMarkOf(field: TemplateSortField): string {\n if (editor.sort?.field !== field) return '↕'\n return editor.sort.direction === SORT_DIRECTIONS.ASC ? '↑' : '↓'\n }\n\n function ariaSortOf(field: TemplateSortField): 'ascending' | 'descending' | 'none' {\n if (editor.sort?.field !== field) return 'none'\n return editor.sort.direction === SORT_DIRECTIONS.ASC ? 'ascending' : 'descending'\n }\n\n return (\n <div className={`adn-settings ${className ?? ''}`}>\n {renderHeader ? (\n renderHeader()\n ) : (\n <header className=\"adn-settings__header\">\n <div>\n <h1 className=\"adn-settings__title\">{label('settings.title')}</h1>\n <p className=\"adn-settings__description\">{label('settings.description')}</p>\n </div>\n {renderHeaderActions?.()}\n </header>\n )}\n\n <div className=\"adn-settings__tabs\" role=\"tablist\">\n {(['messages', 'routing'] as const).map((id) => (\n <button\n key={id}\n type=\"button\"\n role=\"tab\"\n aria-selected={tab === id}\n className={tab === id ? 'adn-settings__tab adn-settings__tab--active' : 'adn-settings__tab'}\n onClick={() => setTab(id)}\n >\n {label(`settings.tab.${id}`)}\n </button>\n ))}\n </div>\n\n {tab === 'routing' && (\n <section className=\"adn-settings__policies\">\n <h2 className=\"adn-settings__section-title\">{label('settings.policiesTitle')}</h2>\n <p className=\"adn-settings__hint\">{label('settings.policiesHint')}</p>\n\n {categories.map((category) => (\n <div key={category.id} className=\"adn-settings__category\">\n <p className=\"adn-settings__category-title\">{category.label}</p>\n <div className=\"adn-settings__category-channels\">\n {channels.map((channel) => (\n <label key={channel.id} className=\"adn-settings__toggle\">\n <input\n type=\"checkbox\"\n checked={policies.isAllowed({ category: category.id, channel: channel.id })}\n onChange={() => policies.toggle({ category: category.id, channel: channel.id })}\n />\n <span className=\"adn-settings__channel-label\">{channel.label}</span>\n </label>\n ))}\n </div>\n </div>\n ))}\n\n {policies.error && <p className=\"adn-settings__error\">{policies.error}</p>}\n\n <div className=\"adn-settings__actions\">\n <button type=\"button\" onClick={policies.save} disabled={!policies.isDirty || policies.isSaving}>\n {policies.isSaving ? label('settings.saving') : label('settings.savePolicies')}\n </button>\n {policies.isDirty && (\n <button type=\"button\" onClick={policies.reset}>\n {label('settings.discard')}\n </button>\n )}\n </div>\n </section>\n )}\n\n {tab === 'routing' && (\n <section className=\"adn-settings__channels\">\n <h2 className=\"adn-settings__section-title\">{label('settings.channelsTitle')}</h2>\n <p className=\"adn-settings__hint\">{label('settings.channelsHint')}</p>\n\n {categories.map((category) => (\n <div key={category.id} className=\"adn-settings__category\">\n <p className=\"adn-settings__category-label\">{category.label}</p>\n {category.hint && <p className=\"adn-settings__hint\">{category.hint}</p>}\n\n <div className=\"adn-settings__channel-grid\">\n {channels.map((channel) => (\n <label key={channel.id} className=\"adn-settings__channel\">\n <input\n type=\"checkbox\"\n checked={isEnabled(category.id, channel.id)}\n disabled={updatePreferences.isPending}\n onChange={() => toggle(category.id, channel.id)}\n />\n <span>\n <span className=\"adn-settings__channel-label\">{channel.label}</span>\n {channel.hint && <span className=\"adn-settings__hint\">{channel.hint}</span>}\n </span>\n </label>\n ))}\n </div>\n </div>\n ))}\n </section>\n )}\n\n {/* Sem rascunho a coluna do editor nao existe: a lista fica com a largura inteira. Reservar\n 2/3 da tela para \"escolha uma mensagem\" e cobrar espaco por uma instrucao. */}\n {tab === 'messages' && (\n <div className={editor.draft ? 'adn-settings__templates' : 'adn-settings__templates adn-settings__templates--browsing'}>\n <section className=\"adn-settings__template-list\">\n <header className=\"adn-settings__list-header\">\n {/* Titulo e acao na MESMA linha; a explicacao desce inteira embaixo. Com os tres lado a\n lado numa coluna de 320px a explicacao quebrava em tres linhas e empurrava o botao. */}\n <div className=\"adn-settings__list-header-row\">\n <h2 className=\"adn-settings__section-title\">{label('settings.templatesTitle')}</h2>\n <div className=\"adn-settings__list-header-actions\">\n {/* Duas leituras da mesma colecao: a tabela compara, a lista reconhece o texto. */}\n <div className=\"adn-settings__view-switch\" role=\"group\" aria-label={label('settings.viewLabel')}>\n {[TEMPLATE_VIEWS.TABLE, TEMPLATE_VIEWS.LIST].map((view) => (\n <button\n key={view}\n type=\"button\"\n aria-pressed={editor.view === view}\n className={\n editor.view === view\n ? 'adn-settings__view adn-settings__view--on'\n : 'adn-settings__view'\n }\n onClick={() => editor.setView(view)}\n >\n {label(`settings.view.${view}`)}\n </button>\n ))}\n </div>\n <button type=\"button\" className=\"adn-settings__new\" onClick={editor.startNew}>\n {/* Decorativo: o rotulo ao lado ja diz a acao, e o leitor de tela nao repete. */}\n <Plus className=\"adn-settings__button-icon\" aria-hidden=\"true\" />\n {label('settings.newTemplate')}\n </button>\n </div>\n </div>\n </header>\n\n {/* Busca sobre chave E texto: quem procura costuma lembrar do que a mensagem diz, não\n da chave técnica. */}\n <div className=\"adn-settings__list-filters\">\n <label className=\"adn-settings__search\">\n <span className=\"adn-settings__field-label adn-settings__visually-hidden\">\n {label('settings.searchLabel')}\n </span>\n <input\n type=\"search\"\n value={editor.search}\n placeholder={label('settings.searchPlaceholder')}\n onChange={(event) => editor.setSearch(event.target.value)}\n />\n </label>\n\n {editor.categories.length > 1 && (\n <div className=\"adn-settings__filter-row\">\n {editor.categories.map((category) => (\n <button\n key={category}\n type=\"button\"\n aria-pressed={editor.categoryFilter.includes(category)}\n className={\n editor.categoryFilter.includes(category)\n ? 'adn-settings__filter adn-settings__filter--on'\n : 'adn-settings__filter'\n }\n onClick={() => editor.toggleCategoryFilter(category)}\n >\n {categoryLabelOf?.(category) ?? category}\n </button>\n ))}\n </div>\n )}\n\n <div className=\"adn-settings__filter-row\">\n {channels.map((channel) => (\n <button\n key={channel.id}\n type=\"button\"\n aria-pressed={editor.channelFilter.includes(channel.id)}\n className={\n editor.channelFilter.includes(channel.id)\n ? 'adn-settings__filter adn-settings__filter--on'\n : 'adn-settings__filter'\n }\n onClick={() => editor.toggleChannelFilter(channel.id)}\n >\n {channel.label}\n </button>\n ))}\n </div>\n\n {/* Só aparece quando há o que limpar (web.md §7). */}\n {editor.hasFilters && (\n <button type=\"button\" className=\"adn-settings__clear\" onClick={editor.clearFilters}>\n {label('settings.clearFilters')}\n </button>\n )}\n </div>\n\n {editor.isLoading && <p className=\"adn-settings__hint\">{label('list.loading')}</p>}\n\n {/* \"Nada cadastrado\" e \"nada encontrado\" são estados diferentes: o primeiro pede criar,\n o segundo pede afrouxar o filtro. */}\n {!editor.isLoading && editor.totalCount === 0 && (\n <p className=\"adn-settings__hint\">{label('settings.templatesEmpty')}</p>\n )}\n {!editor.isLoading && editor.totalCount > 0 && editor.templates.length === 0 && (\n <p className=\"adn-settings__hint\">{label('settings.noResults')}</p>\n )}\n\n {editor.view === TEMPLATE_VIEWS.TABLE && editor.templates.length > 0 && (\n /* `overflow-x` no contêiner: a página nunca rola na horizontal (web.md §10). */\n <div className=\"adn-settings__table-scroll\">\n <table className=\"adn-settings__table\">\n <thead>\n <tr>\n {TEMPLATE_COLUMNS.map(({ labelKey, field, headerHidden }) => (\n <th key={labelKey} scope=\"col\" aria-sort={field ? ariaSortOf(field) : undefined}>\n {field ? (\n <button type=\"button\" onClick={() => editor.toggleSort(field)}>\n {label(labelKey)}\n <span aria-hidden=\"true\" className=\"adn-settings__sort-mark\">\n {sortMarkOf(field)}\n </span>\n </button>\n ) : (\n <span className={headerHidden ? 'adn-settings__visually-hidden' : undefined}>\n {label(labelKey)}\n </span>\n )}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {editor.templates.map((template) => (\n /* A linha inteira abre o template: na tabela so a celula da chave era clicavel,\n e o alvo real de quem varre a lista e a linha. O botao da chave continua\n existindo — e ele que recebe o foco pelo teclado. */\n <tr\n key={template.id}\n onClick={() => editor.select(template)}\n className={\n editor.selected?.id === template.id\n ? 'adn-settings__table-row adn-settings__table-row--active'\n : 'adn-settings__table-row'\n }\n >\n <td>\n <button\n type=\"button\"\n className=\"adn-settings__table-key\"\n onClick={() => editor.select(template)}\n >\n {templateLabelOf?.(template) ?? template.key}\n </button>\n </td>\n <td className=\"adn-settings__table-body\">{template.body}</td>\n <td>\n <span className={`adn-settings__badge adn-settings__badge--${template.channel}`}>\n {label(`channel.${template.channel}`)}\n </span>\n </td>\n <td className=\"adn-settings__version\">\n {label('settings.version')}\n {template.version}\n </td>\n <td>\n {isStandardEmailKey(template.key) ? (\n /* Modelo do sistema não se remove: o servidor recusa e o envio depende dele. */\n <span className=\"adn-settings__badge\">{label('settings.systemTemplate')}</span>\n ) : (\n <button\n type=\"button\"\n className=\"adn-settings__remove\"\n aria-label={`${label('settings.remove')} ${template.key}`}\n disabled={editor.isDeactivating}\n /* Sem parar a propagacao, remover tambem abriria o template no editor. */\n onClick={(event) => {\n event.stopPropagation()\n editor.deactivate(template.id)\n }}\n >\n <Trash2 className=\"adn-settings__button-icon\" aria-hidden=\"true\" />\n {label('settings.remove')}\n </button>\n )}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n {editor.view === TEMPLATE_VIEWS.LIST &&\n editor.groups.map((group) => (\n <div key={group.category} className=\"adn-settings__group\">\n <p className=\"adn-settings__group-title\">\n {categoryLabelOf?.(group.category) ?? group.category}\n <span className=\"adn-settings__group-count\">{group.templates.length}</span>\n </p>\n <ul>\n {group.templates.map((template) => (\n <li key={template.id} className=\"adn-settings__row\">\n <button\n type=\"button\"\n onClick={() => editor.select(template)}\n className={editor.selected?.id === template.id ? 'adn-settings__row--active' : undefined}\n >\n <span className=\"adn-settings__row-main\">\n <span className=\"adn-settings__row-title\">{templateLabelOf?.(template) ?? template.key}</span>\n <span className=\"adn-settings__row-body\">{template.body}</span>\n </span>\n <span className={`adn-settings__badge adn-settings__badge--${template.channel}`}>\n {label(`channel.${template.channel}`)}\n </span>\n <span className=\"adn-settings__version\">\n {label('settings.version')}\n {template.version}\n </span>\n </button>\n {isStandardEmailKey(template.key) ? (\n <span className=\"adn-settings__badge\">{label('settings.systemTemplate')}</span>\n ) : (\n <button\n type=\"button\"\n className=\"adn-settings__remove\"\n aria-label={`${label('settings.remove')} ${template.key}`}\n disabled={editor.isDeactivating}\n onClick={() => editor.deactivate(template.id)}\n >\n <Trash2 className=\"adn-settings__button-icon\" aria-hidden=\"true\" />\n {label('settings.remove')}\n </button>\n )}\n </li>\n ))}\n </ul>\n </div>\n ))}\n </section>\n\n {editor.draft && (\n <section className=\"adn-settings__editor\">\n {(\n <>\n <header className=\"adn-settings__editor-header\">\n <div>\n <h2 className=\"adn-settings__section-title\">\n {editor.selected ? (templateLabelOf?.(editor.selected) ?? editor.selected.key) : ''}\n {editor.isStandardEmail && (\n <span className=\"adn-settings__badge\">{label('settings.systemTemplate')}</span>\n )}\n </h2>\n <p className=\"adn-settings__hint\">\n {editor.draft.channels.join(' · ')} · {editor.draft.locale} · {label('settings.version')}\n {editor.selected?.version}\n </p>\n </div>\n <div className=\"adn-settings__editor-actions\">\n {/* Antes do Fechar: a ação do produto é o que a pessoa procura ali; Fechar é saída. */}\n {editor.selected && renderEditorActions?.({ templateKey: editor.selected.key })}\n {editor.isStandardEmail && editor.selected && (\n <button\n type=\"button\"\n className=\"adn-settings__restore\"\n disabled={editor.isRestoring}\n onClick={() => editor.selected && editor.restoreDefault(editor.selected.id)}\n >\n {editor.isRestoring ? label('settings.restoring') : label('settings.restoreDefault')}\n </button>\n )}\n <button type=\"button\" className=\"adn-settings__close\" onClick={editor.clear}>\n <X className=\"adn-settings__button-icon\" aria-hidden=\"true\" />\n {label('settings.close')}\n </button>\n </div>\n </header>\n\n {!editor.isIdentityLocked && (\n <div className=\"adn-settings__identity\">\n <label className=\"adn-settings__field\">\n <span className=\"adn-settings__field-label\">{label('settings.key')}</span>\n <span className=\"adn-settings__hint\">{label('settings.keyHint')}</span>\n <input value={editor.draft.key} onChange={(event) => editor.update({ key: event.target.value })} />\n </label>\n\n {/* Multipla escolha, e nao `select`: o mesmo aviso costuma sair por mais de um\n canal, e escolher um de cada vez obrigaria a reescrever o texto. */}\n <fieldset className=\"adn-settings__field adn-settings__field--channels\">\n <legend className=\"adn-settings__field-label\">{label('settings.channel')}</legend>\n <span className=\"adn-settings__hint\">{label('settings.channelHint')}</span>\n <div className=\"adn-settings__channel-picker\">\n {channels.map((channel) => (\n <label key={channel.id} className=\"adn-settings__channel-chip\">\n <input\n type=\"checkbox\"\n checked={editor.draft?.channels.includes(channel.id) ?? false}\n onChange={() => {\n editor.toggleChannel(channel.id)\n /* Marcar um canal abre a aba dele: senao a pessoa marca e nada muda na tela. */\n if (!editor.draft?.channels.includes(channel.id)) setActiveChannel(channel.id)\n }}\n />\n <span>{channel.label}</span>\n </label>\n ))}\n </div>\n </fieldset>\n\n <label className=\"adn-settings__field\">\n <span className=\"adn-settings__field-label\">{label('settings.locale')}</span>\n <input\n value={editor.draft.locale}\n onChange={(event) => editor.update({ locale: event.target.value })}\n />\n </label>\n </div>\n )}\n\n {editor.variables.length > 0 && (\n <div className=\"adn-settings__variables\">\n <p className=\"adn-settings__field-label\">{label('settings.variablesTitle')}</p>\n <p className=\"adn-settings__hint\">{label('settings.variablesHint')}</p>\n <ul>\n {editor.variables.map((variable) => {\n const used = editor.variableDiff.used.includes(variable.name)\n const missing = editor.variableDiff.missingRequired.includes(variable.name)\n return (\n <li key={variable.name}>\n <button\n type=\"button\"\n className={[\n 'adn-settings__variable',\n used ? 'adn-settings__variable--used' : '',\n missing ? 'adn-settings__variable--missing' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n onClick={() =>\n editor.insertVariable({\n ...cursor,\n name: variable.name,\n channel: cursorChannel ?? editor.draft?.channels[0] ?? '',\n })\n }\n >\n <span className=\"adn-settings__variable-name\">{`{{${variable.name}}}`}</span>\n <span className=\"adn-settings__hint\">{variable.example}</span>\n </button>\n </li>\n )\n })}\n </ul>\n </div>\n )}\n\n {editor.variableDiff.unknown.length > 0 && (\n <p className=\"adn-settings__error\">\n {label('settings.unknownVariables')} {editor.variableDiff.unknown.join(', ')}\n </p>\n )}\n\n {/**\n * Um bloco por canal: texto, campos do canal e o preview dele, juntos.\n *\n * Os canais nao sao o mesmo recado em molduras diferentes — o WhatsApp ignora o\n * assunto, o SMS cobra por segmento e encurta. Com um editor so, escrever para o\n * pior canal e mandar isso a todos era a unica saida.\n */}\n {/**\n * Abas por canal, e nao blocos empilhados.\n *\n * Com tres canais marcados, empilhado obriga a rolar por tres aparelhos do e-mail\n * para chegar ao WhatsApp. A aba mantem o preview grande e o trabalho focado num\n * canal por vez — e a comparacao que importa (entre APARELHOS) continua lado a lado\n * dentro da aba.\n *\n * O ponto no rotulo e o que impede o efeito colateral: canal sem texto, ou com\n * variavel desconhecida, bloqueia o salvar — e escondido atras de uma aba fechada,\n * bloquearia sem explicar. */}\n <div className=\"adn-settings__channel-tabs\" role=\"tablist\">\n {channels\n .filter((channel) => editor.draft?.channels.includes(channel.id))\n .map((channel) => {\n const vazio = (editor.draft?.byChannel[channel.id]?.body ?? '').length === 0\n const ativo = (activeChannel ?? editor.draft?.channels[0]) === channel.id\n\n return (\n <button\n key={channel.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={ativo}\n className={ativo ? 'adn-settings__tab adn-settings__tab--active' : 'adn-settings__tab'}\n onClick={() => setActiveChannel(channel.id)}\n >\n {channel.label}\n {vazio && <span className=\"adn-settings__tab-dot\" aria-hidden=\"true\" />}\n </button>\n )\n })}\n </div>\n\n {channels\n .filter((channel) => editor.draft?.channels.includes(channel.id))\n .filter((channel) => (activeChannel ?? editor.draft?.channels[0]) === channel.id)\n .map((channel) => {\n const content = editor.draft?.byChannel[channel.id]\n const frames = editor.previews.filter((frame) => frame.channel === channel.id)\n\n return (\n <section key={channel.id} className=\"adn-settings__channel-block\">\n <header className=\"adn-settings__channel-block-header\">\n <h3 className=\"adn-settings__preview-channel\">{channel.label}</h3>\n {channel.hint && <span className=\"adn-settings__hint\">{channel.hint}</span>}\n </header>\n\n {editor.isStandardEmail ? (\n <p className=\"adn-settings__hint\">{label('settings.standardEmailHint')}</p>\n ) : (\n <label className=\"adn-settings__field\">\n <span className=\"adn-settings__field-label\">{label('settings.subject')}</span>\n <span className=\"adn-settings__hint\">{label('settings.subjectHint')}</span>\n <input\n value={content?.subject ?? ''}\n onChange={(event) => editor.updateChannel(channel.id, { subject: event.target.value })}\n onSelect={(event) => rememberCursor('subject', event.currentTarget.selectionStart)}\n onFocus={() => setCursorChannel(channel.id)}\n />\n </label>\n )}\n\n <label className=\"adn-settings__field\">\n <span className=\"adn-settings__field-label\">{label('settings.body')}</span>\n {/* Editor de codigo so onde HTML significa alguma coisa. WhatsApp, SMS e push\n recebem texto puro — realce ali sugeriria uma marcacao que o canal nao\n entende, e a sugestao vira erro na entrega. */}\n {channel.id === 'email' && isHtmlBody(content?.body ?? '') ? (\n <HtmlCodeField\n value={content?.body ?? ''}\n onChange={(next) => editor.updateChannel(channel.id, { body: next })}\n onSelect={(cursorIndex) => rememberCursor('body', cursorIndex)}\n onFocus={() => setCursorChannel(channel.id)}\n {...(validateEmailHtml && !editor.isStandardEmail\n ? { problems: validateEmailHtml(content?.body ?? '').problems }\n : {})}\n />\n ) : (\n <MessageBodyField\n value={content?.body ?? ''}\n onChange={(next) => editor.updateChannel(channel.id, { body: next })}\n onSelect={(cursorIndex) => rememberCursor('body', cursorIndex)}\n onFocus={() => setCursorChannel(channel.id)}\n labelOf={label}\n />\n )}\n </label>\n\n {/* O modelo padrão se valida inteiro, pelo mesmo `assess` do servidor: as obrigatórias\n e o HTML inseguro, sem depender de a área de mensagem existir. */}\n {editor.isStandardEmail && editor.standardAssessment && !editor.standardAssessment.usable && (\n <ul className=\"adn-settings__email-report\" role=\"alert\">\n {editor.standardAssessment.missing.length > 0 && (\n <li className=\"adn-settings__email-problem adn-settings__email-problem--error\">\n {label('settings.standardMissing')}{' '}\n {editor.standardAssessment.missing.map((name) => `{{${name}}}`).join(', ')}\n </li>\n )}\n {editor.standardAssessment.unsafe.length > 0 && (\n <li className=\"adn-settings__email-problem adn-settings__email-problem--error\">\n {label('settings.standardUnsafe')}{' '}\n {editor.standardAssessment.unsafe\n .map((rule) => label(`settings.standardUnsafe.${rule}`))\n .join(', ')}\n </li>\n )}\n </ul>\n )}\n\n {/* Slot do host: campo que só um canal tem, e que o pacote não conhece por nome. */}\n {renderChannelFields?.({\n channel: channel.id,\n value: content?.whatsappTemplateName ?? '',\n onChange: (value) => editor.updateChannel(channel.id, { whatsappTemplateName: value }),\n })}\n\n {frames.length > 0 && (\n <div className=\"adn-settings__previews\">\n <p className=\"adn-settings__preview-title\">{label('settings.previewTitle')}</p>\n <div className=\"adn-settings__preview-frames\">\n {frames.map((frame) => (\n <figure key={`${frame.channel}:${frame.viewport}`} className=\"adn-settings__preview\">\n <figcaption className=\"adn-settings__hint\">\n {label(`settings.viewport.${frame.viewport}`)} · {frame.width}px\n </figcaption>\n <div\n className=\"adn-settings__preview-frame\"\n style={{ '--adn-preview-width': `${frame.width}px` } as CSSProperties}\n >\n {/* O HTML do preview e o QUE ESTA NO CAMPO, nao uma moldura que o\n painel enfia por fora: se a pessoa escreveu HTML, e o HTML\n dela que precisa aparecer. Corpo sem marcacao segue texto. */}\n <TemplatePreview\n channel={frame.channel}\n viewport={frame.viewport}\n rendered={frame.rendered}\n {...(frame.channel === 'email' && editor.standardPreviewHtml !== undefined\n ? { emailHtml: editor.standardPreviewHtml }\n : frame.channel === 'email' &&\n !editor.isStandardEmail &&\n isHtmlBody(content?.body ?? '')\n ? { emailHtml: content?.body ?? '' }\n : {})}\n labels={{\n to: label('preview.to'),\n now: label('preview.now'),\n mailbox: label('preview.mailbox'),\n time: label('preview.time'),\n address: label('preview.address'),\n counter: label('preview.counter'),\n folder: label('preview.folder'),\n senderAddress: label('preview.senderAddress'),\n unsubscribe: label('preview.unsubscribe'),\n online: label('preview.online'),\n today: label('preview.today'),\n compose: label('preview.compose'),\n reply: label('preview.reply'),\n forward: label('preview.forward'),\n replyAll: label('preview.replyAll'),\n }}\n {...(senderName ? { senderName } : {})}\n />\n </div>\n {frame.rendered.constraints\n .filter((constraint) => constraint.exceeded)\n .map((constraint) => (\n <p key={constraint.field} className=\"adn-settings__preview-warning\">\n {label(`settings.constraint.${constraint.field}`)} {constraint.actual}/\n {constraint.limit}\n </p>\n ))}\n </figure>\n ))}\n </div>\n </div>\n )}\n </section>\n )\n })}\n\n {editor.error && <p className=\"adn-settings__error\">{editor.error}</p>}\n\n <div className=\"adn-settings__actions\">\n <button type=\"button\" onClick={editor.save} disabled={!editor.isDirty || !editor.canSave || editor.isSaving}>\n {editor.isSaving ? label('settings.saving') : label('settings.save')}\n </button>\n {/* Diz por que está desabilitado, em vez de deixar o botão inerte sem explicação. */}\n {!editor.isDirty && <span className=\"adn-settings__hint\">{label('settings.unchanged')}</span>}\n </div>\n </>\n )}\n </section>\n )}\n </div>\n )}\n </div>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * Campo de código com realce, numeração de linha e laudo do linter.\n *\n * Técnica de sobreposição, e não um editor de verdade: um `<pre>` colorido embaixo e o `<textarea>`\n * transparente em cima, com a MESMA métrica de texto e a rolagem sincronizada. Custa alinhamento\n * milimétrico, e paga não trazendo um CodeMirror (~200KB) para dentro de um pacote de UI que hoje\n * pesa duas dependências — e não perdendo nada do `<textarea>`: seleção, desfazer, corretor,\n * leitor de tela e o cursor que o editor usa para inserir variável continuam nativos.\n */\n\nimport { useRef } from 'react'\nimport type { UIEvent } from 'react'\n\nimport { tokenizeHtml } from '../htmlHighlight.util'\n\nexport type HtmlCodeFieldProblem = {\n readonly code: string\n readonly severity: string\n readonly message: string\n}\n\nexport type HtmlCodeFieldProps = {\n readonly value: string\n readonly rows?: number\n readonly onChange: (value: string) => void\n readonly onSelect?: (cursorIndex: number) => void\n readonly onFocus?: () => void\n /** Ausente, nenhum laudo aparece — o campo vira só realce. */\n readonly problems?: readonly HtmlCodeFieldProblem[]\n}\n\nexport function HtmlCodeField({ value, rows = 12, onChange, onSelect, onFocus, problems }: HtmlCodeFieldProps) {\n const highlightRef = useRef<HTMLPreElement>(null)\n\n /**\n * O `<pre>` não rola sozinho: ele segue o `<textarea>`. Sem isto, o realce descola do texto no\n * primeiro documento que passa da altura do campo — que é todo documento de e-mail.\n */\n function handleScroll(event: UIEvent<HTMLTextAreaElement>): void {\n const pre = highlightRef.current\n if (!pre) return\n pre.scrollTop = event.currentTarget.scrollTop\n pre.scrollLeft = event.currentTarget.scrollLeft\n }\n\n const lineCount = value.split('\\n').length\n\n return (\n <div className=\"adn-code\">\n <div className=\"adn-code__editor\">\n <div className=\"adn-code__gutter\" aria-hidden=\"true\">\n {Array.from({ length: lineCount }, (_, index) => (\n <span key={index}>{index + 1}</span>\n ))}\n </div>\n\n <div className=\"adn-code__surface\">\n {/* Decorativo: o texto de verdade está no `<textarea>` em cima, e é ele que o leitor de\n tela lê. Anunciar os dois faria o conteúdo aparecer duplicado. */}\n <pre ref={highlightRef} className=\"adn-code__highlight\" aria-hidden=\"true\">\n {tokenizeHtml(value).map((token, index) => (\n <span key={index} className={`adn-code__token adn-code__token--${token.kind}`}>\n {token.text}\n </span>\n ))}\n {/* Linha vazia final: sem ela o realce não acompanha o cursor na última quebra. */}\n {'\\n'}\n </pre>\n\n <textarea\n className=\"adn-code__input\"\n spellCheck={false}\n rows={rows}\n value={value}\n onChange={(event) => onChange(event.target.value)}\n onScroll={handleScroll}\n onSelect={(event) => onSelect?.(event.currentTarget.selectionStart)}\n onFocus={onFocus}\n />\n </div>\n </div>\n\n {problems && problems.length > 0 && (\n <ul className=\"adn-settings__email-report\">\n {problems.map((problem) => (\n <li\n key={problem.code}\n className={`adn-settings__email-problem adn-settings__email-problem--${problem.severity}`}\n >\n {problem.message}\n </li>\n ))}\n </ul>\n )}\n </div>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * Realce de HTML como DADOS, nunca como string de markup.\n *\n * A tentação aqui é montar `<span class=...>` numa string e jogar em `dangerouslySetInnerHTML` —\n * é o caminho mais curto e é como quase toda biblioteca de realce faz. Num editor esse caminho\n * passa por cima do texto que a pessoa acabou de digitar: o realce vira o vetor de injeção do\n * próprio conteúdo que ele deveria só colorir. Devolver tokens deixa o React criar nó de texto, e\n * a questão simplesmente não existe.\n */\n\nexport const HTML_TOKEN = {\n TAG: 'tag',\n NAME: 'name',\n ATTRIBUTE: 'attribute',\n VALUE: 'value',\n COMMENT: 'comment',\n DOCTYPE: 'doctype',\n VARIABLE: 'variable',\n TEXT: 'text',\n} as const\nexport type HtmlTokenKind = (typeof HTML_TOKEN)[keyof typeof HTML_TOKEN]\n\nexport type HtmlToken = {\n readonly kind: HtmlTokenKind\n readonly text: string\n}\n\n/**\n * Um scanner, não um parser: ele não monta árvore nem valida aninhamento — quem reclama de tag\n * desbalanceada é o `validateEmailHtml`. Aqui só interessa onde começa e termina cada pedaço, e\n * um scanner erra de forma inofensiva (colore de menos), enquanto um parser meia-boca erra\n * escondendo texto.\n */\nconst SCANNER =\n /(<!--[\\s\\S]*?-->)|(<!doctype[^>]*>)|(<\\/?)([a-zA-Z][\\w:-]*)((?:[^>\"']|\"[^\"]*\"|'[^']*')*?)(\\/?>)|(\\{\\{\\s*[\\w.]+\\s*\\}\\})/gi\n\nexport function tokenizeHtml(source: string): readonly HtmlToken[] {\n const tokens: HtmlToken[] = []\n let cursor = 0\n\n for (const match of source.matchAll(SCANNER)) {\n const start = match.index\n if (start > cursor) push(tokens, HTML_TOKEN.TEXT, source.slice(cursor, start))\n\n const [whole, comment, doctype, open, name, attributes, close, variable] = match\n\n if (comment) push(tokens, HTML_TOKEN.COMMENT, comment)\n else if (doctype) push(tokens, HTML_TOKEN.DOCTYPE, doctype)\n else if (variable) push(tokens, HTML_TOKEN.VARIABLE, variable)\n else if (name) {\n push(tokens, HTML_TOKEN.TAG, open ?? '<')\n push(tokens, HTML_TOKEN.NAME, name)\n tokens.push(...tokenizeAttributes(attributes ?? ''))\n push(tokens, HTML_TOKEN.TAG, close ?? '>')\n }\n\n cursor = start + whole.length\n }\n\n if (cursor < source.length) push(tokens, HTML_TOKEN.TEXT, source.slice(cursor))\n return tokens\n}\n\nconst ATTRIBUTE_SCANNER = /([\\w:@.-]+)(\\s*=\\s*)(\"[^\"]*\"|'[^']*'|[^\\s>]+)?/g\n\nfunction tokenizeAttributes(source: string): readonly HtmlToken[] {\n const tokens: HtmlToken[] = []\n let cursor = 0\n\n for (const match of source.matchAll(ATTRIBUTE_SCANNER)) {\n const start = match.index\n if (start > cursor) push(tokens, HTML_TOKEN.TEXT, source.slice(cursor, start))\n\n const [whole, attribute, equals, value] = match\n push(tokens, HTML_TOKEN.ATTRIBUTE, attribute ?? '')\n push(tokens, HTML_TOKEN.TEXT, equals ?? '')\n push(tokens, HTML_TOKEN.VALUE, value ?? '')\n\n cursor = start + whole.length\n }\n\n if (cursor < source.length) push(tokens, HTML_TOKEN.TEXT, source.slice(cursor))\n return tokens\n}\n\nfunction push(tokens: HtmlToken[], kind: HtmlTokenKind, text: string): void {\n if (text) tokens.push({ kind, text })\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * A caixa de mensagem com barra de formatação.\n *\n * A seleção é assunto do DOM, e por isso ela mora aqui e não no `useTemplateEditor`: o hook guarda\n * o rascunho, este componente guarda onde o cursor está. Depois de cada botão a seleção é\n * reposicionada à mão — sem isso o cursor pula para o fim do texto a cada clique, e quem estava\n * corrigindo o meio de uma frase perde o lugar.\n */\n\nimport { useLayoutEffect, useRef, useState } from 'react'\n\nimport { applyMark, insertAt } from '../messageFormat.util'\nimport { MessageToolbar } from './MessageToolbar'\n\nexport type MessageBodyFieldProps = {\n readonly value: string\n readonly rows?: number\n readonly onChange: (value: string) => void\n readonly onSelect?: (cursorIndex: number) => void\n readonly onFocus?: () => void\n readonly labelOf: (key: string) => string\n}\n\nexport function MessageBodyField({ value, rows = 5, onChange, onSelect, onFocus, labelOf }: MessageBodyFieldProps) {\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n const [pendingSelection, setPendingSelection] = useState<readonly [number, number]>()\n\n /**\n * `useLayoutEffect` e não `useEffect`: a seleção precisa ser reposta ANTES da pintura, senão o\n * cursor aparece por um quadro no lugar errado — e num campo de texto esse piscar é visível.\n */\n useLayoutEffect(() => {\n if (!pendingSelection) return\n const textarea = textareaRef.current\n if (!textarea) return\n\n textarea.focus()\n textarea.setSelectionRange(pendingSelection[0], pendingSelection[1])\n setPendingSelection(undefined)\n }, [pendingSelection])\n\n function currentRange(): readonly [number, number] {\n const textarea = textareaRef.current\n if (!textarea) return [value.length, value.length]\n return [textarea.selectionStart, textarea.selectionEnd]\n }\n\n function handleMark(delimiter: string): void {\n const [selectionStart, selectionEnd] = currentRange()\n const result = applyMark({ text: value, delimiter, selectionStart, selectionEnd })\n\n onChange(result.text)\n setPendingSelection([result.selectionStart, result.selectionEnd])\n }\n\n function handleInsert(insertion: string): void {\n const [selectionStart, selectionEnd] = currentRange()\n const result = insertAt({ text: value, insertion, selectionStart, selectionEnd })\n\n onChange(result.text)\n setPendingSelection([result.selectionStart, result.selectionEnd])\n }\n\n return (\n <div className=\"adn-message-field\">\n <MessageToolbar onMark={handleMark} onInsert={handleInsert} labelOf={labelOf} />\n <textarea\n ref={textareaRef}\n rows={rows}\n value={value}\n onChange={(event) => onChange(event.target.value)}\n onSelect={(event) => onSelect?.(event.currentTarget.selectionStart)}\n onFocus={onFocus}\n />\n </div>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n */\n\nexport type ApplyMarkParams = {\n readonly text: string\n readonly delimiter: string\n readonly selectionStart: number\n readonly selectionEnd: number\n}\n\nexport type ApplyMarkResult = {\n readonly text: string\n /** Onde o cursor precisa ficar depois — sem isto, ele volta para o começo a cada clique. */\n readonly selectionStart: number\n readonly selectionEnd: number\n}\n\n/**\n * Envolve a seleção com o delimitador — ou DESFAZ, se ela já estiver envolvida.\n *\n * O botão alterna, e não acumula: clicar duas vezes em negrito com o mesmo trecho selecionado\n * devolve o texto original. Sem isso, `**texto**` vira literal na conversa, porque a convenção do\n * WhatsApp não aninha — o segundo par cancela o primeiro e o cliente mostra os asteriscos.\n *\n * Seleção vazia insere o par e põe o cursor no meio: é o comportamento de quem clica em negrito\n * ANTES de escrever, que é metade das vezes.\n */\nexport function applyMark({ text, delimiter, selectionStart, selectionEnd }: ApplyMarkParams): ApplyMarkResult {\n const start = clamp(selectionStart, text.length)\n const end = clamp(Math.max(selectionEnd, selectionStart), text.length)\n\n const selected = text.slice(start, end)\n const size = delimiter.length\n\n const wrappedInside = selected.startsWith(delimiter) && selected.endsWith(delimiter) && selected.length > size * 2\n if (wrappedInside) {\n const bare = selected.slice(size, -size)\n return {\n text: `${text.slice(0, start)}${bare}${text.slice(end)}`,\n selectionStart: start,\n selectionEnd: start + bare.length,\n }\n }\n\n const wrappedOutside = text.slice(start - size, start) === delimiter && text.slice(end, end + size) === delimiter\n if (wrappedOutside) {\n return {\n text: `${text.slice(0, start - size)}${selected}${text.slice(end + size)}`,\n selectionStart: start - size,\n selectionEnd: start - size + selected.length,\n }\n }\n\n return {\n text: `${text.slice(0, start)}${delimiter}${selected}${delimiter}${text.slice(end)}`,\n selectionStart: start + size,\n selectionEnd: start + size + selected.length,\n }\n}\n\n/** Insere no cursor, substituindo o que estiver selecionado — o que todo campo de texto faz. */\nexport function insertAt({\n text,\n insertion,\n selectionStart,\n selectionEnd,\n}: {\n readonly text: string\n readonly insertion: string\n readonly selectionStart: number\n readonly selectionEnd: number\n}): ApplyMarkResult {\n const start = clamp(selectionStart, text.length)\n const end = clamp(Math.max(selectionEnd, selectionStart), text.length)\n const next = start + insertion.length\n\n return {\n text: `${text.slice(0, start)}${insertion}${text.slice(end)}`,\n selectionStart: next,\n selectionEnd: next,\n }\n}\n\nfunction clamp(value: number, max: number): number {\n return Math.min(Math.max(value, 0), max)\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * A barra da caixa de mensagem: negrito, itálico, tachado, monoespaçado e emoji.\n *\n * Ela escreve MARCAÇÃO no texto, não HTML. A convenção é a do WhatsApp (`conversation-flow.md` §4)\n * e vale para todos os canais — quem escreve o fluxo escreve uma vez, e o canal que não a entende\n * nativamente traduz na renderização. Um editor rico que cuspisse `<b>` obrigaria o mesmo texto a\n * existir duas vezes, e a segunda cópia sempre atrasa em relação à primeira.\n */\n\nimport { Bold, Code, Italic, Smile, Strikethrough } from 'lucide-react'\nimport { useState } from 'react'\nimport type { ReactNode } from 'react'\n\nimport { MESSAGE_EMOJI, MESSAGE_FORMAT, MESSAGE_FORMAT_MARKS } from '../messageFormat.constant'\nimport type { MessageFormat } from '../messageFormat.constant'\n\nexport type MessageToolbarProps = {\n /** Aplica o delimitador na seleção corrente do campo. */\n readonly onMark: (delimiter: string) => void\n readonly onInsert: (text: string) => void\n /** Rótulos acessíveis, por formato. Nada aqui é literal (web.md §6). */\n readonly labelOf: (key: string) => string\n}\n\nconst FORMAT_ICON: Readonly<Record<MessageFormat, ReactNode>> = {\n [MESSAGE_FORMAT.BOLD]: <Bold aria-hidden=\"true\" className=\"adn-settings__button-icon\" />,\n [MESSAGE_FORMAT.ITALIC]: <Italic aria-hidden=\"true\" className=\"adn-settings__button-icon\" />,\n [MESSAGE_FORMAT.STRIKETHROUGH]: <Strikethrough aria-hidden=\"true\" className=\"adn-settings__button-icon\" />,\n [MESSAGE_FORMAT.MONOSPACE]: <Code aria-hidden=\"true\" className=\"adn-settings__button-icon\" />,\n}\n\nexport function MessageToolbar({ onMark, onInsert, labelOf }: MessageToolbarProps) {\n const [isEmojiOpen, setIsEmojiOpen] = useState(false)\n\n return (\n <div className=\"adn-toolbar\">\n {MESSAGE_FORMAT_MARKS.map(({ format, delimiter }) => (\n <button\n key={format}\n type=\"button\"\n className=\"adn-toolbar__button\"\n title={labelOf(`toolbar.${format}`)}\n aria-label={labelOf(`toolbar.${format}`)}\n /**\n * `onMouseDown` e não `onClick`: clicar tira o foco do campo, e com ele a seleção que a\n * barra precisa envolver. Prevenir o padrão mantém o cursor onde estava.\n */\n onMouseDown={(event) => {\n event.preventDefault()\n onMark(delimiter)\n }}\n >\n {FORMAT_ICON[format]}\n </button>\n ))}\n\n <span className=\"adn-toolbar__divider\" aria-hidden=\"true\" />\n\n <div className=\"adn-toolbar__emoji\">\n <button\n type=\"button\"\n className=\"adn-toolbar__button\"\n title={labelOf('toolbar.emoji')}\n aria-label={labelOf('toolbar.emoji')}\n aria-expanded={isEmojiOpen}\n onMouseDown={(event) => {\n event.preventDefault()\n setIsEmojiOpen((current) => !current)\n }}\n >\n <Smile aria-hidden=\"true\" className=\"adn-settings__button-icon\" />\n </button>\n\n {isEmojiOpen && (\n <div className=\"adn-toolbar__palette\" role=\"group\" aria-label={labelOf('toolbar.emoji')}>\n {MESSAGE_EMOJI.map((emoji) => (\n <button\n key={emoji}\n type=\"button\"\n className=\"adn-toolbar__emoji-button\"\n onMouseDown={(event) => {\n event.preventDefault()\n onInsert(emoji)\n setIsEmojiOpen(false)\n }}\n >\n {emoji}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n )\n}\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * Formatação e emoji da caixa de mensagem.\n *\n * A marcação é a do WhatsApp — `*negrito*`, `_itálico_` — e ela é ÚNICA para todos os canais\n * (`conversation-flow.md` §4): quem escreve o fluxo escreve uma vez, e o canal que não entende a\n * convenção nativamente traduz na renderização. Um editor rico que cuspisse `<b>` obrigaria o texto\n * a existir duas vezes, e a segunda sempre atrasa em relação à primeira.\n *\n * Os delimitadores são simétricos de propósito: envolver a seleção e desfazer o envolvimento é a\n * mesma operação com o mesmo par, e é isso que deixa o botão alternar em vez de acumular asterisco.\n */\n\nexport const MESSAGE_FORMAT = {\n BOLD: 'bold',\n ITALIC: 'italic',\n STRIKETHROUGH: 'strikethrough',\n MONOSPACE: 'monospace',\n} as const\nexport type MessageFormat = (typeof MESSAGE_FORMAT)[keyof typeof MESSAGE_FORMAT]\n\nexport type MessageFormatMark = {\n readonly format: MessageFormat\n readonly delimiter: string\n}\n\nexport const MESSAGE_FORMAT_MARKS: readonly MessageFormatMark[] = [\n { format: MESSAGE_FORMAT.BOLD, delimiter: '*' },\n { format: MESSAGE_FORMAT.ITALIC, delimiter: '_' },\n { format: MESSAGE_FORMAT.STRIKETHROUGH, delimiter: '~' },\n { format: MESSAGE_FORMAT.MONOSPACE, delimiter: '```' },\n]\n\n/**\n * Paleta curada, e não um seletor com todos os emoji do Unicode.\n *\n * O mesmo emoji precisa significar a mesma coisa em todo o produto (`conversation-flow.md` §3), e\n * uma grade infinita garante o contrário: cada pessoa escolhe um símbolo diferente para \"confirmar\".\n * Vinte e quatro cobrem aviso, dinheiro, prazo e atendimento — o que estes produtos realmente dizem.\n */\nexport const MESSAGE_EMOJI: readonly string[] = [\n '✅',\n '❌',\n '⚠️',\n 'ℹ️',\n '📅',\n '⏰',\n '⏳',\n '🔔',\n '💬',\n '📞',\n '📧',\n '🙋',\n '💰',\n '💳',\n '🧾',\n '📊',\n '📦',\n '🚚',\n '📍',\n '🔗',\n '🙂',\n '🎉',\n '🙏',\n '👋',\n]\n","/**\n * Copyright (c) 2026 Ada Technology. MIT License.\n *\n * O preview com a moldura do canal, e não uma caixa branca igual para todos.\n *\n * Duas caixas idênticas rotuladas \"600px\" e \"375px\" não respondem a pergunta que alguém tem ao\n * escrever a mensagem: *como isso chega?* Um e-mail chega numa caixa de entrada, com remetente e\n * assunto acima do texto; um WhatsApp chega como balão sobre o papel de parede da conversa; um SMS\n * chega sem assunto nenhum, contado em segmentos de 160; um push chega como cartão na tela\n * bloqueada, cortado em duas linhas. O corte e o enquadramento SÃO a informação — sem eles o\n * preview só prova que o texto existe.\n *\n * Nada aqui usa `dangerouslySetInnerHTML`: o corpo entra como nó de texto, mesmo já escapado pelo\n * renderer do `notification-contracts`. Quando o produto injeta a moldura de e-mail (`emailHtml`),\n * o documento vai para um `<iframe sandbox srcDoc>` — nunca para o DOM do painel. O sandbox vazio\n * corta script e mesma-origem, e de quebra isola o CSS do e-mail do CSS da tela.\n */\n\nimport type { RenderedTemplatePreview } from '@adatechnology/notification-contracts'\n\nimport { parseWhatsAppFormatting } from '@adatechnology/conversations-ui'\n\nexport type TemplatePreviewProps = {\n readonly channel: string\n readonly viewport: string\n readonly rendered: RenderedTemplatePreview\n /**\n * O documento de e-mail COMPLETO, já com a moldura da marca em volta do corpo. Vem do produto:\n * o pacote não conhece logo, cartão de usuário nem rodapé. Ausente, o corpo aparece como texto.\n */\n readonly emailHtml?: string\n /** Nome do produto, para o cabeçalho do e-mail e o do push. O pacote não sabe de quem é a marca. */\n readonly senderName?: string\n /**\n * Arquivo que segue com a mensagem (ex.: o PDF do boleto). Aparece como cartão de documento no\n * balão do WhatsApp e como chip no fim do e-mail. O nome e o tamanho vêm do produto.\n */\n readonly attachment?: PreviewAttachment\n /** Os textos da moldura. Nada aqui é hardcoded — nem \"para você\", nem \"agora\" (web.md §6). */\n readonly labels: PreviewLabels\n}\n\nexport type PreviewAttachment = {\n readonly name: string\n /** Já formatado pelo produto (ex.: \"4,4 KB · PDF\"). Ausente, só o nome. */\n readonly detail?: string\n}\n\nexport type PreviewLabels = {\n readonly to: string\n readonly now: string\n readonly mailbox: string\n /** Hora da barra de status do aparelho. */\n readonly time: string\n readonly address: string\n readonly counter: string\n readonly folder: string\n readonly senderAddress: string\n readonly unsubscribe: string\n readonly online: string\n readonly today: string\n readonly compose: string\n readonly reply: string\n readonly forward: string\n readonly replyAll: string\n}\n\n/**\n * O aparelho. `os` muda mais que a largura: o raio da moldura, o raio dos balões e o desenho do\n * cartão de push são diferentes em cada sistema, e é por isso que os dois aparecem lado a lado.\n *\n * Sem barra de status falsa: no aparelho real ela é desenhada por cima, e a pintada fica dobrada.\n */\n/** Sinal, wi-fi e bateria da barra de status. Desenhados, nunca emoji — escalam e herdam a cor. */\nfunction StatusIcons() {\n return (\n <span className=\"adn-preview-status__icons\">\n <svg width=\"15\" height=\"10\" viewBox=\"0 0 15 10\" aria-hidden=\"true\">\n <rect x=\"0\" y=\"6\" width=\"2.5\" height=\"4\" rx=\"0.6\" fill=\"currentColor\" />\n <rect x=\"4\" y=\"4\" width=\"2.5\" height=\"6\" rx=\"0.6\" fill=\"currentColor\" />\n <rect x=\"8\" y=\"2\" width=\"2.5\" height=\"8\" rx=\"0.6\" fill=\"currentColor\" />\n <rect x=\"12\" y=\"0\" width=\"2.5\" height=\"10\" rx=\"0.6\" fill=\"currentColor\" />\n </svg>\n <svg width=\"13\" height=\"10\" viewBox=\"0 0 13 10\" aria-hidden=\"true\">\n <path d=\"M6.5 9.2 1 3.6a7.8 7.8 0 0 1 11 0Z\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.3\" />\n <circle cx=\"6.5\" cy=\"8\" r=\"1\" fill=\"currentColor\" />\n </svg>\n <svg width=\"20\" height=\"10\" viewBox=\"0 0 20 10\" aria-hidden=\"true\">\n <rect x=\"0.5\" y=\"0.5\" width=\"16\" height=\"9\" rx=\"2.5\" fill=\"none\" stroke=\"currentColor\" opacity=\"0.5\" />\n <rect x=\"2\" y=\"2\" width=\"11\" height=\"6\" rx=\"1.2\" fill=\"currentColor\" />\n <rect x=\"18\" y=\"3.5\" width=\"1.6\" height=\"3\" rx=\"0.8\" fill=\"currentColor\" opacity=\"0.5\" />\n </svg>\n </span>\n )\n}\n\n/**\n * O aparelho inteiro: moldura, barra de status, recorte da câmera e a barra de gesto embaixo.\n *\n * `os` muda mais que a largura — no iOS o recorte é a ilha central e os cantos são bem\n * arredondados; no Android é o furo à esquerda e a moldura é mais reta. É o que faz reconhecer o\n * aparelho de relance, e é onde a mesma mensagem quebra em pontos diferentes.\n */\nfunction Phone({ children, os, tone, time }: { children: React.ReactNode; os: string; tone?: 'dark'; time: string }) {\n const android = os === 'android'\n const classes = ['adn-preview-phone', `adn-preview-phone--${android ? 'android' : 'ios'}`]\n if (tone === 'dark') classes.push('adn-preview-phone--dark')\n\n return (\n <div className={classes.join(' ')}>\n {/* Botoes laterais: e o que faz a silhueta parecer um aparelho e nao um retangulo. */}\n <span className=\"adn-preview-phone__btn adn-preview-phone__btn--mute\" />\n <span className=\"adn-preview-phone__btn adn-preview-phone__btn--up\" />\n <span className=\"adn-preview-phone__btn adn-preview-phone__btn--down\" />\n <span className=\"adn-preview-phone__btn adn-preview-phone__btn--power\" />\n <div className=\"adn-preview-phone__screen\">\n <div className=\"adn-preview-status\">\n <span className=\"adn-preview-status__time\">{time}</span>\n {android ? <span className=\"adn-preview-phone__punch\" /> : <span className=\"adn-preview-phone__island\" />}\n <StatusIcons />\n </div>\n <div className=\"adn-preview-phone__content\">{children}</div>\n <div className=\"adn-preview-phone__gesture\" />\n </div>\n </div>\n )\n}\n\n/** Ícone traçado de 20px, no mesmo estilo do resto — nunca emoji (web.md §9). */\nfunction Icon({ d, size = 16 }: { d: string; size?: number }) {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.7\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d={d} />\n </svg>\n )\n}\n\nconst ICON = {\n back: 'M19 12H5M12 19l-7-7 7-7',\n archive: 'M3 8h18v12H3zM3 4h18v4H3M10 12h4',\n report: 'M12 8v5M12 16.5v.01M12 3 2 20h20Z',\n trash: 'M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6',\n unread: 'M3 5h18v14H3zM3 5l9 7 9-7',\n move: 'M3 7h6l2 2h10v10H3zM3 7V5h6l2 2',\n more: 'M12 6v.01M12 12v.01M12 18v.01',\n prev: 'M15 19l-7-7 7-7',\n next: 'M9 5l7 7-7 7',\n print: 'M6 9V3h12v6M6 18H4v-6h16v6h-2M8 14h8v7H8z',\n popout: 'M14 4h6v6M20 4l-9 9M18 14v6H4V6h6',\n star: 'm12 3 2.9 5.9 6.5.9-4.7 4.6 1.1 6.5L12 17.8 6.2 20.9l1.1-6.5L2.6 9.8l6.5-.9Z',\n reply: 'M9 17H4V7M4 7l7 7M20 17v-3a6 6 0 0 0-6-6H4',\n pencil: 'M16.5 3.5a2.1 2.1 0 0 1 3 3L8 18l-4 1 1-4Z',\n inbox: 'M3 12h5l2 3h4l2-3h5M3 12l2-7h14l2 7v7H3z',\n search: 'M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14M20 20l-3.5-3.5',\n help: 'M12 17v.01M9.5 9a2.5 2.5 0 1 1 3.5 2.3c-.6.3-1 .9-1 1.7',\n video: 'M3 7h11v10H3zM14 10l7-3v10l-7-3',\n call: 'M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a1 1 0 0 1-1 1A16 16 0 0 1 4 5a1 1 0 0 1 1-1',\n mic: 'M12 3a3 3 0 0 1 3 3v5a3 3 0 0 1-6 0V6a3 3 0 0 1 3-3M5 11a7 7 0 0 0 14 0M12 18v3',\n forward: 'M15 17h5V7M20 7l-7 7M4 17v-3a6 6 0 0 1 6-6h10',\n replyAll: 'M7 17H3V9M3 9l5 5M11 17H8V9M8 9l5 5M20 17v-3a6 6 0 0 0-6-6H8',\n chevron: 'm6 9 6 6 6-6',\n file: 'M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8zM14 3v5h5',\n settings:\n 'M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6M19 12a7 7 0 0 0-.1-1l2-1.5-2-3.4-2.3 1a7 7 0 0 0-1.7-1L14.5 3h-4l-.4 2.6a7 7 0 0 0-1.7 1l-2.3-1-2 3.4L6.1 11a7 7 0 0 0 0 2l-2 1.5 2 3.4 2.3-1a7 7 0 0 0 1.7 1l.4 2.6h4l.4-2.6a7 7 0 0 0 1.7-1l2.3 1 2-3.4-2-1.5c.1-.3.1-.7.1-1',\n} as const\n\n/**\n * A mensagem aberta num leitor de e-mail no computador.\n *\n * A anatomia é a que todo cliente compartilha — trilho de ações à esquerda, barra de ferramentas\n * da mensagem, contador de posição, assunto grande com o rótulo da pasta, e a linha do remetente\n * com endereço, horário e ações. Nenhuma marca de terceiro é reproduzida: sem logotipo, sem\n * wordmark, sem a paleta de nenhum produto.\n */\nfunction EmailDesktop({\n rendered,\n emailHtml,\n senderName,\n labels,\n attachment,\n}: {\n rendered: RenderedTemplatePreview\n emailHtml: string | undefined\n senderName: string\n labels: PreviewLabels\n attachment: PreviewAttachment | undefined\n}) {\n return (\n <div className=\"adn-preview-browser\">\n <div className=\"adn-preview-browser__bar\">\n <span className=\"adn-preview-browser__dot\" />\n <span className=\"adn-preview-browser__dot\" />\n <span className=\"adn-preview-browser__dot\" />\n <div className=\"adn-preview-browser__address\">{labels.address}</div>\n </div>\n\n <div className=\"adn-preview-mailapp\">\n <div className=\"adn-preview-mailapp__bar\">\n <span className=\"adn-preview-mailapp__menu\" aria-hidden=\"true\">\n <span />\n <span />\n <span />\n </span>\n <div className=\"adn-preview-mailapp__search\">\n <Icon d={ICON.search} size={15} />\n <span>{labels.mailbox}</span>\n </div>\n <span className=\"adn-preview-mailapp__account\">\n <Icon d={ICON.help} size={15} />\n <Icon d={ICON.settings} size={15} />\n <span className=\"adn-preview-avatar adn-preview-avatar--small\">{senderName.slice(0, 1)}</span>\n </span>\n </div>\n\n <div className=\"adn-preview-mailapp__split\">\n <nav className=\"adn-preview-mailapp__rail\" aria-hidden=\"true\">\n <span className=\"adn-preview-mailapp__compose\">\n <Icon d={ICON.pencil} size={16} />\n </span>\n <span className=\"adn-preview-mailapp__rail-item adn-preview-mailapp__rail-item--active\">\n <Icon d={ICON.inbox} size={16} />\n </span>\n <span className=\"adn-preview-mailapp__rail-item\">\n <Icon d={ICON.star} size={16} />\n </span>\n </nav>\n\n <div className=\"adn-preview-browser__viewport\">\n <div className=\"adn-preview-mailapp__toolbar\">\n <Icon d={ICON.back} />\n <span className=\"adn-preview-mailapp__divider\" />\n <Icon d={ICON.archive} />\n <Icon d={ICON.report} />\n <Icon d={ICON.trash} />\n <span className=\"adn-preview-mailapp__divider\" />\n <Icon d={ICON.unread} />\n <Icon d={ICON.move} />\n <Icon d={ICON.more} />\n <span className=\"adn-preview-mailapp__spacer\" />\n <span className=\"adn-preview-mailapp__counter\">{labels.counter}</span>\n <Icon d={ICON.prev} size={14} />\n <Icon d={ICON.next} size={14} />\n </div>\n\n <div className=\"adn-preview-mail\">\n <div className=\"adn-preview-mail__subject-row\">\n <div className=\"adn-preview-mail__subject\">{rendered.title}</div>\n <span className=\"adn-preview-mail__folder\">{labels.folder}</span>\n <span className=\"adn-preview-mail__subject-actions\">\n <Icon d={ICON.print} size={15} />\n <Icon d={ICON.popout} size={15} />\n </span>\n </div>\n\n <div className=\"adn-preview-mail__from\">\n <span className=\"adn-preview-avatar\">{senderName.slice(0, 1)}</span>\n <span className=\"adn-preview-mail__identity\">\n <span className=\"adn-preview-mail__sender-row\">\n <span className=\"adn-preview-mail__sender\">{senderName}</span>\n <span className=\"adn-preview-mail__address\">{labels.senderAddress}</span>\n <span className=\"adn-preview-mail__unsubscribe\">{labels.unsubscribe}</span>\n </span>\n <span className=\"adn-preview-mail__to\">{labels.to}</span>\n </span>\n <span className=\"adn-preview-mail__from-actions\">\n <span className=\"adn-preview-mail__time\">{labels.now}</span>\n <Icon d={ICON.star} size={15} />\n <Icon d={ICON.reply} size={15} />\n <Icon d={ICON.more} size={15} />\n </span>\n </div>\n\n <MailBody html={emailHtml} text={rendered.body} />\n {attachment ? <AttachmentCard attachment={attachment} block=\"adn-preview-attachment--mail\" /> : null}\n </div>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\n/**\n * A mensagem aberta no app de e-mail do aparelho.\n *\n * Não é a tela do navegador encolhida — a anatomia é outra: a barra de ações fica fixa no topo, o\n * assunto vem antes do remetente, a linha do remetente traz avatar grande, horário e estrela na\n * mesma altura, o destinatário fica numa linha que se expande, e as ações de resposta ficam no fim\n * da mensagem em vez de numa barra lateral.\n */\nfunction EmailMobile({\n rendered,\n emailHtml,\n senderName,\n os,\n labels,\n attachment,\n}: {\n rendered: RenderedTemplatePreview\n emailHtml: string | undefined\n senderName: string\n os: string\n labels: PreviewLabels\n attachment: PreviewAttachment | undefined\n}) {\n return (\n <Phone os={os} time={labels.time}>\n <div className=\"adn-preview-mailapp__actions\">\n <Icon d={ICON.back} size={18} />\n <span className=\"adn-preview-mailapp__spacer\" />\n <Icon d={ICON.archive} size={18} />\n <Icon d={ICON.trash} size={18} />\n <Icon d={ICON.unread} size={18} />\n <Icon d={ICON.more} size={18} />\n </div>\n\n <div className=\"adn-preview-mailapp__scroll\">\n <div className=\"adn-preview-mail adn-preview-mail--compact\">\n <div className=\"adn-preview-mail__subject-row\">\n <div className=\"adn-preview-mail__subject\">{rendered.title}</div>\n </div>\n <span className=\"adn-preview-mail__folder\">{labels.folder}</span>\n\n <div className=\"adn-preview-mail__from adn-preview-mail__from--mobile\">\n <span className=\"adn-preview-avatar adn-preview-avatar--large\">{senderName.slice(0, 1)}</span>\n <span className=\"adn-preview-mail__identity\">\n <span className=\"adn-preview-mail__sender-row\">\n <span className=\"adn-preview-mail__sender\">{senderName}</span>\n <span className=\"adn-preview-mail__time\">{labels.now}</span>\n </span>\n {/* Linha do destinatário que expande — é assim que o app esconde os detalhes. */}\n <span className=\"adn-preview-mail__recipients\">\n {labels.to}\n <Icon d={ICON.chevron} size={12} />\n </span>\n </span>\n <span className=\"adn-preview-mail__from-actions\">\n <Icon d={ICON.star} size={17} />\n </span>\n </div>\n\n <MailBody html={emailHtml} text={rendered.body} />\n {attachment ? <AttachmentCard attachment={attachment} block=\"adn-preview-attachment--mail\" /> : null}\n\n <div className=\"adn-preview-mail__reply\">\n <span className=\"adn-preview-mail__reply-button\">\n <Icon d={ICON.reply} size={14} />\n {labels.reply}\n </span>\n <span className=\"adn-preview-mail__reply-button\">\n <Icon d={ICON.replyAll} size={14} />\n {labels.replyAll}\n </span>\n <span className=\"adn-preview-mail__reply-button\">\n <Icon d={ICON.forward} size={14} />\n {labels.forward}\n </span>\n </div>\n </div>\n </div>\n </Phone>\n )\n}\n\n/**\n * A tela da conversa, e não um balão solto.\n *\n * O balão sozinho não diz como a mensagem chega: quem escreve precisa ver o cabeçalho com o\n * remetente, o balão recebido com a ponta à esquerda sobre o papel de parede, e a barra de digitar\n * embaixo — é isso que enquadra o texto no tamanho real que ele ocupa na conversa.\n */\nfunction WhatsAppPreview({\n rendered,\n labels,\n os,\n senderName,\n attachment,\n}: {\n rendered: RenderedTemplatePreview\n labels: PreviewLabels\n os: string\n senderName: string\n attachment: PreviewAttachment | undefined\n}) {\n return (\n <Phone os={os} time={labels.time}>\n <div className=\"adn-preview-wa__header\">\n <Icon d={ICON.back} size={18} />\n <span className=\"adn-preview-wa__avatar\">{senderName.slice(0, 1)}</span>\n <span className=\"adn-preview-wa__contact\">\n <span className=\"adn-preview-wa__name\">{senderName}</span>\n <span className=\"adn-preview-wa__status\">{labels.online}</span>\n </span>\n <span className=\"adn-preview-wa__header-actions\">\n <Icon d={ICON.video} size={17} />\n <Icon d={ICON.call} size={17} />\n <Icon d={ICON.more} size={17} />\n </span>\n </div>\n\n <div className=\"adn-preview-wa\">\n <div className=\"adn-preview-wa__day\">{labels.today}</div>\n <div className=\"adn-preview-wa__bubble\">\n {attachment ? <AttachmentCard attachment={attachment} block=\"adn-preview-attachment--wa\" /> : null}\n <div className=\"adn-preview-wa__text\">{parseWhatsAppFormatting(rendered.body)}</div>\n <div className=\"adn-preview-wa__time\">{labels.now}</div>\n </div>\n </div>\n\n <div className=\"adn-preview-wa__composer\">\n <span className=\"adn-preview-wa__input\">{labels.compose}</span>\n <span className=\"adn-preview-wa__send\">\n <Icon d={ICON.mic} size={16} />\n </span>\n </div>\n </Phone>\n )\n}\n\nfunction SmsPreview({\n rendered,\n os,\n labels,\n}: {\n rendered: RenderedTemplatePreview\n os: string\n labels: PreviewLabels\n}) {\n return (\n <Phone os={os} time={labels.time}>\n <div className=\"adn-preview-sms\">\n <div className=\"adn-preview-sms__bubble\">{rendered.body}</div>\n </div>\n </Phone>\n )\n}\n\n/** Tela bloqueada: título e corpo cortados, que é onde o limite do canal aparece de verdade. */\nfunction PushPreview({\n rendered,\n senderName,\n labels,\n os,\n}: {\n rendered: RenderedTemplatePreview\n senderName: string\n labels: PreviewLabels\n os: string\n}) {\n return (\n <Phone os={os} tone=\"dark\" time={labels.time}>\n <div className=\"adn-preview-push\">\n <div className=\"adn-preview-push__card\">\n <div className=\"adn-preview-push__app\">\n <span className=\"adn-preview-avatar adn-preview-avatar--small\">{senderName.slice(0, 1)}</span>\n <span>{senderName}</span>\n <span className=\"adn-preview-push__time\">{labels.now}</span>\n </div>\n <div className=\"adn-preview-push__title\">{rendered.title}</div>\n <div className=\"adn-preview-push__body\">{rendered.body}</div>\n </div>\n </div>\n </Phone>\n )\n}\n\n/** O aviso dentro do próprio produto — o cartão da lista de notificações. */\nfunction InboxPreview({ rendered }: { rendered: RenderedTemplatePreview }) {\n return (\n <div className=\"adn-preview-inbox\">\n <span className=\"adn-preview-inbox__dot\" />\n <div className=\"adn-preview-inbox__text\">\n <div className=\"adn-preview-inbox__title\">{rendered.title}</div>\n <div className=\"adn-preview-inbox__body\">{rendered.body}</div>\n </div>\n </div>\n )\n}\n\n/** O arquivo anexo: mesmo cartão nos canais que o mostram, só a moldura em volta muda. */\nfunction AttachmentCard({ attachment, block }: { attachment: PreviewAttachment; block: string }) {\n return (\n <div className={`adn-preview-attachment ${block}`}>\n <Icon d={ICON.file} size={18} />\n <span className=\"adn-preview-attachment__text\">\n <span className=\"adn-preview-attachment__name\">{attachment.name}</span>\n {attachment.detail ? <span className=\"adn-preview-attachment__detail\">{attachment.detail}</span> : null}\n </span>\n </div>\n )\n}\n\n/**\n * O corpo do e-mail. Com `html`, um documento inteiro dentro de `<iframe sandbox=\"\" srcDoc>`:\n * sandbox vazio é o mais restrito que existe — sem script, sem mesma-origem, sem formulário — e o\n * CSS do e-mail não vaza para o painel nem herda o dele. Sem `html`, o nó de texto de sempre.\n *\n * Altura fixa com rolagem interna: `sandbox=\"\"` impede ler `contentDocument`, então medir o\n * conteúdo não é possível — e um iframe que se auto-mede exigiria devolver a mesma-origem.\n */\nfunction MailBody({ html, text }: { html: string | undefined; text: string }) {\n if (!html) return <div className=\"adn-preview-mail__body\">{text}</div>\n\n return (\n <iframe\n className=\"adn-preview-mail__body adn-preview-mail__frame\"\n sandbox=\"\"\n srcDoc={html}\n title={text.slice(0, 60)}\n />\n )\n}\n\nexport function TemplatePreview({\n channel,\n viewport,\n rendered,\n emailHtml,\n senderName,\n attachment,\n labels,\n}: TemplatePreviewProps) {\n /** Sem nome do produto, o remetente vira a inicial do assunto — nunca um literal inventado. */\n const sender = senderName ?? rendered.title.slice(0, 1).toUpperCase()\n\n if (channel === 'whatsapp') {\n return (\n <WhatsAppPreview rendered={rendered} labels={labels} os={viewport} senderName={sender} attachment={attachment} />\n )\n }\n if (channel === 'sms') return <SmsPreview rendered={rendered} os={viewport} labels={labels} />\n if (channel === 'push') {\n return <PushPreview rendered={rendered} senderName={sender} labels={labels} os={viewport} />\n }\n if (channel === 'inbox') return <InboxPreview rendered={rendered} />\n\n return viewport === 'browser' ? (\n <EmailDesktop\n rendered={rendered}\n emailHtml={emailHtml}\n senderName={sender}\n labels={labels}\n attachment={attachment}\n />\n ) : (\n <EmailMobile\n rendered={rendered}\n emailHtml={emailHtml}\n senderName={sender}\n os={viewport}\n labels={labels}\n attachment={attachment}\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,SAAS,YAAY;AACrB,OAAO,UAAU;AA6Bb,SAQE,KARF;AAjBJ,IAAM,0BAA0B;AAEzB,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,gBAAgB;AAClB,GAA0B;AACxB,QAAM,EAAE,UAAU,MAAM,IAAI,uBAAuB;AACnD,QAAM,EAAE,MAAM,cAAc,EAAE,IAAI,eAAe;AAEjD,QAAM,YAAY,cAAc;AAChC,QAAM,aAAa,cAAc,gBAAgB,GAAG,aAAa,MAAM,OAAO,WAAW;AACzF,QAAM,kBAAkB,YACpB,GAAG,SAAS,YAAY,CAAC,KAAK,WAAW,IAAI,SAAS,mBAAmB,CAAC,KAC1E,SAAS,YAAY;AAEzB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL;AAAA,MACA,WAAW,KAAK,YAAY,MAAM,eAAe,SAAS;AAAA,MAE1D,cAAY;AAAA,MAGZ;AAAA,4BAAC,QAAK,WAAU,kBAAiB,eAAY,QAAO;AAAA,QACnD;AAAA;AAAA;AAAA,UAGC,oBAAC,UAAK,WAAU,mBAAkB,aAAU,UACzC,sBACH;AAAA,YACE;AAAA;AAAA;AAAA,EACN;AAEJ;;;AChDA,SAAS,YAAY,OAAO,gBAAgB;AAC5C,OAAOA,WAAU;;;ACDjB,SAAS,OAAO,cAAc;AAC9B,OAAOC,WAAU;AA8BT,SAGc,OAAAC,MAHd,QAAAC,aAAA;AAjBD,SAAS,iBAAiB,EAAE,cAAc,UAAU,UAAU,GAA0B;AAC7F,QAAM,EAAE,QAAQ,SAAS,IAAI,uBAAuB;AACpD,QAAM,aAAa,cAAc;AACjC,QAAM,qBAAqB,sBAAsB;AAEjD,QAAM,WAAW,aAAa,WAAW;AAEzC,WAAS,eAAqB;AAC5B,QAAI,SAAU,YAAW,OAAO,aAAa,EAAE;AAC/C,eAAW,YAAY;AAAA,EACzB;AAEA,SACE,gBAAAA,MAAC,QAAG,WAAWC,MAAK,YAAY,YAAY,oBAAoB,SAAS,GAGvE;AAAA,oBAAAD,MAAC,YAAO,MAAK,UAAS,WAAU,kBAAiB,SAAS,cACxD;AAAA,sBAAAA,MAAC,UAAK,WAAU,qBAGb;AAAA,mBAAW,gBAAAD,KAAC,UAAK,WAAU,wBAAuB,cAAY,SAAS,aAAa,GAAG,IAAK;AAAA,QAC7F,gBAAAA,KAAC,UAAK,WAAU,mBAAmB,uBAAa,OAAM;AAAA,QAGtD,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,UAAU,aAAa;AAAA,YACvB,OAAO,4BAA4B,aAAa,WAAW,MAAM;AAAA,YAEhE,iCAAuB,aAAa,WAAW,QAAQ,oBAAI,KAAK,CAAC;AAAA;AAAA,QACpE;AAAA,SACF;AAAA,MACA,gBAAAA,KAAC,UAAK,WAAU,kBAAkB,uBAAa,MAAK;AAAA,OACtD;AAAA,IAEA,gBAAAC,MAAC,SAAI,WAAU,qBACZ;AAAA,iBACC,gBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS,MAAM,WAAW,OAAO,aAAa,EAAE;AAAA,UAChD,UAAU,WAAW;AAAA,UACrB,cAAY,SAAS,iBAAiB;AAAA,UACtC,OAAO,SAAS,iBAAiB;AAAA,UAEjC,0BAAAA,KAAC,SAAM,WAAU,yBAAwB,eAAY,QAAO;AAAA;AAAA,MAC9D,IACE;AAAA,MAEJ,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS,MAAM,mBAAmB,OAAO,aAAa,EAAE;AAAA,UACxD,UAAU,mBAAmB;AAAA,UAC7B,cAAY,SAAS,aAAa;AAAA,UAClC,OAAO,SAAS,aAAa;AAAA,UAG7B,0BAAAA,KAAC,UAAO,WAAU,yBAAwB,eAAY,QAAO;AAAA;AAAA,MAC/D;AAAA,OACF;AAAA,KACF;AAEJ;;;ADvCQ,SACE,OAAAG,MADF,QAAAC,aAAA;AA5BR,IAAM,gBAAgB,CAAC,GAAG,GAAG,CAAC;AAevB,SAAS,iBAAiB,EAAE,UAAU,UAAU,WAAW,aAAa,WAAW,GAA0B;AAClH,QAAM,EAAE,UAAU,MAAM,IAAI,uBAAuB;AACnD,QAAM,QAAQ,iBAAiB,EAAE,SAAS,CAAC;AAC3C,QAAM,EAAE,MAAM,cAAc,EAAE,IAAI,eAAe;AACjD,QAAM,gBAAgB,iBAAiB;AAEvC,QAAM,OAAO,YAAY,QAAQ;AACjC,QAAM,gBAAgB,yBAAyB,MAAM,MAAM,KAAK;AAChE,QAAM,UAAU,CAAC,MAAM,aAAa,CAAC,MAAM,WAAW,cAAc,WAAW;AAE/E,SACE,gBAAAA,MAAC,aAAQ,WAAWC,MAAK,YAAY,MAAM,eAAe,SAAS,GAAG,cAAY,SAAS,YAAY,GACrG;AAAA,oBAAAD,MAAC,YAAO,WAAU,oBAChB;AAAA,sBAAAA,MAAC,SAAI,WAAU,qBACb;AAAA,wBAAAD,KAAC,QAAG,WAAU,mBAAmB,mBAAS,YAAY,GAAE;AAAA,QAGvD,cAAc,IACb,gBAAAA,KAAC,UAAK,WAAU,mBAAkB,MAAK,UAAS,cAAY,GAAG,WAAW,IAAI,SAAS,aAAa,CAAC,IAClG,uBACH,IACE;AAAA,SACN;AAAA,MAEC,cAAc,IACb,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS,MAAM,cAAc,OAAO;AAAA,UACpC,UAAU,cAAc;AAAA,UAExB;AAAA,4BAAAD,KAAC,cAAW,WAAU,uBAAsB,eAAY,QAAO;AAAA,YAC9D,SAAS,oBAAoB;AAAA;AAAA;AAAA,MAChC,IACE;AAAA,OACN;AAAA,IAIC,MAAM,YACL,gBAAAA,KAAC,SAAI,WAAU,sBAAqB,MAAK,UAAS,cAAY,SAAS,cAAc,GAClF,wBAAc,IAAI,CAAC,QAClB,gBAAAA,KAAC,UAAe,WAAU,4BAAf,GAAwC,CACpD,GACH,IACE;AAAA,IAEH,MAAM,UACL,gBAAAC,MAAC,SAAI,WAAU,0CAAyC,MAAK,SAC3D;AAAA,sBAAAD,KAAC,OAAG,mBAAS,YAAY,GAAE;AAAA,MAC3B,gBAAAC,MAAC,YAAO,MAAK,UAAS,WAAU,mBAAkB,SAAS,MAAM,KAAK,MAAM,QAAQ,GAClF;AAAA,wBAAAD,KAAC,YAAS,WAAU,wBAAuB,eAAY,QAAO;AAAA,QAC7D,SAAS,YAAY;AAAA,SACxB;AAAA,OACF,IACE;AAAA,IAEH,UACI,cAAc,KACb,gBAAAC,MAAC,SAAI,WAAU,0CACb;AAAA,sBAAAD,KAAC,SAAM,WAAU,wBAAuB,eAAY,QAAO;AAAA,MAC3D,gBAAAA,KAAC,OAAG,mBAAS,YAAY,GAAE;AAAA,OAC7B,IAEF;AAAA,IAEH,cAAc,SAAS,IACtB,gBAAAA,KAAC,QAAG,WAAU,mBACX,wBAAc,IAAI,CAAC,iBAClB,gBAAAA,KAAC,QAA2B,cAA4B,YAA7C,aAAa,EAAoD,CAC7E,GACH,IACE;AAAA,IAEH,MAAM,cACL,gBAAAA,KAAC,SAAI,WAAU,oBACb,0BAAAA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,SAAS,MAAM,KAAK,MAAM,cAAc;AAAA,QACxC,UAAU,MAAM;AAAA,QAEf,mBAAS,eAAe;AAAA;AAAA,IAC3B,GACF,IACE;AAAA,KACN;AAEJ;;;AEjHA,SAAS,gBAAgB;AACzB,SAAS,YAAY;AACrB,OAAOG,WAAU;AAsCO,gBAAAC,MAIlB,QAAAC,aAJkB;AA5BxB,SAAS,gBAAgB,SAAyB;AAChD,SAAO,WAAW,OAAO;AAC3B;AAEO,SAAS,iBAAiB,EAAE,UAAU,GAA0B;AACrE,QAAM,EAAE,UAAU,MAAM,IAAI,uBAAuB;AACnD,QAAM,EAAE,MAAM,QAAQ,CAAC,GAAG,UAAU,IAAI,eAAe;AACvD,QAAM,oBAAoB,qBAAqB;AAI/C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA+C,MAAS;AAClF,QAAM,cAAc,SAAS;AAE7B,WAAS,cAAc,QAAsC;AAC3D;AAAA,MACE,YAAY;AAAA,QAAI,CAAC,eACf,WAAW,aAAa,OAAO,YAAY,WAAW,YAAY,OAAO,UACrE,EAAE,GAAG,YAAY,SAAS,CAAC,WAAW,QAAQ,IAC9C;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEA,WAAS,aAAmB;AAC1B,sBAAkB,OAAO,aAAa,EAAE,WAAW,MAAM,SAAS,MAAS,EAAE,CAAC;AAAA,EAChF;AAEA,MAAI,UAAW,QAAO,gBAAAD,KAAC,OAAE,WAAU,0BAA0B,mBAAS,cAAc,GAAE;AAEtF,SACE,gBAAAC,MAAC,aAAQ,WAAWC,MAAK,mBAAmB,MAAM,eAAe,SAAS,GACxE;AAAA,oBAAAD,MAAC,YAAO,WAAU,2BAChB;AAAA,sBAAAD,KAAC,QAAG,WAAU,0BAA0B,mBAAS,mBAAmB,GAAE;AAAA,MACtE,gBAAAA,KAAC,OAAE,WAAU,gCAAgC,mBAAS,yBAAyB,GAAE;AAAA,OACnF;AAAA,IAEC,YAAY,WAAW,IACtB,gBAAAA,KAAC,OAAE,WAAU,0BAA0B,mBAAS,mBAAmB,GAAE,IAErE,gBAAAA,KAAC,QAAG,WAAU,0BACX,sBAAY,IAAI,CAAC,eAAe;AAC/B,YAAM,UAAU,YAAY,WAAW,QAAQ,IAAI,WAAW,OAAO;AACrE,aACE,gBAAAC,MAAC,QAAiB,WAAU,yBAG1B;AAAA,wBAAAA,MAAC,WAAM,WAAU,0BAAyB,SAAS,SACjD;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,IAAI;AAAA,cACJ,MAAK;AAAA,cACL,WAAU;AAAA,cACV,SAAS,WAAW;AAAA,cACpB,UAAU,MAAM,cAAc,UAAU;AAAA;AAAA,UAC1C;AAAA,UACA,gBAAAA,KAAC,UAAK,WAAU,6BAA6B,qBAAW,UAAS;AAAA,UACjE,gBAAAA,KAAC,UAAK,WAAU,4BACb,mBAAS,gBAAgB,WAAW,OAAO,CAA0B,KAAK,WAAW,SACxF;AAAA,WACF;AAAA,QAEC,WAAW,mBAAmB,WAAW,gBACxC,gBAAAC,MAAC,UAAK,WAAU,gCACb;AAAA,mBAAS,wBAAwB;AAAA,UAAE;AAAA,UAAE,WAAW;AAAA,UAAiB;AAAA,UACjE,SAAS,0BAA0B;AAAA,UAAE;AAAA,UAAE,WAAW;AAAA,WACrD,IACE;AAAA,WAtBG,OAuBT;AAAA,IAEJ,CAAC,GACH;AAAA,IAGF,gBAAAA,MAAC,YAAO,WAAU,2BAEhB;AAAA,sBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,SAAS;AAAA,UACT,UAAU,kBAAkB,aAAa,UAAU;AAAA,UAEnD;AAAA,4BAAAD,KAAC,QAAK,WAAU,8BAA6B,eAAY,QAAO;AAAA,YAC/D,SAAS,kBAAkB;AAAA;AAAA;AAAA,MAC9B;AAAA,MAEC,kBAAkB,aAAa,UAAU,SACxC,gBAAAA,KAAC,UAAK,WAAU,6BAA4B,MAAK,UAC9C,mBAAS,mBAAmB,GAC/B,IACE;AAAA,MACH,kBAAkB,UACjB,gBAAAA,KAAC,UAAK,WAAU,8DAA6D,MAAK,SAC/E,mBAAS,mBAAmB,GAC/B,IACE;AAAA,OACN;AAAA,KACF;AAEJ;;;ACnCU,SACE,OAAAG,MADF,QAAAC,aAAA;AArBH,SAAS,uBAAuB;AAAA,EACrC,QAAQ;AAAA,EACR;AAAA,EACA,kBAAkB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAgC;AAC9B,QAAM,EAAE,SAAS,IAAI,uBAAuB;AAC5C,QAAM,QAAQ,CAAC,QAAwB,iBAAiB,GAAG,KAAM,SAAoC,GAAG,KAAK;AAE7G,SACE,gBAAAA,MAAC,SAAI,WAAW,iBAAiB,aAAa,EAAE,IAC7C;AAAA,mBACC,aAAa,IAEb,gBAAAA,MAAC,YAAO,WAAU,yBAChB;AAAA,sBAAAA,MAAC,SACC;AAAA,wBAAAD,KAAC,QAAG,WAAU,wBAAwB,gBAAM,iBAAiB,GAAE;AAAA,QAC/D,gBAAAA,KAAC,OAAE,WAAU,8BAA8B,gBAAM,uBAAuB,GAAE;AAAA,SAC5E;AAAA,MAEA,gBAAAC,MAAC,SAAI,WAAU,0BACZ;AAAA,8BAAsB;AAAA,QAEtB,gBACC,gBAAAD,KAAC,OAAE,MAAM,cAAc,WAAU,kCAC9B,gBAAM,wBAAwB,GACjC;AAAA,SAEJ;AAAA,OACF;AAAA,IAGD,kBAAkB;AAAA,IAEnB,gBAAAC,MAAC,SAAI,WAAW,kBAAkB,wBAAwB,+BACxD;AAAA,sBAAAD,KAAC,aAAQ,WAAU,wBAGjB,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACE,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,UAC/B,GAAI,uBAAuB,EAAE,UAAU,qBAAqB,IAAI,CAAC;AAAA,UACjE,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA;AAAA,MACxC,GACF;AAAA,MAEC,mBACC,gBAAAA,KAAC,WAAM,WAAU,wBACf,0BAAAA,KAAC,oBAAiB,GACpB;AAAA,OAEJ;AAAA,KACF;AAEJ;;;ACtGA,SAAS,MAAM,UAAAE,SAAQ,SAAS;AAChC,SAAmB,YAAAC,iBAAgB;;;ACJnC,SAAS,cAAc;;;ACAhB,IAAM,aAAa;AAAA,EACxB,KAAK;AAAA,EACL,MAAM;AAAA,EACN,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AAAA,EACT,SAAS;AAAA,EACT,UAAU;AAAA,EACV,MAAM;AACR;AAcA,IAAM,UACJ;AAEK,SAAS,aAAa,QAAsC;AACjE,QAAM,SAAsB,CAAC;AAC7B,MAAI,SAAS;AAEb,aAAW,SAAS,OAAO,SAAS,OAAO,GAAG;AAC5C,UAAM,QAAQ,MAAM;AACpB,QAAI,QAAQ,OAAQ,MAAK,QAAQ,WAAW,MAAM,OAAO,MAAM,QAAQ,KAAK,CAAC;AAE7E,UAAM,CAAC,OAAO,SAAS,SAAS,MAAM,MAAM,YAAY,OAAO,QAAQ,IAAI;AAE3E,QAAI,QAAS,MAAK,QAAQ,WAAW,SAAS,OAAO;AAAA,aAC5C,QAAS,MAAK,QAAQ,WAAW,SAAS,OAAO;AAAA,aACjD,SAAU,MAAK,QAAQ,WAAW,UAAU,QAAQ;AAAA,aACpD,MAAM;AACb,WAAK,QAAQ,WAAW,KAAK,QAAQ,GAAG;AACxC,WAAK,QAAQ,WAAW,MAAM,IAAI;AAClC,aAAO,KAAK,GAAG,mBAAmB,cAAc,EAAE,CAAC;AACnD,WAAK,QAAQ,WAAW,KAAK,SAAS,GAAG;AAAA,IAC3C;AAEA,aAAS,QAAQ,MAAM;AAAA,EACzB;AAEA,MAAI,SAAS,OAAO,OAAQ,MAAK,QAAQ,WAAW,MAAM,OAAO,MAAM,MAAM,CAAC;AAC9E,SAAO;AACT;AAEA,IAAM,oBAAoB;AAE1B,SAAS,mBAAmB,QAAsC;AAChE,QAAM,SAAsB,CAAC;AAC7B,MAAI,SAAS;AAEb,aAAW,SAAS,OAAO,SAAS,iBAAiB,GAAG;AACtD,UAAM,QAAQ,MAAM;AACpB,QAAI,QAAQ,OAAQ,MAAK,QAAQ,WAAW,MAAM,OAAO,MAAM,QAAQ,KAAK,CAAC;AAE7E,UAAM,CAAC,OAAO,WAAW,QAAQ,KAAK,IAAI;AAC1C,SAAK,QAAQ,WAAW,WAAW,aAAa,EAAE;AAClD,SAAK,QAAQ,WAAW,MAAM,UAAU,EAAE;AAC1C,SAAK,QAAQ,WAAW,OAAO,SAAS,EAAE;AAE1C,aAAS,QAAQ,MAAM;AAAA,EACzB;AAEA,MAAI,SAAS,OAAO,OAAQ,MAAK,QAAQ,WAAW,MAAM,OAAO,MAAM,MAAM,CAAC;AAC9E,SAAO;AACT;AAEA,SAAS,KAAK,QAAqB,MAAqB,MAAoB;AAC1E,MAAI,KAAM,QAAO,KAAK,EAAE,MAAM,KAAK,CAAC;AACtC;;;ADnCY,gBAAAC,MAOF,QAAAC,aAPE;AArBL,SAAS,cAAc,EAAE,OAAO,OAAO,IAAI,UAAU,UAAU,SAAS,SAAS,GAAuB;AAC7G,QAAM,eAAe,OAAuB,IAAI;AAMhD,WAAS,aAAa,OAA2C;AAC/D,UAAM,MAAM,aAAa;AACzB,QAAI,CAAC,IAAK;AACV,QAAI,YAAY,MAAM,cAAc;AACpC,QAAI,aAAa,MAAM,cAAc;AAAA,EACvC;AAEA,QAAM,YAAY,MAAM,MAAM,IAAI,EAAE;AAEpC,SACE,gBAAAA,MAAC,SAAI,WAAU,YACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,oBACb;AAAA,sBAAAD,KAAC,SAAI,WAAU,oBAAmB,eAAY,QAC3C,gBAAM,KAAK,EAAE,QAAQ,UAAU,GAAG,CAAC,GAAG,UACrC,gBAAAA,KAAC,UAAkB,kBAAQ,KAAhB,KAAkB,CAC9B,GACH;AAAA,MAEA,gBAAAC,MAAC,SAAI,WAAU,qBAGb;AAAA,wBAAAA,MAAC,SAAI,KAAK,cAAc,WAAU,uBAAsB,eAAY,QACjE;AAAA,uBAAa,KAAK,EAAE,IAAI,CAAC,OAAO,UAC/B,gBAAAD,KAAC,UAAiB,WAAW,oCAAoC,MAAM,IAAI,IACxE,gBAAM,QADE,KAEX,CACD;AAAA,UAEA;AAAA,WACH;AAAA,QAEA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,YAAY;AAAA,YACZ;AAAA,YACA;AAAA,YACA,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,YAChD,UAAU;AAAA,YACV,UAAU,CAAC,UAAU,WAAW,MAAM,cAAc,cAAc;AAAA,YAClE;AAAA;AAAA,QACF;AAAA,SACF;AAAA,OACF;AAAA,IAEC,YAAY,SAAS,SAAS,KAC7B,gBAAAA,KAAC,QAAG,WAAU,8BACX,mBAAS,IAAI,CAAC,YACb,gBAAAA;AAAA,MAAC;AAAA;AAAA,QAEC,WAAW,4DAA4D,QAAQ,QAAQ;AAAA,QAEtF,kBAAQ;AAAA;AAAA,MAHJ,QAAQ;AAAA,IAIf,CACD,GACH;AAAA,KAEJ;AAEJ;;;AEvFA,SAAS,iBAAiB,UAAAE,SAAQ,YAAAC,iBAAgB;;;ACiB3C,SAAS,UAAU,EAAE,MAAM,WAAW,gBAAgB,aAAa,GAAqC;AAC7G,QAAM,QAAQ,MAAM,gBAAgB,KAAK,MAAM;AAC/C,QAAM,MAAM,MAAM,KAAK,IAAI,cAAc,cAAc,GAAG,KAAK,MAAM;AAErE,QAAM,WAAW,KAAK,MAAM,OAAO,GAAG;AACtC,QAAM,OAAO,UAAU;AAEvB,QAAM,gBAAgB,SAAS,WAAW,SAAS,KAAK,SAAS,SAAS,SAAS,KAAK,SAAS,SAAS,OAAO;AACjH,MAAI,eAAe;AACjB,UAAM,OAAO,SAAS,MAAM,MAAM,CAAC,IAAI;AACvC,WAAO;AAAA,MACL,MAAM,GAAG,KAAK,MAAM,GAAG,KAAK,CAAC,GAAG,IAAI,GAAG,KAAK,MAAM,GAAG,CAAC;AAAA,MACtD,gBAAgB;AAAA,MAChB,cAAc,QAAQ,KAAK;AAAA,IAC7B;AAAA,EACF;AAEA,QAAM,iBAAiB,KAAK,MAAM,QAAQ,MAAM,KAAK,MAAM,aAAa,KAAK,MAAM,KAAK,MAAM,IAAI,MAAM;AACxG,MAAI,gBAAgB;AAClB,WAAO;AAAA,MACL,MAAM,GAAG,KAAK,MAAM,GAAG,QAAQ,IAAI,CAAC,GAAG,QAAQ,GAAG,KAAK,MAAM,MAAM,IAAI,CAAC;AAAA,MACxE,gBAAgB,QAAQ;AAAA,MACxB,cAAc,QAAQ,OAAO,SAAS;AAAA,IACxC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,GAAG,KAAK,MAAM,GAAG,KAAK,CAAC,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,MAAM,GAAG,CAAC;AAAA,IAClF,gBAAgB,QAAQ;AAAA,IACxB,cAAc,QAAQ,OAAO,SAAS;AAAA,EACxC;AACF;AAGO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKoB;AAClB,QAAM,QAAQ,MAAM,gBAAgB,KAAK,MAAM;AAC/C,QAAM,MAAM,MAAM,KAAK,IAAI,cAAc,cAAc,GAAG,KAAK,MAAM;AACrE,QAAM,OAAO,QAAQ,UAAU;AAE/B,SAAO;AAAA,IACL,MAAM,GAAG,KAAK,MAAM,GAAG,KAAK,CAAC,GAAG,SAAS,GAAG,KAAK,MAAM,GAAG,CAAC;AAAA,IAC3D,gBAAgB;AAAA,IAChB,cAAc;AAAA,EAChB;AACF;AAEA,SAAS,MAAM,OAAe,KAAqB;AACjD,SAAO,KAAK,IAAI,KAAK,IAAI,OAAO,CAAC,GAAG,GAAG;AACzC;;;AC3EA,SAAS,MAAM,MAAM,QAAQ,OAAO,qBAAqB;AACzD,SAAS,YAAAC,iBAAgB;;;ACElB,IAAM,iBAAiB;AAAA,EAC5B,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,WAAW;AACb;AAQO,IAAM,uBAAqD;AAAA,EAChE,EAAE,QAAQ,eAAe,MAAM,WAAW,IAAI;AAAA,EAC9C,EAAE,QAAQ,eAAe,QAAQ,WAAW,IAAI;AAAA,EAChD,EAAE,QAAQ,eAAe,eAAe,WAAW,IAAI;AAAA,EACvD,EAAE,QAAQ,eAAe,WAAW,WAAW,MAAM;AACvD;AASO,IAAM,gBAAmC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ADvCyB,gBAAAC,MAiCnB,QAAAC,aAjCmB;AADzB,IAAM,cAA0D;AAAA,EAC9D,CAAC,eAAe,IAAI,GAAG,gBAAAD,KAAC,QAAK,eAAY,QAAO,WAAU,6BAA4B;AAAA,EACtF,CAAC,eAAe,MAAM,GAAG,gBAAAA,KAAC,UAAO,eAAY,QAAO,WAAU,6BAA4B;AAAA,EAC1F,CAAC,eAAe,aAAa,GAAG,gBAAAA,KAAC,iBAAc,eAAY,QAAO,WAAU,6BAA4B;AAAA,EACxG,CAAC,eAAe,SAAS,GAAG,gBAAAA,KAAC,QAAK,eAAY,QAAO,WAAU,6BAA4B;AAC7F;AAEO,SAAS,eAAe,EAAE,QAAQ,UAAU,QAAQ,GAAwB;AACjF,QAAM,CAAC,aAAa,cAAc,IAAIE,UAAS,KAAK;AAEpD,SACE,gBAAAD,MAAC,SAAI,WAAU,eACZ;AAAA,yBAAqB,IAAI,CAAC,EAAE,QAAQ,UAAU,MAC7C,gBAAAD;AAAA,MAAC;AAAA;AAAA,QAEC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,OAAO,QAAQ,WAAW,MAAM,EAAE;AAAA,QAClC,cAAY,QAAQ,WAAW,MAAM,EAAE;AAAA,QAKvC,aAAa,CAAC,UAAU;AACtB,gBAAM,eAAe;AACrB,iBAAO,SAAS;AAAA,QAClB;AAAA,QAEC,sBAAY,MAAM;AAAA;AAAA,MAdd;AAAA,IAeP,CACD;AAAA,IAED,gBAAAA,KAAC,UAAK,WAAU,wBAAuB,eAAY,QAAO;AAAA,IAE1D,gBAAAC,MAAC,SAAI,WAAU,sBACb;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,OAAO,QAAQ,eAAe;AAAA,UAC9B,cAAY,QAAQ,eAAe;AAAA,UACnC,iBAAe;AAAA,UACf,aAAa,CAAC,UAAU;AACtB,kBAAM,eAAe;AACrB,2BAAe,CAAC,YAAY,CAAC,OAAO;AAAA,UACtC;AAAA,UAEA,0BAAAA,KAAC,SAAM,eAAY,QAAO,WAAU,6BAA4B;AAAA;AAAA,MAClE;AAAA,MAEC,eACC,gBAAAA,KAAC,SAAI,WAAU,wBAAuB,MAAK,SAAQ,cAAY,QAAQ,eAAe,GACnF,wBAAc,IAAI,CAAC,UAClB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,WAAU;AAAA,UACV,aAAa,CAAC,UAAU;AACtB,kBAAM,eAAe;AACrB,qBAAS,KAAK;AACd,2BAAe,KAAK;AAAA,UACtB;AAAA,UAEC;AAAA;AAAA,QATI;AAAA,MAUP,CACD,GACH;AAAA,OAEJ;AAAA,KACF;AAEJ;;;AF9BI,SACE,OAAAG,MADF,QAAAC,aAAA;AAzCG,SAAS,iBAAiB,EAAE,OAAO,OAAO,GAAG,UAAU,UAAU,SAAS,QAAQ,GAA0B;AACjH,QAAM,cAAcC,QAA4B,IAAI;AACpD,QAAM,CAAC,kBAAkB,mBAAmB,IAAIC,UAAoC;AAMpF,kBAAgB,MAAM;AACpB,QAAI,CAAC,iBAAkB;AACvB,UAAM,WAAW,YAAY;AAC7B,QAAI,CAAC,SAAU;AAEf,aAAS,MAAM;AACf,aAAS,kBAAkB,iBAAiB,CAAC,GAAG,iBAAiB,CAAC,CAAC;AACnE,wBAAoB,MAAS;AAAA,EAC/B,GAAG,CAAC,gBAAgB,CAAC;AAErB,WAAS,eAA0C;AACjD,UAAM,WAAW,YAAY;AAC7B,QAAI,CAAC,SAAU,QAAO,CAAC,MAAM,QAAQ,MAAM,MAAM;AACjD,WAAO,CAAC,SAAS,gBAAgB,SAAS,YAAY;AAAA,EACxD;AAEA,WAAS,WAAW,WAAyB;AAC3C,UAAM,CAAC,gBAAgB,YAAY,IAAI,aAAa;AACpD,UAAM,SAAS,UAAU,EAAE,MAAM,OAAO,WAAW,gBAAgB,aAAa,CAAC;AAEjF,aAAS,OAAO,IAAI;AACpB,wBAAoB,CAAC,OAAO,gBAAgB,OAAO,YAAY,CAAC;AAAA,EAClE;AAEA,WAAS,aAAa,WAAyB;AAC7C,UAAM,CAAC,gBAAgB,YAAY,IAAI,aAAa;AACpD,UAAM,SAAS,SAAS,EAAE,MAAM,OAAO,WAAW,gBAAgB,aAAa,CAAC;AAEhF,aAAS,OAAO,IAAI;AACpB,wBAAoB,CAAC,OAAO,gBAAgB,OAAO,YAAY,CAAC;AAAA,EAClE;AAEA,SACE,gBAAAF,MAAC,SAAI,WAAU,qBACb;AAAA,oBAAAD,KAAC,kBAAe,QAAQ,YAAY,UAAU,cAAc,SAAkB;AAAA,IAC9E,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,QAChD,UAAU,CAAC,UAAU,WAAW,MAAM,cAAc,cAAc;AAAA,QAClE;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;;;AI1DA,SAAS,+BAA+B;AAyDlC,SACE,OAAAI,MADF,QAAAC,aAAA;AAHN,SAAS,cAAc;AACrB,SACE,gBAAAA,MAAC,UAAK,WAAU,6BACd;AAAA,oBAAAA,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,eAAY,QAC1D;AAAA,sBAAAD,KAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,OAAM,QAAO,KAAI,IAAG,OAAM,MAAK,gBAAe;AAAA,MACtE,gBAAAA,KAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,OAAM,QAAO,KAAI,IAAG,OAAM,MAAK,gBAAe;AAAA,MACtE,gBAAAA,KAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,OAAM,QAAO,KAAI,IAAG,OAAM,MAAK,gBAAe;AAAA,MACtE,gBAAAA,KAAC,UAAK,GAAE,MAAK,GAAE,KAAI,OAAM,OAAM,QAAO,MAAK,IAAG,OAAM,MAAK,gBAAe;AAAA,OAC1E;AAAA,IACA,gBAAAC,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,eAAY,QAC1D;AAAA,sBAAAD,KAAC,UAAK,GAAE,sCAAqC,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM;AAAA,MACjG,gBAAAA,KAAC,YAAO,IAAG,OAAM,IAAG,KAAI,GAAE,KAAI,MAAK,gBAAe;AAAA,OACpD;AAAA,IACA,gBAAAC,MAAC,SAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,eAAY,QAC1D;AAAA,sBAAAD,KAAC,UAAK,GAAE,OAAM,GAAE,OAAM,OAAM,MAAK,QAAO,KAAI,IAAG,OAAM,MAAK,QAAO,QAAO,gBAAe,SAAQ,OAAM;AAAA,MACrG,gBAAAA,KAAC,UAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,KAAI,IAAG,OAAM,MAAK,gBAAe;AAAA,MACrE,gBAAAA,KAAC,UAAK,GAAE,MAAK,GAAE,OAAM,OAAM,OAAM,QAAO,KAAI,IAAG,OAAM,MAAK,gBAAe,SAAQ,OAAM;AAAA,OACzF;AAAA,KACF;AAEJ;AASA,SAAS,MAAM,EAAE,UAAU,IAAI,MAAM,KAAK,GAA2E;AACnH,QAAM,UAAU,OAAO;AACvB,QAAM,UAAU,CAAC,qBAAqB,sBAAsB,UAAU,YAAY,KAAK,EAAE;AACzF,MAAI,SAAS,OAAQ,SAAQ,KAAK,yBAAyB;AAE3D,SACE,gBAAAC,MAAC,SAAI,WAAW,QAAQ,KAAK,GAAG,GAE9B;AAAA,oBAAAD,KAAC,UAAK,WAAU,uDAAsD;AAAA,IACtE,gBAAAA,KAAC,UAAK,WAAU,qDAAoD;AAAA,IACpE,gBAAAA,KAAC,UAAK,WAAU,uDAAsD;AAAA,IACtE,gBAAAA,KAAC,UAAK,WAAU,wDAAuD;AAAA,IACvE,gBAAAC,MAAC,SAAI,WAAU,6BACb;AAAA,sBAAAA,MAAC,SAAI,WAAU,sBACb;AAAA,wBAAAD,KAAC,UAAK,WAAU,4BAA4B,gBAAK;AAAA,QAChD,UAAU,gBAAAA,KAAC,UAAK,WAAU,4BAA2B,IAAK,gBAAAA,KAAC,UAAK,WAAU,6BAA4B;AAAA,QACvG,gBAAAA,KAAC,eAAY;AAAA,SACf;AAAA,MACA,gBAAAA,KAAC,SAAI,WAAU,8BAA8B,UAAS;AAAA,MACtD,gBAAAA,KAAC,SAAI,WAAU,8BAA6B;AAAA,OAC9C;AAAA,KACF;AAEJ;AAGA,SAAS,KAAK,EAAE,GAAG,OAAO,GAAG,GAAiC;AAC5D,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MAEZ,0BAAAA,KAAC,UAAK,GAAM;AAAA;AAAA,EACd;AAEJ;AAEA,IAAM,OAAO;AAAA,EACX,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,KAAK;AAAA,EACL,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AAAA,EACT,MAAM;AAAA,EACN,UACE;AACJ;AAUA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACE,gBAAAC,MAAC,SAAI,WAAU,uBACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,4BACb;AAAA,sBAAAD,KAAC,UAAK,WAAU,4BAA2B;AAAA,MAC3C,gBAAAA,KAAC,UAAK,WAAU,4BAA2B;AAAA,MAC3C,gBAAAA,KAAC,UAAK,WAAU,4BAA2B;AAAA,MAC3C,gBAAAA,KAAC,SAAI,WAAU,gCAAgC,iBAAO,SAAQ;AAAA,OAChE;AAAA,IAEA,gBAAAC,MAAC,SAAI,WAAU,uBACb;AAAA,sBAAAA,MAAC,SAAI,WAAU,4BACb;AAAA,wBAAAA,MAAC,UAAK,WAAU,6BAA4B,eAAY,QACtD;AAAA,0BAAAD,KAAC,UAAK;AAAA,UACN,gBAAAA,KAAC,UAAK;AAAA,UACN,gBAAAA,KAAC,UAAK;AAAA,WACR;AAAA,QACA,gBAAAC,MAAC,SAAI,WAAU,+BACb;AAAA,0BAAAD,KAAC,QAAK,GAAG,KAAK,QAAQ,MAAM,IAAI;AAAA,UAChC,gBAAAA,KAAC,UAAM,iBAAO,SAAQ;AAAA,WACxB;AAAA,QACA,gBAAAC,MAAC,UAAK,WAAU,gCACd;AAAA,0BAAAD,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI;AAAA,UAC9B,gBAAAA,KAAC,QAAK,GAAG,KAAK,UAAU,MAAM,IAAI;AAAA,UAClC,gBAAAA,KAAC,UAAK,WAAU,gDAAgD,qBAAW,MAAM,GAAG,CAAC,GAAE;AAAA,WACzF;AAAA,SACF;AAAA,MAEA,gBAAAC,MAAC,SAAI,WAAU,8BACb;AAAA,wBAAAA,MAAC,SAAI,WAAU,6BAA4B,eAAY,QACrD;AAAA,0BAAAD,KAAC,UAAK,WAAU,gCACd,0BAAAA,KAAC,QAAK,GAAG,KAAK,QAAQ,MAAM,IAAI,GAClC;AAAA,UACA,gBAAAA,KAAC,UAAK,WAAU,yEACd,0BAAAA,KAAC,QAAK,GAAG,KAAK,OAAO,MAAM,IAAI,GACjC;AAAA,UACA,gBAAAA,KAAC,UAAK,WAAU,kCACd,0BAAAA,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI,GAChC;AAAA,WACF;AAAA,QAEA,gBAAAC,MAAC,SAAI,WAAU,iCACb;AAAA,0BAAAA,MAAC,SAAI,WAAU,gCACb;AAAA,4BAAAD,KAAC,QAAK,GAAG,KAAK,MAAM;AAAA,YACpB,gBAAAA,KAAC,UAAK,WAAU,gCAA+B;AAAA,YAC/C,gBAAAA,KAAC,QAAK,GAAG,KAAK,SAAS;AAAA,YACvB,gBAAAA,KAAC,QAAK,GAAG,KAAK,QAAQ;AAAA,YACtB,gBAAAA,KAAC,QAAK,GAAG,KAAK,OAAO;AAAA,YACrB,gBAAAA,KAAC,UAAK,WAAU,gCAA+B;AAAA,YAC/C,gBAAAA,KAAC,QAAK,GAAG,KAAK,QAAQ;AAAA,YACtB,gBAAAA,KAAC,QAAK,GAAG,KAAK,MAAM;AAAA,YACpB,gBAAAA,KAAC,QAAK,GAAG,KAAK,MAAM;AAAA,YACpB,gBAAAA,KAAC,UAAK,WAAU,+BAA8B;AAAA,YAC9C,gBAAAA,KAAC,UAAK,WAAU,gCAAgC,iBAAO,SAAQ;AAAA,YAC/D,gBAAAA,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI;AAAA,YAC9B,gBAAAA,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI;AAAA,aAChC;AAAA,UAEA,gBAAAC,MAAC,SAAI,WAAU,oBACb;AAAA,4BAAAA,MAAC,SAAI,WAAU,iCACb;AAAA,8BAAAD,KAAC,SAAI,WAAU,6BAA6B,mBAAS,OAAM;AAAA,cAC3D,gBAAAA,KAAC,UAAK,WAAU,4BAA4B,iBAAO,QAAO;AAAA,cAC1D,gBAAAC,MAAC,UAAK,WAAU,qCACd;AAAA,gCAAAD,KAAC,QAAK,GAAG,KAAK,OAAO,MAAM,IAAI;AAAA,gBAC/B,gBAAAA,KAAC,QAAK,GAAG,KAAK,QAAQ,MAAM,IAAI;AAAA,iBAClC;AAAA,eACF;AAAA,YAEA,gBAAAC,MAAC,SAAI,WAAU,0BACb;AAAA,8BAAAD,KAAC,UAAK,WAAU,sBAAsB,qBAAW,MAAM,GAAG,CAAC,GAAE;AAAA,cAC7D,gBAAAC,MAAC,UAAK,WAAU,8BACd;AAAA,gCAAAA,MAAC,UAAK,WAAU,gCACd;AAAA,kCAAAD,KAAC,UAAK,WAAU,4BAA4B,sBAAW;AAAA,kBACvD,gBAAAA,KAAC,UAAK,WAAU,6BAA6B,iBAAO,eAAc;AAAA,kBAClE,gBAAAA,KAAC,UAAK,WAAU,iCAAiC,iBAAO,aAAY;AAAA,mBACtE;AAAA,gBACA,gBAAAA,KAAC,UAAK,WAAU,wBAAwB,iBAAO,IAAG;AAAA,iBACpD;AAAA,cACA,gBAAAC,MAAC,UAAK,WAAU,kCACd;AAAA,gCAAAD,KAAC,UAAK,WAAU,0BAA0B,iBAAO,KAAI;AAAA,gBACrD,gBAAAA,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI;AAAA,gBAC9B,gBAAAA,KAAC,QAAK,GAAG,KAAK,OAAO,MAAM,IAAI;AAAA,gBAC/B,gBAAAA,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI;AAAA,iBAChC;AAAA,eACF;AAAA,YAEA,gBAAAA,KAAC,YAAS,MAAM,WAAW,MAAM,SAAS,MAAM;AAAA,YAC/C,aAAa,gBAAAA,KAAC,kBAAe,YAAwB,OAAM,gCAA+B,IAAK;AAAA,aAClG;AAAA,WACF;AAAA,SACF;AAAA,OACF;AAAA,KACF;AAEJ;AAUA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,SACE,gBAAAC,MAAC,SAAM,IAAQ,MAAM,OAAO,MAC1B;AAAA,oBAAAA,MAAC,SAAI,WAAU,gCACb;AAAA,sBAAAD,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI;AAAA,MAC9B,gBAAAA,KAAC,UAAK,WAAU,+BAA8B;AAAA,MAC9C,gBAAAA,KAAC,QAAK,GAAG,KAAK,SAAS,MAAM,IAAI;AAAA,MACjC,gBAAAA,KAAC,QAAK,GAAG,KAAK,OAAO,MAAM,IAAI;AAAA,MAC/B,gBAAAA,KAAC,QAAK,GAAG,KAAK,QAAQ,MAAM,IAAI;AAAA,MAChC,gBAAAA,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI;AAAA,OAChC;AAAA,IAEA,gBAAAA,KAAC,SAAI,WAAU,+BACb,0BAAAC,MAAC,SAAI,WAAU,8CACb;AAAA,sBAAAD,KAAC,SAAI,WAAU,iCACb,0BAAAA,KAAC,SAAI,WAAU,6BAA6B,mBAAS,OAAM,GAC7D;AAAA,MACA,gBAAAA,KAAC,UAAK,WAAU,4BAA4B,iBAAO,QAAO;AAAA,MAE1D,gBAAAC,MAAC,SAAI,WAAU,yDACb;AAAA,wBAAAD,KAAC,UAAK,WAAU,gDAAgD,qBAAW,MAAM,GAAG,CAAC,GAAE;AAAA,QACvF,gBAAAC,MAAC,UAAK,WAAU,8BACd;AAAA,0BAAAA,MAAC,UAAK,WAAU,gCACd;AAAA,4BAAAD,KAAC,UAAK,WAAU,4BAA4B,sBAAW;AAAA,YACvD,gBAAAA,KAAC,UAAK,WAAU,0BAA0B,iBAAO,KAAI;AAAA,aACvD;AAAA,UAEA,gBAAAC,MAAC,UAAK,WAAU,gCACb;AAAA,mBAAO;AAAA,YACR,gBAAAD,KAAC,QAAK,GAAG,KAAK,SAAS,MAAM,IAAI;AAAA,aACnC;AAAA,WACF;AAAA,QACA,gBAAAA,KAAC,UAAK,WAAU,kCACd,0BAAAA,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI,GAChC;AAAA,SACF;AAAA,MAEA,gBAAAA,KAAC,YAAS,MAAM,WAAW,MAAM,SAAS,MAAM;AAAA,MAC/C,aAAa,gBAAAA,KAAC,kBAAe,YAAwB,OAAM,gCAA+B,IAAK;AAAA,MAEhG,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,wBAAAA,MAAC,UAAK,WAAU,kCACd;AAAA,0BAAAD,KAAC,QAAK,GAAG,KAAK,OAAO,MAAM,IAAI;AAAA,UAC9B,OAAO;AAAA,WACV;AAAA,QACA,gBAAAC,MAAC,UAAK,WAAU,kCACd;AAAA,0BAAAD,KAAC,QAAK,GAAG,KAAK,UAAU,MAAM,IAAI;AAAA,UACjC,OAAO;AAAA,WACV;AAAA,QACA,gBAAAC,MAAC,UAAK,WAAU,kCACd;AAAA,0BAAAD,KAAC,QAAK,GAAG,KAAK,SAAS,MAAM,IAAI;AAAA,UAChC,OAAO;AAAA,WACV;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;AASA,SAAS,gBAAgB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACE,gBAAAC,MAAC,SAAM,IAAQ,MAAM,OAAO,MAC1B;AAAA,oBAAAA,MAAC,SAAI,WAAU,0BACb;AAAA,sBAAAD,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI;AAAA,MAC9B,gBAAAA,KAAC,UAAK,WAAU,0BAA0B,qBAAW,MAAM,GAAG,CAAC,GAAE;AAAA,MACjE,gBAAAC,MAAC,UAAK,WAAU,2BACd;AAAA,wBAAAD,KAAC,UAAK,WAAU,wBAAwB,sBAAW;AAAA,QACnD,gBAAAA,KAAC,UAAK,WAAU,0BAA0B,iBAAO,QAAO;AAAA,SAC1D;AAAA,MACA,gBAAAC,MAAC,UAAK,WAAU,kCACd;AAAA,wBAAAD,KAAC,QAAK,GAAG,KAAK,OAAO,MAAM,IAAI;AAAA,QAC/B,gBAAAA,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI;AAAA,QAC9B,gBAAAA,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI;AAAA,SAChC;AAAA,OACF;AAAA,IAEA,gBAAAC,MAAC,SAAI,WAAU,kBACb;AAAA,sBAAAD,KAAC,SAAI,WAAU,uBAAuB,iBAAO,OAAM;AAAA,MACnD,gBAAAC,MAAC,SAAI,WAAU,0BACZ;AAAA,qBAAa,gBAAAD,KAAC,kBAAe,YAAwB,OAAM,8BAA6B,IAAK;AAAA,QAC9F,gBAAAA,KAAC,SAAI,WAAU,wBAAwB,kCAAwB,SAAS,IAAI,GAAE;AAAA,QAC9E,gBAAAA,KAAC,SAAI,WAAU,wBAAwB,iBAAO,KAAI;AAAA,SACpD;AAAA,OACF;AAAA,IAEA,gBAAAC,MAAC,SAAI,WAAU,4BACb;AAAA,sBAAAD,KAAC,UAAK,WAAU,yBAAyB,iBAAO,SAAQ;AAAA,MACxD,gBAAAA,KAAC,UAAK,WAAU,wBACd,0BAAAA,KAAC,QAAK,GAAG,KAAK,KAAK,MAAM,IAAI,GAC/B;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,SAAS,WAAW;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACE,gBAAAA,KAAC,SAAM,IAAQ,MAAM,OAAO,MAC1B,0BAAAA,KAAC,SAAI,WAAU,mBACb,0BAAAA,KAAC,SAAI,WAAU,2BAA2B,mBAAS,MAAK,GAC1D,GACF;AAEJ;AAGA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,SACE,gBAAAA,KAAC,SAAM,IAAQ,MAAK,QAAO,MAAM,OAAO,MACtC,0BAAAA,KAAC,SAAI,WAAU,oBACb,0BAAAC,MAAC,SAAI,WAAU,0BACb;AAAA,oBAAAA,MAAC,SAAI,WAAU,yBACb;AAAA,sBAAAD,KAAC,UAAK,WAAU,gDAAgD,qBAAW,MAAM,GAAG,CAAC,GAAE;AAAA,MACvF,gBAAAA,KAAC,UAAM,sBAAW;AAAA,MAClB,gBAAAA,KAAC,UAAK,WAAU,0BAA0B,iBAAO,KAAI;AAAA,OACvD;AAAA,IACA,gBAAAA,KAAC,SAAI,WAAU,2BAA2B,mBAAS,OAAM;AAAA,IACzD,gBAAAA,KAAC,SAAI,WAAU,0BAA0B,mBAAS,MAAK;AAAA,KACzD,GACF,GACF;AAEJ;AAGA,SAAS,aAAa,EAAE,SAAS,GAA0C;AACzE,SACE,gBAAAC,MAAC,SAAI,WAAU,qBACb;AAAA,oBAAAD,KAAC,UAAK,WAAU,0BAAyB;AAAA,IACzC,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,sBAAAD,KAAC,SAAI,WAAU,4BAA4B,mBAAS,OAAM;AAAA,MAC1D,gBAAAA,KAAC,SAAI,WAAU,2BAA2B,mBAAS,MAAK;AAAA,OAC1D;AAAA,KACF;AAEJ;AAGA,SAAS,eAAe,EAAE,YAAY,MAAM,GAAqD;AAC/F,SACE,gBAAAC,MAAC,SAAI,WAAW,0BAA0B,KAAK,IAC7C;AAAA,oBAAAD,KAAC,QAAK,GAAG,KAAK,MAAM,MAAM,IAAI;AAAA,IAC9B,gBAAAC,MAAC,UAAK,WAAU,gCACd;AAAA,sBAAAD,KAAC,UAAK,WAAU,gCAAgC,qBAAW,MAAK;AAAA,MAC/D,WAAW,SAAS,gBAAAA,KAAC,UAAK,WAAU,kCAAkC,qBAAW,QAAO,IAAU;AAAA,OACrG;AAAA,KACF;AAEJ;AAUA,SAAS,SAAS,EAAE,MAAM,KAAK,GAA+C;AAC5E,MAAI,CAAC,KAAM,QAAO,gBAAAA,KAAC,SAAI,WAAU,0BAA0B,gBAAK;AAEhE,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,SAAQ;AAAA,MACR,QAAQ;AAAA,MACR,OAAO,KAAK,MAAM,GAAG,EAAE;AAAA;AAAA,EACzB;AAEJ;AAEO,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyB;AAEvB,QAAM,SAAS,cAAc,SAAS,MAAM,MAAM,GAAG,CAAC,EAAE,YAAY;AAEpE,MAAI,YAAY,YAAY;AAC1B,WACE,gBAAAA,KAAC,mBAAgB,UAAoB,QAAgB,IAAI,UAAU,YAAY,QAAQ,YAAwB;AAAA,EAEnH;AACA,MAAI,YAAY,MAAO,QAAO,gBAAAA,KAAC,cAAW,UAAoB,IAAI,UAAU,QAAgB;AAC5F,MAAI,YAAY,QAAQ;AACtB,WAAO,gBAAAA,KAAC,eAAY,UAAoB,YAAY,QAAQ,QAAgB,IAAI,UAAU;AAAA,EAC5F;AACA,MAAI,YAAY,QAAS,QAAO,gBAAAA,KAAC,gBAAa,UAAoB;AAElE,SAAO,aAAa,YAClB,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,MACA;AAAA;AAAA,EACF,IAEA,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ,IAAI;AAAA,MACJ;AAAA,MACA;AAAA;AAAA,EACF;AAEJ;;;APnbQ,SAwbI,YAAAE,WAxbJ,OAAAC,OAsGE,QAAAC,cAtGF;AAVR,SAAS,WAAW,MAAuB;AACzC,SAAO,+BAA+B,KAAK,IAAI;AACjD;AAgBO,SAAS,8BAA8B;AAAA,EAC5C,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuC;AACrC,QAAM,EAAE,SAAS,IAAI,uBAAuB;AAC5C,QAAM,QAAQ,CAAC,QAAwB,iBAAiB,GAAG,KAAM,SAAoC,GAAG,KAAK;AAE7G,QAAM,mBAAmB,eAAe;AACxC,QAAM,oBAAoB,qBAAqB;AAC/C,QAAM,SAAS,kBAAkB;AAAA,IAC/B,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;AAAA,IAC3C,GAAI,SAAS,CAAC,IAAI,EAAE,gBAAgB,SAAS,CAAC,EAAE,GAAG,IAAI,CAAC;AAAA,EAC1D,CAAC;AAOD,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAA6D;AAAA,IACvF,OAAO;AAAA,IACP,aAAa;AAAA,EACf,CAAC;AAGD,QAAM,CAAC,eAAe,gBAAgB,IAAIA,UAA6B,MAAS;AAEhF,QAAM,CAAC,eAAe,gBAAgB,IAAIA,UAA6B,MAAS;AAEhF,WAAS,eAAe,OAA2B,aAAkC;AACnF,cAAU,EAAE,OAAO,aAAa,eAAe,EAAE,CAAC;AAAA,EACpD;AAEA,QAAM,WAAW,oBAAoB;AACrC,QAAM,CAAC,KAAK,MAAM,IAAIA,UAAiC,UAAU;AAOjE,WAAS,UAAU,UAAkB,SAA0B;AAC7D,UAAM,OAAO,iBAAiB,QAAQ,CAAC,GAAG;AAAA,MACxC,CAAC,eAAe,WAAW,aAAa,YAAY,WAAW,YAAY;AAAA,IAC7E;AACA,WAAO,KAAK,WAAW;AAAA,EACzB;AAEA,WAAS,OAAO,UAAkB,SAAuB;AAEvD,UAAM,OAAiC,WAAW;AAAA,MAAQ,CAAC,iBACzD,SAAS,IAAI,CAAC,iBAAiB;AAAA,QAC7B,UAAU,aAAa;AAAA,QACvB,SAAS,YAAY;AAAA,QACrB,SACE,aAAa,OAAO,YAAY,YAAY,OAAO,UAC/C,CAAC,UAAU,UAAU,OAAO,IAC5B,UAAU,aAAa,IAAI,YAAY,EAAE;AAAA,MACjD,EAAE;AAAA,IACJ;AACA,sBAAkB,OAAO,IAAI;AAAA,EAC/B;AAMA,WAAS,WAAW,OAAkC;AACpD,QAAI,OAAO,MAAM,UAAU,MAAO,QAAO;AACzC,WAAO,OAAO,KAAK,cAAc,gBAAgB,MAAM,WAAM;AAAA,EAC/D;AAEA,WAAS,WAAW,OAA+D;AACjF,QAAI,OAAO,MAAM,UAAU,MAAO,QAAO;AACzC,WAAO,OAAO,KAAK,cAAc,gBAAgB,MAAM,cAAc;AAAA,EACvE;AAEA,SACE,gBAAAC,OAAC,SAAI,WAAW,gBAAgB,aAAa,EAAE,IAC5C;AAAA,mBACC,aAAa,IAEb,gBAAAA,OAAC,YAAO,WAAU,wBAChB;AAAA,sBAAAA,OAAC,SACC;AAAA,wBAAAC,MAAC,QAAG,WAAU,uBAAuB,gBAAM,gBAAgB,GAAE;AAAA,QAC7D,gBAAAA,MAAC,OAAE,WAAU,6BAA6B,gBAAM,sBAAsB,GAAE;AAAA,SAC1E;AAAA,MACC,sBAAsB;AAAA,OACzB;AAAA,IAGF,gBAAAA,MAAC,SAAI,WAAU,sBAAqB,MAAK,WACrC,WAAC,YAAY,SAAS,EAAY,IAAI,CAAC,OACvC,gBAAAA;AAAA,MAAC;AAAA;AAAA,QAEC,MAAK;AAAA,QACL,MAAK;AAAA,QACL,iBAAe,QAAQ;AAAA,QACvB,WAAW,QAAQ,KAAK,gDAAgD;AAAA,QACxE,SAAS,MAAM,OAAO,EAAE;AAAA,QAEvB,gBAAM,gBAAgB,EAAE,EAAE;AAAA;AAAA,MAPtB;AAAA,IAQP,CACD,GACH;AAAA,IAEC,QAAQ,aACP,gBAAAD,OAAC,aAAQ,WAAU,0BACjB;AAAA,sBAAAC,MAAC,QAAG,WAAU,+BAA+B,gBAAM,wBAAwB,GAAE;AAAA,MAC7E,gBAAAA,MAAC,OAAE,WAAU,sBAAsB,gBAAM,uBAAuB,GAAE;AAAA,MAEjE,WAAW,IAAI,CAAC,aACf,gBAAAD,OAAC,SAAsB,WAAU,0BAC/B;AAAA,wBAAAC,MAAC,OAAE,WAAU,gCAAgC,mBAAS,OAAM;AAAA,QAC5D,gBAAAA,MAAC,SAAI,WAAU,mCACZ,mBAAS,IAAI,CAAC,YACb,gBAAAD,OAAC,WAAuB,WAAU,wBAChC;AAAA,0BAAAC;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,SAAS,UAAU,EAAE,UAAU,SAAS,IAAI,SAAS,QAAQ,GAAG,CAAC;AAAA,cAC1E,UAAU,MAAM,SAAS,OAAO,EAAE,UAAU,SAAS,IAAI,SAAS,QAAQ,GAAG,CAAC;AAAA;AAAA,UAChF;AAAA,UACA,gBAAAA,MAAC,UAAK,WAAU,+BAA+B,kBAAQ,OAAM;AAAA,aANnD,QAAQ,EAOpB,CACD,GACH;AAAA,WAbQ,SAAS,EAcnB,CACD;AAAA,MAEA,SAAS,SAAS,gBAAAA,MAAC,OAAE,WAAU,uBAAuB,mBAAS,OAAM;AAAA,MAEtE,gBAAAD,OAAC,SAAI,WAAU,yBACb;AAAA,wBAAAC,MAAC,YAAO,MAAK,UAAS,SAAS,SAAS,MAAM,UAAU,CAAC,SAAS,WAAW,SAAS,UACnF,mBAAS,WAAW,MAAM,iBAAiB,IAAI,MAAM,uBAAuB,GAC/E;AAAA,QACC,SAAS,WACR,gBAAAA,MAAC,YAAO,MAAK,UAAS,SAAS,SAAS,OACrC,gBAAM,kBAAkB,GAC3B;AAAA,SAEJ;AAAA,OACF;AAAA,IAGD,QAAQ,aACT,gBAAAD,OAAC,aAAQ,WAAU,0BACjB;AAAA,sBAAAC,MAAC,QAAG,WAAU,+BAA+B,gBAAM,wBAAwB,GAAE;AAAA,MAC7E,gBAAAA,MAAC,OAAE,WAAU,sBAAsB,gBAAM,uBAAuB,GAAE;AAAA,MAEjE,WAAW,IAAI,CAAC,aACf,gBAAAD,OAAC,SAAsB,WAAU,0BAC/B;AAAA,wBAAAC,MAAC,OAAE,WAAU,gCAAgC,mBAAS,OAAM;AAAA,QAC3D,SAAS,QAAQ,gBAAAA,MAAC,OAAE,WAAU,sBAAsB,mBAAS,MAAK;AAAA,QAEnE,gBAAAA,MAAC,SAAI,WAAU,8BACZ,mBAAS,IAAI,CAAC,YACb,gBAAAD,OAAC,WAAuB,WAAU,yBAChC;AAAA,0BAAAC;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,UAAU,SAAS,IAAI,QAAQ,EAAE;AAAA,cAC1C,UAAU,kBAAkB;AAAA,cAC5B,UAAU,MAAM,OAAO,SAAS,IAAI,QAAQ,EAAE;AAAA;AAAA,UAChD;AAAA,UACA,gBAAAD,OAAC,UACC;AAAA,4BAAAC,MAAC,UAAK,WAAU,+BAA+B,kBAAQ,OAAM;AAAA,YAC5D,QAAQ,QAAQ,gBAAAA,MAAC,UAAK,WAAU,sBAAsB,kBAAQ,MAAK;AAAA,aACtE;AAAA,aAVU,QAAQ,EAWpB,CACD,GACH;AAAA,WAnBQ,SAAS,EAoBnB,CACD;AAAA,OACH;AAAA,IAKC,QAAQ,cACT,gBAAAD,OAAC,SAAI,WAAW,OAAO,QAAQ,4BAA4B,6DACzD;AAAA,sBAAAA,OAAC,aAAQ,WAAU,+BACjB;AAAA,wBAAAC,MAAC,YAAO,WAAU,6BAGhB,0BAAAD,OAAC,SAAI,WAAU,iCACb;AAAA,0BAAAC,MAAC,QAAG,WAAU,+BAA+B,gBAAM,yBAAyB,GAAE;AAAA,UAC9E,gBAAAD,OAAC,SAAI,WAAU,qCAEb;AAAA,4BAAAC,MAAC,SAAI,WAAU,6BAA4B,MAAK,SAAQ,cAAY,MAAM,oBAAoB,GAC3F,WAAC,eAAe,OAAO,eAAe,IAAI,EAAE,IAAI,CAAC,SAChD,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,gBAAc,OAAO,SAAS;AAAA,gBAC9B,WACE,OAAO,SAAS,OACZ,8CACA;AAAA,gBAEN,SAAS,MAAM,OAAO,QAAQ,IAAI;AAAA,gBAEjC,gBAAM,iBAAiB,IAAI,EAAE;AAAA;AAAA,cAVzB;AAAA,YAWP,CACD,GACH;AAAA,YACA,gBAAAD,OAAC,YAAO,MAAK,UAAS,WAAU,qBAAoB,SAAS,OAAO,UAElE;AAAA,8BAAAC,MAAC,QAAK,WAAU,6BAA4B,eAAY,QAAO;AAAA,cAC9D,MAAM,sBAAsB;AAAA,eAC/B;AAAA,aACF;AAAA,WACF,GACF;AAAA,QAIA,gBAAAD,OAAC,SAAI,WAAU,8BACb;AAAA,0BAAAA,OAAC,WAAM,WAAU,wBACf;AAAA,4BAAAC,MAAC,UAAK,WAAU,2DACb,gBAAM,sBAAsB,GAC/B;AAAA,YACA,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO,OAAO;AAAA,gBACd,aAAa,MAAM,4BAA4B;AAAA,gBAC/C,UAAU,CAAC,UAAU,OAAO,UAAU,MAAM,OAAO,KAAK;AAAA;AAAA,YAC1D;AAAA,aACF;AAAA,UAEC,OAAO,WAAW,SAAS,KAC1B,gBAAAA,MAAC,SAAI,WAAU,4BACZ,iBAAO,WAAW,IAAI,CAAC,aACtB,gBAAAA;AAAA,YAAC;AAAA;AAAA,cAEC,MAAK;AAAA,cACL,gBAAc,OAAO,eAAe,SAAS,QAAQ;AAAA,cACrD,WACE,OAAO,eAAe,SAAS,QAAQ,IACnC,kDACA;AAAA,cAEN,SAAS,MAAM,OAAO,qBAAqB,QAAQ;AAAA,cAElD,4BAAkB,QAAQ,KAAK;AAAA;AAAA,YAV3B;AAAA,UAWP,CACD,GACH;AAAA,UAGF,gBAAAA,MAAC,SAAI,WAAU,4BACZ,mBAAS,IAAI,CAAC,YACb,gBAAAA;AAAA,YAAC;AAAA;AAAA,cAEC,MAAK;AAAA,cACL,gBAAc,OAAO,cAAc,SAAS,QAAQ,EAAE;AAAA,cACtD,WACE,OAAO,cAAc,SAAS,QAAQ,EAAE,IACpC,kDACA;AAAA,cAEN,SAAS,MAAM,OAAO,oBAAoB,QAAQ,EAAE;AAAA,cAEnD,kBAAQ;AAAA;AAAA,YAVJ,QAAQ;AAAA,UAWf,CACD,GACH;AAAA,UAGC,OAAO,cACN,gBAAAA,MAAC,YAAO,MAAK,UAAS,WAAU,uBAAsB,SAAS,OAAO,cACnE,gBAAM,uBAAuB,GAChC;AAAA,WAEJ;AAAA,QAEC,OAAO,aAAa,gBAAAA,MAAC,OAAE,WAAU,sBAAsB,gBAAM,cAAc,GAAE;AAAA,QAI7E,CAAC,OAAO,aAAa,OAAO,eAAe,KAC1C,gBAAAA,MAAC,OAAE,WAAU,sBAAsB,gBAAM,yBAAyB,GAAE;AAAA,QAErE,CAAC,OAAO,aAAa,OAAO,aAAa,KAAK,OAAO,UAAU,WAAW,KACzE,gBAAAA,MAAC,OAAE,WAAU,sBAAsB,gBAAM,oBAAoB,GAAE;AAAA,QAGhE,OAAO,SAAS,eAAe,SAAS,OAAO,UAAU,SAAS;AAAA,QAEjE,gBAAAA,MAAC,SAAI,WAAU,8BACb,0BAAAD,OAAC,WAAM,WAAU,uBACf;AAAA,0BAAAC,MAAC,WACC,0BAAAA,MAAC,QACE,2BAAiB,IAAI,CAAC,EAAE,UAAU,OAAO,aAAa,MACrD,gBAAAA,MAAC,QAAkB,OAAM,OAAM,aAAW,QAAQ,WAAW,KAAK,IAAI,QACnE,kBACC,gBAAAD,OAAC,YAAO,MAAK,UAAS,SAAS,MAAM,OAAO,WAAW,KAAK,GACzD;AAAA,kBAAM,QAAQ;AAAA,YACf,gBAAAC,MAAC,UAAK,eAAY,QAAO,WAAU,2BAChC,qBAAW,KAAK,GACnB;AAAA,aACF,IAEA,gBAAAA,MAAC,UAAK,WAAW,eAAe,kCAAkC,QAC/D,gBAAM,QAAQ,GACjB,KAXK,QAaT,CACD,GACH,GACF;AAAA,UACA,gBAAAA,MAAC,WACE,iBAAO,UAAU,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,YAIrB,gBAAAD;AAAA,cAAC;AAAA;AAAA,gBAEC,SAAS,MAAM,OAAO,OAAO,QAAQ;AAAA,gBACrC,WACE,OAAO,UAAU,OAAO,SAAS,KAC7B,4DACA;AAAA,gBAGN;AAAA,kCAAAC,MAAC,QACC,0BAAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,WAAU;AAAA,sBACV,SAAS,MAAM,OAAO,OAAO,QAAQ;AAAA,sBAEpC,4BAAkB,QAAQ,KAAK,SAAS;AAAA;AAAA,kBAC3C,GACF;AAAA,kBACA,gBAAAA,MAAC,QAAG,WAAU,4BAA4B,mBAAS,MAAK;AAAA,kBACxD,gBAAAA,MAAC,QACC,0BAAAA,MAAC,UAAK,WAAW,4CAA4C,SAAS,OAAO,IAC1E,gBAAM,WAAW,SAAS,OAAO,EAAE,GACtC,GACF;AAAA,kBACA,gBAAAD,OAAC,QAAG,WAAU,yBACX;AAAA,0BAAM,kBAAkB;AAAA,oBACxB,SAAS;AAAA,qBACZ;AAAA,kBACA,gBAAAC,MAAC,QACE,6BAAmB,SAAS,GAAG;AAAA;AAAA,oBAE9B,gBAAAA,MAAC,UAAK,WAAU,uBAAuB,gBAAM,yBAAyB,GAAE;AAAA,sBAExE,gBAAAD;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,WAAU;AAAA,sBACV,cAAY,GAAG,MAAM,iBAAiB,CAAC,IAAI,SAAS,GAAG;AAAA,sBACvD,UAAU,OAAO;AAAA,sBAEjB,SAAS,CAAC,UAAU;AAClB,8BAAM,gBAAgB;AACtB,+BAAO,WAAW,SAAS,EAAE;AAAA,sBAC/B;AAAA,sBAEA;AAAA,wCAAAC,MAACC,SAAA,EAAO,WAAU,6BAA4B,eAAY,QAAO;AAAA,wBAChE,MAAM,iBAAiB;AAAA;AAAA;AAAA,kBAC1B,GAEJ;AAAA;AAAA;AAAA,cA/CK,SAAS;AAAA,YAgDhB;AAAA,WACD,GACH;AAAA,WACF,GACF;AAAA,QAGD,OAAO,SAAS,eAAe,QAC9B,OAAO,OAAO,IAAI,CAAC,UACnB,gBAAAF,OAAC,SAAyB,WAAU,uBAClC;AAAA,0BAAAA,OAAC,OAAE,WAAU,6BACV;AAAA,8BAAkB,MAAM,QAAQ,KAAK,MAAM;AAAA,YAC5C,gBAAAC,MAAC,UAAK,WAAU,6BAA6B,gBAAM,UAAU,QAAO;AAAA,aACtE;AAAA,UACA,gBAAAA,MAAC,QACE,gBAAM,UAAU,IAAI,CAAC,aACpB,gBAAAD,OAAC,QAAqB,WAAU,qBAC9B;AAAA,4BAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,MAAM,OAAO,OAAO,QAAQ;AAAA,gBACrC,WAAW,OAAO,UAAU,OAAO,SAAS,KAAK,8BAA8B;AAAA,gBAE/E;AAAA,kCAAAA,OAAC,UAAK,WAAU,0BACd;AAAA,oCAAAC,MAAC,UAAK,WAAU,2BAA2B,4BAAkB,QAAQ,KAAK,SAAS,KAAI;AAAA,oBACvF,gBAAAA,MAAC,UAAK,WAAU,0BAA0B,mBAAS,MAAK;AAAA,qBAC1D;AAAA,kBACA,gBAAAA,MAAC,UAAK,WAAW,4CAA4C,SAAS,OAAO,IAC1E,gBAAM,WAAW,SAAS,OAAO,EAAE,GACtC;AAAA,kBACA,gBAAAD,OAAC,UAAK,WAAU,yBACb;AAAA,0BAAM,kBAAkB;AAAA,oBACxB,SAAS;AAAA,qBACZ;AAAA;AAAA;AAAA,YACF;AAAA,YACC,mBAAmB,SAAS,GAAG,IAC9B,gBAAAC,MAAC,UAAK,WAAU,uBAAuB,gBAAM,yBAAyB,GAAE,IAExE,gBAAAD;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,cAAY,GAAG,MAAM,iBAAiB,CAAC,IAAI,SAAS,GAAG;AAAA,gBACvD,UAAU,OAAO;AAAA,gBACjB,SAAS,MAAM,OAAO,WAAW,SAAS,EAAE;AAAA,gBAE5C;AAAA,kCAAAC,MAACC,SAAA,EAAO,WAAU,6BAA4B,eAAY,QAAO;AAAA,kBAChE,MAAM,iBAAiB;AAAA;AAAA;AAAA,YAC1B;AAAA,eA9BK,SAAS,EAgClB,CACD,GACH;AAAA,aAzCQ,MAAM,QA0Cd,CACD;AAAA,SACL;AAAA,MAEC,OAAO,SACR,gBAAAD,MAAC,aAAQ,WAAU,wBAEf,0BAAAD,OAAAG,WAAA,EACE;AAAA,wBAAAH,OAAC,YAAO,WAAU,+BAChB;AAAA,0BAAAA,OAAC,SACC;AAAA,4BAAAA,OAAC,QAAG,WAAU,+BACX;AAAA,qBAAO,WAAY,kBAAkB,OAAO,QAAQ,KAAK,OAAO,SAAS,MAAO;AAAA,cAChF,OAAO,mBACN,gBAAAC,MAAC,UAAK,WAAU,uBAAuB,gBAAM,yBAAyB,GAAE;AAAA,eAE5E;AAAA,YACA,gBAAAD,OAAC,OAAE,WAAU,sBACV;AAAA,qBAAO,MAAM,SAAS,KAAK,QAAK;AAAA,cAAE;AAAA,cAAI,OAAO,MAAM;AAAA,cAAO;AAAA,cAAI,MAAM,kBAAkB;AAAA,cACtF,OAAO,UAAU;AAAA,eACpB;AAAA,aACF;AAAA,UACA,gBAAAA,OAAC,SAAI,WAAU,gCAEZ;AAAA,mBAAO,YAAY,sBAAsB,EAAE,aAAa,OAAO,SAAS,IAAI,CAAC;AAAA,YAC7E,OAAO,mBAAmB,OAAO,YAChC,gBAAAC;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,UAAU,OAAO;AAAA,gBACjB,SAAS,MAAM,OAAO,YAAY,OAAO,eAAe,OAAO,SAAS,EAAE;AAAA,gBAEzE,iBAAO,cAAc,MAAM,oBAAoB,IAAI,MAAM,yBAAyB;AAAA;AAAA,YACrF;AAAA,YAEF,gBAAAD,OAAC,YAAO,MAAK,UAAS,WAAU,uBAAsB,SAAS,OAAO,OACpE;AAAA,8BAAAC,MAAC,KAAE,WAAU,6BAA4B,eAAY,QAAO;AAAA,cAC3D,MAAM,gBAAgB;AAAA,eACzB;AAAA,aACF;AAAA,WACF;AAAA,QAEC,CAAC,OAAO,oBACP,gBAAAD,OAAC,SAAI,WAAU,0BACb;AAAA,0BAAAA,OAAC,WAAM,WAAU,uBACf;AAAA,4BAAAC,MAAC,UAAK,WAAU,6BAA6B,gBAAM,cAAc,GAAE;AAAA,YACnE,gBAAAA,MAAC,UAAK,WAAU,sBAAsB,gBAAM,kBAAkB,GAAE;AAAA,YAChE,gBAAAA,MAAC,WAAM,OAAO,OAAO,MAAM,KAAK,UAAU,CAAC,UAAU,OAAO,OAAO,EAAE,KAAK,MAAM,OAAO,MAAM,CAAC,GAAG;AAAA,aACnG;AAAA,UAIA,gBAAAD,OAAC,cAAS,WAAU,qDAClB;AAAA,4BAAAC,MAAC,YAAO,WAAU,6BAA6B,gBAAM,kBAAkB,GAAE;AAAA,YACzE,gBAAAA,MAAC,UAAK,WAAU,sBAAsB,gBAAM,sBAAsB,GAAE;AAAA,YACpE,gBAAAA,MAAC,SAAI,WAAU,gCACZ,mBAAS,IAAI,CAAC,YACb,gBAAAD,OAAC,WAAuB,WAAU,8BAChC;AAAA,8BAAAC;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAS,OAAO,OAAO,SAAS,SAAS,QAAQ,EAAE,KAAK;AAAA,kBACxD,UAAU,MAAM;AACd,2BAAO,cAAc,QAAQ,EAAE;AAE/B,wBAAI,CAAC,OAAO,OAAO,SAAS,SAAS,QAAQ,EAAE,EAAG,kBAAiB,QAAQ,EAAE;AAAA,kBAC/E;AAAA;AAAA,cACF;AAAA,cACA,gBAAAA,MAAC,UAAM,kBAAQ,OAAM;AAAA,iBAVX,QAAQ,EAWpB,CACD,GACH;AAAA,aACF;AAAA,UAEA,gBAAAD,OAAC,WAAM,WAAU,uBACf;AAAA,4BAAAC,MAAC,UAAK,WAAU,6BAA6B,gBAAM,iBAAiB,GAAE;AAAA,YACtE,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,OAAO,MAAM;AAAA,gBACpB,UAAU,CAAC,UAAU,OAAO,OAAO,EAAE,QAAQ,MAAM,OAAO,MAAM,CAAC;AAAA;AAAA,YACnE;AAAA,aACF;AAAA,WACF;AAAA,QAGD,OAAO,UAAU,SAAS,KACzB,gBAAAD,OAAC,SAAI,WAAU,2BACb;AAAA,0BAAAC,MAAC,OAAE,WAAU,6BAA6B,gBAAM,yBAAyB,GAAE;AAAA,UAC3E,gBAAAA,MAAC,OAAE,WAAU,sBAAsB,gBAAM,wBAAwB,GAAE;AAAA,UACnE,gBAAAA,MAAC,QACE,iBAAO,UAAU,IAAI,CAAC,aAAa;AAClC,kBAAM,OAAO,OAAO,aAAa,KAAK,SAAS,SAAS,IAAI;AAC5D,kBAAM,UAAU,OAAO,aAAa,gBAAgB,SAAS,SAAS,IAAI;AAC1E,mBACE,gBAAAA,MAAC,QACC,0BAAAD;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAW;AAAA,kBACT;AAAA,kBACA,OAAO,iCAAiC;AAAA,kBACxC,UAAU,oCAAoC;AAAA,gBAChD,EACG,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,gBACX,SAAS,MACP,OAAO,eAAe;AAAA,kBACpB,GAAG;AAAA,kBACH,MAAM,SAAS;AAAA,kBACf,SAAS,iBAAiB,OAAO,OAAO,SAAS,CAAC,KAAK;AAAA,gBACzD,CAAC;AAAA,gBAGH;AAAA,kCAAAC,MAAC,UAAK,WAAU,+BAA+B,eAAK,SAAS,IAAI,MAAK;AAAA,kBACtE,gBAAAA,MAAC,UAAK,WAAU,sBAAsB,mBAAS,SAAQ;AAAA;AAAA;AAAA,YACzD,KApBO,SAAS,IAqBlB;AAAA,UAEJ,CAAC,GACH;AAAA,WACF;AAAA,QAGD,OAAO,aAAa,QAAQ,SAAS,KACpC,gBAAAD,OAAC,OAAE,WAAU,uBACV;AAAA,gBAAM,2BAA2B;AAAA,UAAE;AAAA,UAAE,OAAO,aAAa,QAAQ,KAAK,IAAI;AAAA,WAC7E;AAAA,QAqBF,gBAAAC,MAAC,SAAI,WAAU,8BAA6B,MAAK,WAC9C,mBACE,OAAO,CAAC,YAAY,OAAO,OAAO,SAAS,SAAS,QAAQ,EAAE,CAAC,EAC/D,IAAI,CAAC,YAAY;AAChB,gBAAM,SAAS,OAAO,OAAO,UAAU,QAAQ,EAAE,GAAG,QAAQ,IAAI,WAAW;AAC3E,gBAAM,SAAS,iBAAiB,OAAO,OAAO,SAAS,CAAC,OAAO,QAAQ;AAEvE,iBACE,gBAAAD;AAAA,YAAC;AAAA;AAAA,cAEC,MAAK;AAAA,cACL,MAAK;AAAA,cACL,iBAAe;AAAA,cACf,WAAW,QAAQ,gDAAgD;AAAA,cACnE,SAAS,MAAM,iBAAiB,QAAQ,EAAE;AAAA,cAEzC;AAAA,wBAAQ;AAAA,gBACR,SAAS,gBAAAC,MAAC,UAAK,WAAU,yBAAwB,eAAY,QAAO;AAAA;AAAA;AAAA,YARhE,QAAQ;AAAA,UASf;AAAA,QAEJ,CAAC,GACL;AAAA,QAEC,SACE,OAAO,CAAC,YAAY,OAAO,OAAO,SAAS,SAAS,QAAQ,EAAE,CAAC,EAC/D,OAAO,CAAC,aAAa,iBAAiB,OAAO,OAAO,SAAS,CAAC,OAAO,QAAQ,EAAE,EAC/E,IAAI,CAAC,YAAY;AAChB,gBAAM,UAAU,OAAO,OAAO,UAAU,QAAQ,EAAE;AAClD,gBAAM,SAAS,OAAO,SAAS,OAAO,CAAC,UAAU,MAAM,YAAY,QAAQ,EAAE;AAE7E,iBACE,gBAAAD,OAAC,aAAyB,WAAU,+BAClC;AAAA,4BAAAA,OAAC,YAAO,WAAU,sCAChB;AAAA,8BAAAC,MAAC,QAAG,WAAU,iCAAiC,kBAAQ,OAAM;AAAA,cAC5D,QAAQ,QAAQ,gBAAAA,MAAC,UAAK,WAAU,sBAAsB,kBAAQ,MAAK;AAAA,eACtE;AAAA,YAEC,OAAO,kBACN,gBAAAA,MAAC,OAAE,WAAU,sBAAsB,gBAAM,4BAA4B,GAAE,IAEzE,gBAAAD,OAAC,WAAM,WAAU,uBACf;AAAA,8BAAAC,MAAC,UAAK,WAAU,6BAA6B,gBAAM,kBAAkB,GAAE;AAAA,cACvE,gBAAAA,MAAC,UAAK,WAAU,sBAAsB,gBAAM,sBAAsB,GAAE;AAAA,cACpE,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO,SAAS,WAAW;AAAA,kBAC3B,UAAU,CAAC,UAAU,OAAO,cAAc,QAAQ,IAAI,EAAE,SAAS,MAAM,OAAO,MAAM,CAAC;AAAA,kBACrF,UAAU,CAAC,UAAU,eAAe,WAAW,MAAM,cAAc,cAAc;AAAA,kBACjF,SAAS,MAAM,iBAAiB,QAAQ,EAAE;AAAA;AAAA,cAC5C;AAAA,eACF;AAAA,YAGA,gBAAAD,OAAC,WAAM,WAAU,uBACf;AAAA,8BAAAC,MAAC,UAAK,WAAU,6BAA6B,gBAAM,eAAe,GAAE;AAAA,cAInE,QAAQ,OAAO,WAAW,WAAW,SAAS,QAAQ,EAAE,IACvD,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO,SAAS,QAAQ;AAAA,kBACxB,UAAU,CAAC,SAAS,OAAO,cAAc,QAAQ,IAAI,EAAE,MAAM,KAAK,CAAC;AAAA,kBACnE,UAAU,CAAC,gBAAgB,eAAe,QAAQ,WAAW;AAAA,kBAC7D,SAAS,MAAM,iBAAiB,QAAQ,EAAE;AAAA,kBACzC,GAAI,qBAAqB,CAAC,OAAO,kBAC9B,EAAE,UAAU,kBAAkB,SAAS,QAAQ,EAAE,EAAE,SAAS,IAC5D,CAAC;AAAA;AAAA,cACP,IAEA,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO,SAAS,QAAQ;AAAA,kBACxB,UAAU,CAAC,SAAS,OAAO,cAAc,QAAQ,IAAI,EAAE,MAAM,KAAK,CAAC;AAAA,kBACnE,UAAU,CAAC,gBAAgB,eAAe,QAAQ,WAAW;AAAA,kBAC7D,SAAS,MAAM,iBAAiB,QAAQ,EAAE;AAAA,kBAC1C,SAAS;AAAA;AAAA,cACX;AAAA,eAEJ;AAAA,YAIC,OAAO,mBAAmB,OAAO,sBAAsB,CAAC,OAAO,mBAAmB,UACjF,gBAAAD,OAAC,QAAG,WAAU,8BAA6B,MAAK,SAC7C;AAAA,qBAAO,mBAAmB,QAAQ,SAAS,KAC1C,gBAAAA,OAAC,QAAG,WAAU,kEACX;AAAA,sBAAM,0BAA0B;AAAA,gBAAG;AAAA,gBACnC,OAAO,mBAAmB,QAAQ,IAAI,CAAC,SAAS,KAAK,IAAI,IAAI,EAAE,KAAK,IAAI;AAAA,iBAC3E;AAAA,cAED,OAAO,mBAAmB,OAAO,SAAS,KACzC,gBAAAA,OAAC,QAAG,WAAU,kEACX;AAAA,sBAAM,yBAAyB;AAAA,gBAAG;AAAA,gBAClC,OAAO,mBAAmB,OACxB,IAAI,CAAC,SAAS,MAAM,2BAA2B,IAAI,EAAE,CAAC,EACtD,KAAK,IAAI;AAAA,iBACd;AAAA,eAEJ;AAAA,YAID,sBAAsB;AAAA,cACrB,SAAS,QAAQ;AAAA,cACjB,OAAO,SAAS,wBAAwB;AAAA,cACxC,UAAU,CAAC,UAAU,OAAO,cAAc,QAAQ,IAAI,EAAE,sBAAsB,MAAM,CAAC;AAAA,YACvF,CAAC;AAAA,YAEA,OAAO,SAAS,KACf,gBAAAA,OAAC,SAAI,WAAU,0BACb;AAAA,8BAAAC,MAAC,OAAE,WAAU,+BAA+B,gBAAM,uBAAuB,GAAE;AAAA,cAC3E,gBAAAA,MAAC,SAAI,WAAU,gCACZ,iBAAO,IAAI,CAAC,UACX,gBAAAD,OAAC,YAAkD,WAAU,yBAC3D;AAAA,gCAAAA,OAAC,gBAAW,WAAU,sBACnB;AAAA,wBAAM,qBAAqB,MAAM,QAAQ,EAAE;AAAA,kBAAE;AAAA,kBAAI,MAAM;AAAA,kBAAM;AAAA,mBAChE;AAAA,gBACA,gBAAAC;AAAA,kBAAC;AAAA;AAAA,oBACC,WAAU;AAAA,oBACV,OAAO,EAAE,uBAAuB,GAAG,MAAM,KAAK,KAAK;AAAA,oBAKnD,0BAAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,SAAS,MAAM;AAAA,wBACf,UAAU,MAAM;AAAA,wBAChB,UAAU,MAAM;AAAA,wBACf,GAAI,MAAM,YAAY,WAAW,OAAO,wBAAwB,SAC7D,EAAE,WAAW,OAAO,oBAAoB,IACxC,MAAM,YAAY,WAChB,CAAC,OAAO,mBACR,WAAW,SAAS,QAAQ,EAAE,IAC9B,EAAE,WAAW,SAAS,QAAQ,GAAG,IACjC,CAAC;AAAA,wBACP,QAAQ;AAAA,0BACN,IAAI,MAAM,YAAY;AAAA,0BACtB,KAAK,MAAM,aAAa;AAAA,0BACxB,SAAS,MAAM,iBAAiB;AAAA,0BAChC,MAAM,MAAM,cAAc;AAAA,0BAC1B,SAAS,MAAM,iBAAiB;AAAA,0BAChC,SAAS,MAAM,iBAAiB;AAAA,0BAChC,QAAQ,MAAM,gBAAgB;AAAA,0BAC9B,eAAe,MAAM,uBAAuB;AAAA,0BAC5C,aAAa,MAAM,qBAAqB;AAAA,0BACxC,QAAQ,MAAM,gBAAgB;AAAA,0BAC9B,OAAO,MAAM,eAAe;AAAA,0BAC5B,SAAS,MAAM,iBAAiB;AAAA,0BAChC,OAAO,MAAM,eAAe;AAAA,0BAC5B,SAAS,MAAM,iBAAiB;AAAA,0BAChC,UAAU,MAAM,kBAAkB;AAAA,wBACpC;AAAA,wBACC,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA;AAAA,oBACtC;AAAA;AAAA,gBACF;AAAA,gBACC,MAAM,SAAS,YACb,OAAO,CAAC,eAAe,WAAW,QAAQ,EAC1C,IAAI,CAAC,eACJ,gBAAAD,OAAC,OAAyB,WAAU,iCACjC;AAAA,wBAAM,uBAAuB,WAAW,KAAK,EAAE;AAAA,kBAAE;AAAA,kBAAE,WAAW;AAAA,kBAAO;AAAA,kBACrE,WAAW;AAAA,qBAFN,WAAW,KAGnB,CACD;AAAA,mBAjDQ,GAAG,MAAM,OAAO,IAAI,MAAM,QAAQ,EAkD/C,CACD,GACH;AAAA,eACF;AAAA,eArIU,QAAQ,EAuItB;AAAA,QAEJ,CAAC;AAAA,QAEF,OAAO,SAAS,gBAAAC,MAAC,OAAE,WAAU,uBAAuB,iBAAO,OAAM;AAAA,QAElE,gBAAAD,OAAC,SAAI,WAAU,yBACb;AAAA,0BAAAC,MAAC,YAAO,MAAK,UAAS,SAAS,OAAO,MAAM,UAAU,CAAC,OAAO,WAAW,CAAC,OAAO,WAAW,OAAO,UAChG,iBAAO,WAAW,MAAM,iBAAiB,IAAI,MAAM,eAAe,GACrE;AAAA,UAEC,CAAC,OAAO,WAAW,gBAAAA,MAAC,UAAK,WAAU,sBAAsB,gBAAM,oBAAoB,GAAE;AAAA,WACxF;AAAA,SACF,GAEJ;AAAA,OAEF;AAAA,KAEF;AAEJ;","names":["clsx","clsx","jsx","jsxs","clsx","jsx","jsxs","clsx","clsx","jsx","jsxs","clsx","jsx","jsxs","Trash2","useState","jsx","jsxs","useRef","useState","useState","jsx","jsxs","useState","jsx","jsxs","useRef","useState","jsx","jsxs","Fragment","jsx","jsxs","useState","jsxs","jsx","Trash2","Fragment"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adatechnology/notification-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Notification UI — headless hooks + componentes de inbox, sino e preferências",
|
|
6
6
|
"publishConfig": {
|
|
@@ -26,8 +26,9 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"clsx": "^2.1.1",
|
|
28
28
|
"lucide-react": "^1.21.0",
|
|
29
|
-
"@adatechnology/
|
|
30
|
-
"@adatechnology/notification-
|
|
29
|
+
"@adatechnology/conversations-ui": "0.14.0",
|
|
30
|
+
"@adatechnology/notification-client": "0.3.0",
|
|
31
|
+
"@adatechnology/notification-contracts": "0.4.0"
|
|
31
32
|
},
|
|
32
33
|
"peerDependencies": {
|
|
33
34
|
"@tanstack/react-query": "^5",
|