@fayz-ai/plugin-forms 0.9.1 → 0.9.2

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/html-text.ts","../src/components/FormRenderer.tsx","../src/lib/print.ts","../src/lib/agent-tools.ts","../src/lib/person-fields.ts"],"names":["t","optionLabel"],"mappings":"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","file":"chunk-RBLXIKWB.js","sourcesContent":["// ============================================================\n// HTML guardado num campo de formulário → texto legível\n// ============================================================\n//\n// Os campos `richtext` (e alguns `memo` vindos de importação) guardam HTML: o\n// conteúdo trazido do Feegow chega como `<p dir=\"ltr\"><b id=\"docs-internal-guid-\n// …\">Está triste, mas sabe que vai superar.&nbsp;</b></p>` — colado de um Google\n// Docs, com atributos e tudo.\n//\n// Isso dá dois jeitos ERRADOS de mostrar, e o produto já teve os dois:\n//\n// • escapar e imprimir → a pessoa lê `&lt;p dir=&quot;ltr&quot;&gt;` numa\n// ficha de atendimento. Era o que a impressão fazia.\n// • injetar como HTML → a marcação some da tela, mas o documento passa a poder\n// trazer <script>/<img onerror> de dentro do banco para dentro da página.\n// Consertar a primeira coisa caindo na segunda seria trocar um problema de\n// leitura por um de execução.\n//\n// O certo é o terceiro: extrair o TEXTO do HTML e escapar esse texto. Fica\n// legível e nada do que estava guardado é executado — o parser monta os nós, e\n// `textContent` nunca roda nenhum deles.\n\n/** Parece HTML? Uma tag de abertura ou fechamento basta. */\nexport function looksLikeHtml(value: string): boolean {\n return /<\\/?[a-z][^>]*>/i.test(value)\n}\n\n// Blocos viram quebra de linha ANTES de extrair o texto. `textContent` sozinho\n// cola os parágrafos — \"…17.07.26Está triste, mas sabe…\" — e numa evolução\n// clínica o parágrafo É a estrutura do que foi dito.\nconst BLOCKS = 'p, div, li, tr, h1, h2, h3, h4, h5, h6, blockquote, section, article'\n\n/** Espaço rígido (U+00A0): o parser decodifica `&nbsp;` para ele, mas ele não\n * quebra linha e o `trim()` não o remove. Vira espaço comum. */\nconst NBSP = / /g\n\nexport function htmlToPlainText(value: string): string {\n if (!value) return ''\n\n if (typeof document === 'undefined') {\n // Sem DOM (teste em node, render no servidor). Um \"parser\" de regex é uma\n // aproximação, e está assumido como tal: derruba as tags para não devolver\n // marcação, e não pretende estar certo para HTML arbitrário.\n return value\n .replace(/<br\\s*\\/?>/gi, '\\n')\n .replace(/<\\/(p|div|li|tr|h[1-6]|blockquote)>/gi, '\\n')\n .replace(/<[^>]*>/g, '')\n .replace(/&nbsp;/g, ' ')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n // `&amp;` por último: antes dos outros, ele transformaria `&amp;lt;` em\n // `<` — decodificando uma vez a mais do que o texto pedia.\n .replace(/&amp;/g, '&')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim()\n }\n\n const el = document.createElement('div')\n el.innerHTML = value\n for (const br of Array.from(el.querySelectorAll('br'))) {\n br.replaceWith('\\n')\n }\n for (const block of Array.from(el.querySelectorAll(BLOCKS))) {\n block.append('\\n')\n }\n\n return (el.textContent ?? '')\n .replace(NBSP, ' ')\n .replace(/[ \\t]+\\n/g, '\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim()\n}\n\n/** Texto legível de um campo longo, seja ele HTML guardado ou texto puro. */\nexport function fieldTextValue(value: unknown): string {\n if (typeof value !== 'string') return ''\n // Um memo digitado à mão passa intacto: converter tudo faria \"a < b virou c\"\n // perder o que vem depois do `<`.\n return looksLikeHtml(value) ? htmlToPlainText(value) : value\n}\n\n// ============================================================\n// Sanitização — mostrar a FORMATAÇÃO sem executar o documento\n// ============================================================\n//\n// Texto puro resolve a legibilidade e perde o resto: negrito, parágrafo, lista.\n// Numa evolução clínica colada do Docs, o negrito costuma ser o que a\n// terapeuta destacou, e a lista é a lista. Achatar tudo é jogar fora sentido\n// que estava lá.\n//\n// Então o HTML volta a ser HTML — mas passando por uma lista de permissão. O\n// que não está nela não é \"provavelmente inofensivo\": é removido. Isso é o\n// contrário de uma lista de proibições, que só protege do que alguém lembrou\n// de proibir.\n//\n// `DOMParser` com 'text/html' monta um documento INERTE: nenhum script roda,\n// nenhuma imagem é buscada, nenhum `onerror` dispara — nem durante a análise,\n// nem enquanto caminhamos pela árvore. É por isso que a limpeza acontece aqui e\n// não com regex sobre a string, que nunca dá conta de HTML malformado (e é\n// justamente com HTML malformado que se burla um filtro de regex).\n\n/** Some com o elemento E com o conteúdo dele. Desembrulhar um <script> jogaria\n * o código para dentro do texto visível. */\nconst DROP_WITH_CONTENT = new Set([\n 'script', 'style', 'iframe', 'object', 'embed', 'svg', 'math', 'link', 'meta',\n 'form', 'input', 'button', 'textarea', 'select', 'template', 'noscript',\n])\n\n/** Some com a TAG e mantém os filhos: um `<font>` ou um `<span>` desconhecido\n * não deve levar embora a frase que estava dentro dele. */\nconst ALLOWED_TAGS = new Set([\n 'p', 'br', 'hr', 'div', 'span',\n 'b', 'strong', 'i', 'em', 'u', 's', 'sub', 'sup', 'mark', 'small',\n 'ul', 'ol', 'li', 'blockquote', 'pre', 'code',\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'table', 'thead', 'tbody', 'tfoot', 'tr', 'td', 'th', 'caption',\n 'a',\n])\n\n/** Só o que é preciso para um link funcionar. `style`, `class`, `id` e todo\n * `on*` ficam de fora — o `id=\"docs-internal-guid-…\"` que vem do Google Docs\n * é lixo de origem, e `style` é caminho para `expression()`/`url(javascript:)`\n * em motores antigos. */\nconst ALLOWED_ATTRS: Record<string, Set<string>> = {\n a: new Set(['href', 'title']),\n td: new Set(['colspan', 'rowspan']),\n th: new Set(['colspan', 'rowspan']),\n}\n\nconst SAFE_HREF = /^(https?:|mailto:|tel:)/i\n\nfunction cleanElement(el: Element): void {\n // Percorre uma CÓPIA: remover/desembrulhar filhos mexe na lista viva.\n for (const child of Array.from(el.children)) {\n cleanElement(child)\n }\n\n const tag = el.tagName.toLowerCase()\n\n if (DROP_WITH_CONTENT.has(tag)) {\n el.remove()\n return\n }\n\n for (const attr of Array.from(el.attributes)) {\n const name = attr.name.toLowerCase()\n const allowed = ALLOWED_ATTRS[tag]?.has(name) ?? false\n if (!allowed) {\n el.removeAttribute(attr.name)\n continue\n }\n // `href=\"javascript:…\"` é o caso clássico de atributo permitido com valor\n // que não é.\n if (name === 'href' && !SAFE_HREF.test(attr.value.trim())) {\n el.removeAttribute(attr.name)\n }\n }\n\n if (!ALLOWED_TAGS.has(tag)) {\n el.replaceWith(...Array.from(el.childNodes))\n return\n }\n\n if (tag === 'a') {\n // Um <a> que perdeu o href (era `javascript:`) continuaria azul e\n // sublinhado, prometendo um destino que não existe. Vira o texto que é.\n if (!el.getAttribute('href')) {\n el.replaceWith(...Array.from(el.childNodes))\n return\n }\n el.setAttribute('target', '_blank')\n el.setAttribute('rel', 'noopener noreferrer nofollow')\n }\n}\n\n/**\n * HTML guardado → HTML seguro de renderizar.\n *\n * Sem DOMParser (node, SSR) devolve string vazia em vez de deixar passar: quem\n * chama tem o texto puro como alternativa, e \"não consegui limpar\" nunca pode\n * virar \"então mando cru\".\n */\nexport function sanitizeHtml(value: string): string {\n if (!value) return ''\n if (typeof DOMParser === 'undefined') return ''\n\n const doc = new DOMParser().parseFromString(value, 'text/html')\n for (const child of Array.from(doc.body.children)) {\n cleanElement(child)\n }\n return doc.body.innerHTML\n}\n\n/** O campo longo pronto para exibir: `html` quando dá para formatar com\n * segurança, `text` quando não (e o chamador escapa esse). */\nexport function fieldRichValue(value: unknown): { html: string } | { text: string } {\n if (typeof value !== 'string' || !value) return { text: '' }\n if (!looksLikeHtml(value)) return { text: value }\n const html = sanitizeHtml(value)\n return html ? { html } : { text: htmlToPlainText(value) }\n}\n","import React, { useCallback } from 'react'\nimport { Input } from '@fayz-ai/ui'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@fayz-ai/ui'\nimport { Badge } from '@fayz-ai/ui'\nimport { useTranslation } from '@fayz-ai/core'\nimport { fieldRichValue } from '../lib/html-text'\nimport type { FormFieldDef, FormSchema } from '../types'\n\n// O HTML sanitizado chega sem `class` nenhuma (a lista de permissão derruba\n// todas), então o espaçamento e os pesos vêm daqui, pelo seletor de filho. Sem\n// isto o Tailwind zera as margens de `<p>`/`<ul>` no preflight e os parágrafos\n// do documento voltam a se colar uns nos outros.\nconst RICH_TEXT_CLASS = [\n 'space-y-2',\n '[&_p]:leading-relaxed',\n '[&_b]:font-semibold [&_strong]:font-semibold',\n '[&_i]:italic [&_em]:italic',\n '[&_u]:underline',\n '[&_ul]:list-disc [&_ul]:pl-5 [&_ol]:list-decimal [&_ol]:pl-5 [&_li]:leading-relaxed',\n '[&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-3 [&_blockquote]:text-muted-foreground',\n '[&_a]:text-primary [&_a]:underline',\n '[&_h1]:font-semibold [&_h2]:font-semibold [&_h3]:font-semibold',\n '[&_table]:w-full [&_td]:border [&_td]:border-border [&_td]:px-2 [&_td]:py-1',\n '[&_th]:border [&_th]:border-border [&_th]:px-2 [&_th]:py-1 [&_th]:font-medium',\n].join(' ')\n\ninterface FormRendererProps {\n schema: FormSchema\n data: Record<string, unknown>\n onChange: (data: Record<string, unknown>) => void\n readOnly?: boolean\n}\n\n/**\n * Leitura é uma APRESENTAÇÃO, não um formulário travado.\n *\n * `readOnly` chegava no `<input readOnly>` e parava aí: caixa, borda, cursor de\n * texto, radio marcado — pixel por pixel a mesma tela de preencher. Abrir uma\n * anamnese de fevereiro parecia estar editando a anamnese de fevereiro, e a\n * única pista do contrário era o campo não aceitar digitação. Aqui o valor vira\n * texto e some a moldura: dá para ler de cima a baixo sem confundir com um\n * rascunho aberto.\n */\nfunction ReadField({ label, children }: { label?: string; children: React.ReactNode }) {\n return (\n <div className=\"space-y-0.5\">\n {label && <p className=\"text-xs font-medium text-muted-foreground\">{label}</p>}\n <div className=\"text-sm text-foreground\">{children}</div>\n </div>\n )\n}\n\nfunction EmptyValue() {\n return <span className=\"text-muted-foreground/50\">—</span>\n}\n\n/** O rótulo escolhido, não o valor cru: um documento que mostra \"prefer_not_say\"\n * faz a pessoa traduzir de cabeça o que a tela já sabia dizer. */\nfunction optionLabel(field: FormFieldDef, value: unknown): string | null {\n if (value == null || value === '') return null\n const match = (field.options ?? []).find((o) => o.value === value)\n return match?.label ?? String(value)\n}\n\nfunction ReadValue({ field, value }: { field: FormFieldDef; value: unknown }) {\n switch (field.type) {\n case 'memo':\n case 'richtext': {\n // Formatação preservada, documento não executado: o valor passa pela\n // lista de permissão de lib/html-text.ts e volta como HTML seguro. O\n // negrito que a terapeuta aplicou continua negrito; o\n // `id=\"docs-internal-guid-…\"` que veio junto do Google Docs não sobrevive.\n //\n // Sem tag nenhuma (memo digitado à mão) é texto puro mesmo, com as\n // quebras respeitadas pelo `whitespace-pre-wrap`.\n const rich = fieldRichValue(value)\n return (\n <ReadField label={field.label}>\n {'html' in rich ? (\n <div className={RICH_TEXT_CLASS} dangerouslySetInnerHTML={{ __html: rich.html }} />\n ) : rich.text ? (\n <p className=\"whitespace-pre-wrap\">{rich.text}</p>\n ) : (\n <EmptyValue />\n )}\n </ReadField>\n )\n }\n\n case 'date': {\n const raw = typeof value === 'string' ? value : ''\n const date = raw ? new Date(raw) : null\n const text = date && !Number.isNaN(date.getTime())\n // `T00:00` faz o Date nascer em UTC e o fuso do Brasil o joga para o dia\n // anterior — daí o corte manual em vez de toLocaleDateString direto.\n ? raw.slice(0, 10).split('-').reverse().join('/')\n : raw\n return <ReadField label={field.label}>{text || <EmptyValue />}</ReadField>\n }\n\n case 'select':\n case 'radio': {\n const label = optionLabel(field, value)\n return <ReadField label={field.label}>{label ?? <EmptyValue />}</ReadField>\n }\n\n case 'tags': {\n const selected = Array.isArray(value) ? (value as string[]) : []\n return (\n <ReadField label={field.label}>\n {selected.length > 0 ? (\n <div className=\"flex flex-wrap gap-1.5\">\n {selected.map((v) => (\n <Badge key={v} variant=\"secondary\" className=\"text-xs\">\n {optionLabel(field, v) ?? v}\n </Badge>\n ))}\n </div>\n ) : (\n <EmptyValue />\n )}\n </ReadField>\n )\n }\n\n case 'checkbox':\n // Sem rótulo próprio: o texto do checkbox JÁ é a pergunta (\"Autoriza uso\n // de imagem\"), então repeti-lo acima da resposta diria duas vezes a mesma\n // coisa.\n return (\n <ReadField>\n <span className=\"font-medium\">{field.label}</span>\n <span className=\"text-muted-foreground\"> · </span>\n <span>{value ? 'Sim' : 'Não'}</span>\n </ReadField>\n )\n\n default: {\n const text = value == null || value === '' ? null : String(value)\n return <ReadField label={field.label}>{text ?? <EmptyValue />}</ReadField>\n }\n }\n}\n\nfunction FieldRenderer({\n field,\n value,\n onChange,\n readOnly,\n}: {\n field: FormFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly?: boolean\n}) {\n const t = useTranslation()\n\n // Título e os blocos ainda não implementados continuam iguais nos dois modos:\n // um é estrutura do documento, os outros não têm valor para apresentar.\n if (readOnly && field.type !== 'title' && field.type !== 'image' && field.type !== 'gallery' && field.type !== 'budget') {\n return <ReadValue field={field} value={value} />\n }\n\n switch (field.type) {\n case 'title':\n return (\n <h3 className=\"text-base font-semibold pt-2 pb-1 border-b\">\n {field.label}\n </h3>\n )\n\n case 'text':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <Input\n value={(value as string) ?? ''}\n onChange={(e) => onChange(e.target.value)}\n placeholder={field.placeholder}\n className=\"h-9 text-sm\"\n readOnly={readOnly}\n />\n </div>\n )\n\n case 'memo':\n case 'richtext':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <textarea\n value={(value as string) ?? ''}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => onChange(e.target.value)}\n placeholder={field.placeholder}\n className=\"flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 min-h-[100px]\"\n readOnly={readOnly}\n />\n </div>\n )\n\n case 'date':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <Input\n type=\"date\"\n value={(value as string) ?? ''}\n onChange={(e) => onChange(e.target.value)}\n className=\"h-9 text-sm\"\n readOnly={readOnly}\n />\n </div>\n )\n\n case 'select':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n {readOnly ? (\n <p className=\"text-sm py-1\">{(value as string) ?? '-'}</p>\n ) : (\n <Select value={(value as string) ?? ''} onValueChange={onChange}>\n <SelectTrigger className=\"h-9 text-sm\">\n <SelectValue placeholder={field.placeholder ?? '...'} />\n </SelectTrigger>\n <SelectContent>\n {(field.options ?? []).map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n </div>\n )\n\n case 'radio':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <div className=\"space-y-1\">\n {(field.options ?? []).map((opt) => (\n <label key={opt.value} className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"radio\"\n name={field.id}\n value={opt.value}\n checked={value === opt.value}\n onChange={() => onChange(opt.value)}\n disabled={readOnly}\n className=\"text-primary\"\n />\n <span className=\"text-sm\">{opt.label}</span>\n </label>\n ))}\n </div>\n </div>\n )\n\n case 'tags': {\n const selectedTags = Array.isArray(value) ? (value as string[]) : []\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <div className=\"flex flex-wrap gap-1.5\">\n {(field.options ?? []).map((opt) => {\n const active = selectedTags.includes(opt.value)\n return (\n <Badge\n key={opt.value}\n variant={active ? 'default' : 'outline'}\n className={`cursor-pointer text-xs ${readOnly ? 'pointer-events-none' : ''}`}\n onClick={() => {\n if (readOnly) return\n onChange(\n active\n ? selectedTags.filter((t) => t !== opt.value)\n : [...selectedTags, opt.value],\n )\n }}\n >\n {opt.label}\n </Badge>\n )\n })}\n </div>\n </div>\n )\n }\n\n case 'checkbox':\n return (\n <label className=\"flex items-center gap-2 cursor-pointer py-1\">\n <input\n type=\"checkbox\"\n checked={!!value}\n onChange={(e) => onChange(e.target.checked)}\n disabled={readOnly}\n className=\"rounded border-input\"\n />\n <span className=\"text-sm font-medium\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </span>\n </label>\n )\n\n case 'image':\n case 'gallery':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <div className=\"flex items-center justify-center rounded-lg border-2 border-dashed py-8 text-sm text-muted-foreground\">\n {field.type === 'gallery' ? 'Gallery upload' : 'Image upload'} — v2\n </div>\n </div>\n )\n\n case 'budget':\n return (\n <div className=\"space-y-1.5\">\n <label className=\"text-xs font-medium block\">\n {field.label}\n {field.required && <span className=\"text-destructive ml-0.5\">*</span>}\n </label>\n <div className=\"flex items-center justify-center rounded-lg border-2 border-dashed py-8 text-sm text-muted-foreground\">\n Budget / line items — v2\n </div>\n </div>\n )\n\n default:\n return null\n }\n}\n\nexport function FormRenderer({ schema, data, onChange, readOnly }: FormRendererProps) {\n const sortedFields = [...schema.fields].sort((a, b) => a.row - b.row || a.col - b.col)\n\n const handleFieldChange = useCallback(\n (fieldId: string, value: unknown) => {\n onChange({ ...data, [fieldId]: value })\n },\n [data, onChange],\n )\n\n return (\n <div\n className=\"grid gap-x-4 gap-y-3\"\n style={{ gridTemplateColumns: 'repeat(12, 1fr)' }}\n >\n {sortedFields.map((field) => (\n <div key={field.id} style={{ gridColumn: `span ${field.colSpan}` }}>\n <FieldRenderer\n field={field}\n value={data[field.id]}\n onChange={(v) => handleFieldChange(field.id, v)}\n readOnly={readOnly}\n />\n </div>\n ))}\n </div>\n )\n}\n","// ============================================================\n// PRINT / PDF — render a filled document to a printable A4 page\n// ============================================================\n//\n// Browser print-to-PDF: we build a clean, self-contained A4 HTML document from\n// the template schema + saved data, drop it into a hidden iframe, and call\n// print() on it. The browser's print dialog covers both physical printing and\n// \"Save as PDF\". No external deps.\n\nimport type { FormDocument, FormFieldDef, FormTemplate } from '../types'\nimport { fieldRichValue } from './html-text'\n\nfunction esc(value: unknown): string {\n return String(value ?? '').replace(/[&<>\"']/g, (c) =>\n ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c] as string),\n )\n}\n\nfunction nl2br(value: string): string {\n return esc(value).replace(/\\r?\\n/g, '<br/>')\n}\n\nfunction formatDate(value: string): string {\n // ISO date (YYYY-MM-DD) → locale date; anything else passes through.\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(value)\n if (!m) return esc(value)\n return `${m[3]}/${m[2]}/${m[1]}`\n}\n\nfunction optionLabel(field: FormFieldDef, value: unknown): string {\n const opt = (field.options ?? []).find((o) => o.value === value)\n return esc(opt ? opt.label : value)\n}\n\n/** Render one field's value as an HTML fragment for the printed page. */\nfunction renderValue(field: FormFieldDef, value: unknown): string {\n const empty = '<span class=\"empty\">—</span>'\n switch (field.type) {\n case 'memo':\n case 'richtext': {\n // Texto primeiro, escape depois. `nl2br` já escapava — e era exatamente\n // por isso que a folha impressa saía com `&lt;p dir=&quot;ltr&quot;&gt;`\n // no lugar da evolução do atendimento: escapar HTML guardado mostra a\n // marcação. Ver lib/html-text.ts.\n // Agora o valor passa pela lista de permissão e a folha sai formatada,\n // igual à tela. O escape continua no caminho de texto puro, que é onde\n // ele sempre foi o certo.\n const rich = fieldRichValue(value)\n if ('html' in rich) return `<div class=\"long rich\">${rich.html}</div>`\n return rich.text ? `<div class=\"long\">${nl2br(rich.text)}</div>` : empty\n }\n case 'date':\n return value ? formatDate(String(value)) : empty\n case 'select':\n case 'radio':\n return value ? optionLabel(field, value) : empty\n case 'tags': {\n const arr = Array.isArray(value) ? value : []\n return arr.length\n ? arr.map((v) => optionLabel(field, v)).join(', ')\n : empty\n }\n case 'checkbox':\n return value ? 'Sim' : 'Não'\n case 'image':\n case 'gallery':\n case 'budget':\n return '' // not meaningful on a printed contract\n default:\n return value ? esc(value) : empty\n }\n}\n\nexport interface BuildPrintOptions {\n /** Heading shown at the top of the page (defaults to the document title). */\n heading?: string\n /** Small line under the heading (e.g. person name). */\n subheading?: string\n}\n\n/** Build a full, self-contained printable HTML document. */\nexport function buildPrintHtml(\n template: FormTemplate,\n doc: FormDocument,\n opts: BuildPrintOptions = {},\n): string {\n const heading = opts.heading ?? doc.title ?? template.name\n const subParts = [opts.subheading ?? doc.personName, new Date(doc.createdAt).toLocaleDateString()]\n .filter(Boolean)\n .map((s) => esc(s))\n .join(' &middot; ')\n\n const fields = [...template.schema.fields].sort((a, b) => a.row - b.row || a.col - b.col)\n\n const clampSpan = (n: unknown) => Math.max(1, Math.min(12, Number(n) || 12))\n\n // Mirror the builder's 12-column grid so the print keeps the authored layout\n // (side-by-side fields stay side by side). Titles span the full row.\n const body = fields\n .map((field) => {\n if (field.type === 'title') {\n return `<h2 class=\"section\" style=\"grid-column: 1 / -1\">${esc(field.label)}</h2>`\n }\n const rendered = renderValue(field, doc.data[field.id])\n if (rendered === '') return ''\n const isLong = field.type === 'memo' || field.type === 'richtext'\n return `<div class=\"field${isLong ? ' field--long' : ''}\" style=\"grid-column: span ${clampSpan(field.colSpan)}\">\n <div class=\"label\">${esc(field.label)}</div>\n <div class=\"value\">${rendered}</div>\n </div>`\n })\n .join('\\n')\n\n return `<!doctype html>\n<html lang=\"pt-BR\">\n<head>\n<meta charset=\"utf-8\"/>\n<title>${esc(heading)}</title>\n<style>\n @page { size: A4; margin: 20mm; }\n * { box-sizing: border-box; }\n html, body { margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n color: #111; font-size: 12pt; line-height: 1.5;\n -webkit-print-color-adjust: exact; print-color-adjust: exact;\n }\n .page { max-width: 170mm; margin: 0 auto; padding: 12mm 0; }\n header { border-bottom: 2px solid #111; padding-bottom: 8px; margin-bottom: 20px; }\n header h1 { font-size: 18pt; margin: 0 0 2px; }\n header .sub { font-size: 10pt; color: #555; }\n /* 12-column grid — mirrors the builder Preview (FormRenderer) so the print\n keeps the authored column layout. */\n .grid { display: grid; grid-template-columns: repeat(12, 1fr); column-gap: 16px; row-gap: 12px; align-items: start; }\n h2.section { font-size: 13pt; margin: 22px 0 4px; padding-bottom: 3px; border-bottom: 1px solid #ccc; }\n .grid > h2.section:first-child { margin-top: 4px; }\n .field { margin: 0; min-width: 0; }\n .field .label { font-size: 9pt; text-transform: uppercase; letter-spacing: .04em; color: #666; margin-bottom: 2px; }\n .field .value { font-size: 12pt; }\n .field--long .value .long { white-space: normal; text-align: justify; }\n /* Conteudo formatado (sanitizado em lib/html-text.ts). O HTML chega sem\n class nenhuma, entao o estilo vem por tag. orphans/widows evitam que um\n paragrafo deixe uma linha solta virando a pagina. */\n .long.rich p { margin: 0 0 8px; orphans: 2; widows: 2; }\n .long.rich p:last-child { margin-bottom: 0; }\n .long.rich ul, .long.rich ol { margin: 0 0 8px; padding-left: 20px; }\n .long.rich li { margin: 0 0 3px; }\n .long.rich b, .long.rich strong { font-weight: 600; }\n .long.rich blockquote { margin: 0 0 8px; padding-left: 10px; border-left: 2px solid #ccc; color: #444; }\n .long.rich a { color: #111; text-decoration: underline; }\n .long.rich table { width: 100%; border-collapse: collapse; margin: 0 0 8px; }\n .long.rich td, .long.rich th { border: 1px solid #ccc; padding: 4px 6px; text-align: left; }\n .long.rich h1, .long.rich h2, .long.rich h3,\n .long.rich h4, .long.rich h5, .long.rich h6 { font-size: 12pt; font-weight: 600; margin: 10px 0 4px; }\n .empty { color: #bbb; }\n footer { margin-top: 40px; font-size: 9pt; color: #888; text-align: center; }\n @media screen { body { background: #f3f3f3; } .page { background: #fff; max-width: 210mm; min-height: 297mm; padding: 20mm; box-shadow: 0 1px 8px rgba(0,0,0,.15); } }\n</style>\n</head>\n<body>\n <div class=\"page\">\n <header>\n <h1>${esc(heading)}</h1>\n ${subParts ? `<div class=\"sub\">${subParts}</div>` : ''}\n </header>\n <div class=\"grid\">\n ${body}\n </div>\n </div>\n</body>\n</html>`\n}\n\n/**\n * Print a prebuilt HTML document via a hidden iframe (popup-blocker safe).\n * The browser print dialog handles both printing and \"Save as PDF\".\n */\nexport function printHtml(html: string): void {\n if (typeof document === 'undefined') return\n const iframe = document.createElement('iframe')\n iframe.setAttribute('aria-hidden', 'true')\n iframe.style.position = 'fixed'\n iframe.style.right = '0'\n iframe.style.bottom = '0'\n iframe.style.width = '0'\n iframe.style.height = '0'\n iframe.style.border = '0'\n document.body.appendChild(iframe)\n\n const cleanup = () => {\n // Give the print dialog a beat before tearing the frame down.\n setTimeout(() => {\n if (iframe.parentNode) iframe.parentNode.removeChild(iframe)\n }, 1000)\n }\n\n const win = iframe.contentWindow\n const idoc = iframe.contentDocument || win?.document\n if (!win || !idoc) {\n cleanup()\n return\n }\n\n idoc.open()\n idoc.write(html)\n idoc.close()\n\n const doPrint = () => {\n try {\n win.focus()\n win.print()\n } finally {\n cleanup()\n }\n }\n\n // Wait for the frame document to be ready before printing.\n if (idoc.readyState === 'complete') {\n setTimeout(doPrint, 50)\n } else {\n iframe.addEventListener('load', () => setTimeout(doPrint, 50), { once: true })\n }\n}\n\n/** Convenience: build + print a document in one call. */\nexport function printDocument(\n template: FormTemplate,\n doc: FormDocument,\n opts?: BuildPrintOptions,\n): void {\n printHtml(buildPrintHtml(template, doc, opts))\n}\n","import type { PluginAITool } from '@fayz-ai/core'\n\n/**\n * The assistant's form-building tool. It is a SERVER-PLANE write (a pool RPC),\n * not a client-side surface mutation — so it works from any page and any\n * channel (in-app FAB, WhatsApp, MCP), and persists straight to the tenant's\n * form templates. This is the same pattern agenda/financial/marketing use.\n *\n * The builder surface (see FormBuilder) still publishes CONTEXT — which form is\n * open and its current fields with ids — so \"add an allergies field to THIS\n * form\" resolves to the right template. But the action itself is this tool.\n */\n\nconst CATEGORY_ENUM = ['anamnesis', 'evolution', 'report', 'contract', 'general'] as const\n\nconst FIELD_SHAPE =\n 'A field object: { type, label, required?, placeholder?, options?[] }. ' +\n 'type ∈ title|text|memo|richtext|date|select|radio|tags|checkbox|image|gallery|budget ' +\n '(title = section heading, no input). options are plain strings, only for select/radio/tags.'\n\nexport const createOrUpdateFormTool: PluginAITool = {\n id: 'custom_forms.createOrUpdateForm',\n name: 'createOrUpdateForm',\n description:\n 'Creates or edits a form template (anamnese, contrato, ficha…). Persisted server-side, so it works from ANY page — the user does NOT need the form builder open. ' +\n 'Omit templateId to CREATE (name required); pass templateId to EDIT an existing form. ' +\n 'Send the FULL desired field list in `fields` (replaces all fields), or `append_fields` to add to what already exists. ' +\n 'Layout is automatic — never send positions. Understand the intent and propose a sensible field set in one call rather than asking field by field. The user confirms before it is saved.',\n icon: 'FileText',\n mode: 'persist',\n limitKey: 'form_templates',\n permission: { feature: 'custom_forms', action: 'create' },\n execution: { plane: 'server', kind: 'rpc', rpc: 'agent_forms_upsert_template' },\n category: 'Forms',\n suggestions: [\n { label: 'Monte um formulário de anamnese' },\n { label: 'Adicione um campo de alergias neste formulário' },\n ],\n parameters: {\n type: 'object',\n properties: {\n templateId: {\n type: 'string',\n description: 'Existing form id to EDIT (from context or listFormTemplates). Omit to create a new form.',\n },\n name: { type: 'string', description: 'Form name — required when creating.' },\n category: {\n type: 'string',\n enum: [...CATEGORY_ENUM],\n description: 'anamnesis | evolution | report | contract | general',\n },\n description: { type: 'string', description: 'Optional short description of the form.' },\n fields: {\n type: 'array',\n description: `The FULL desired field list — REPLACES every existing field. Each item: ${FIELD_SHAPE}`,\n items: { type: 'object', description: FIELD_SHAPE },\n },\n append_fields: {\n type: 'array',\n description: `Fields to ADD to the existing form, keeping current ones. Use this for incremental edits instead of \\`fields\\`. Each item: ${FIELD_SHAPE}`,\n items: { type: 'object', description: FIELD_SHAPE },\n },\n },\n },\n}\n\nexport const FORM_BUILDER_INSTRUCTIONS = [\n 'Você está na tela do CONSTRUTOR DE FORMULÁRIOS. Para montar ou editar formulários use a tool createOrUpdateForm (ela persiste no backend e funciona mesmo fora desta tela).',\n 'O formulário aberto agora — id, nome, categoria e campos com seus ids — está no JSON da tela em contexto.',\n 'Para EDITAR este formulário, passe o templateId do contexto. Para adicionar campos mantendo os atuais, use append_fields; para redefinir tudo, use fields com a lista completa.',\n 'Ao criar do zero: entenda a intenção e proponha um conjunto de campos enxuto numa única chamada (não pergunte campo a campo). Depois confirme em uma frase o que foi montado.',\n 'Tipos de campo: title (cabeçalho de seção, sem input), text, memo (multilinha), richtext, date, select, radio, tags, checkbox, image, gallery, budget. Layout é automático.',\n].join(' ')\n","// ============================================================\n// PERSON FIELD MAPPING — prefill a document from a person record\n// ============================================================\n//\n// A template field can declare `map: '<personKey>'` (see FormFieldDef.map).\n// When a document is created from a person's profile, fields with a mapping are\n// pre-filled from that person's record. The person record reaching the widget\n// is the host app's CRUD detail `item`, keyed by the entity's field keys\n// (camelCase, e.g. `documentNumber`). We resolve tolerantly so the same mapping\n// works whether the host exposes camelCase or snake_case keys.\n\nimport type { FormSchema } from '../types'\n\n/** Curated, vertical-agnostic person keys offered in the field builder. */\nexport const PERSON_FIELD_OPTIONS: Array<{ value: string; labelKey: string }> = [\n { value: 'name', labelKey: 'customForms.personField.name' },\n { value: 'documentNumber', labelKey: 'customForms.personField.documentNumber' },\n { value: 'email', labelKey: 'customForms.personField.email' },\n { value: 'phone', labelKey: 'customForms.personField.phone' },\n { value: 'dateOfBirth', labelKey: 'customForms.personField.dateOfBirth' },\n { value: 'guardianName', labelKey: 'customForms.personField.guardianName' },\n { value: 'address', labelKey: 'customForms.personField.address' },\n { value: 'city', labelKey: 'customForms.personField.city' },\n { value: 'state', labelKey: 'customForms.personField.state' },\n]\n\nconst toSnake = (k: string) => k.replace(/[A-Z]/g, (m) => '_' + m.toLowerCase())\nconst toCamel = (k: string) => k.replace(/_([a-z])/g, (_, c: string) => c.toUpperCase())\n\n/** Read a person field value, tolerating camelCase/snake_case key variants. */\nexport function resolvePersonValue(\n person: Record<string, unknown> | undefined | null,\n mapKey: string | undefined,\n): unknown {\n if (!person || !mapKey) return undefined\n for (const key of [mapKey, toSnake(mapKey), toCamel(mapKey)]) {\n const v = person[key]\n if (v != null && v !== '') return v\n }\n return undefined\n}\n\n/**\n * Build the initial document data for a template. For each field, applies (in\n * priority order) an existing value, then the mapped person value, then the\n * field's static `defaultValue`. Never overwrites a value already present in\n * `existing`.\n */\nexport function prefillFromPerson(\n schema: FormSchema | undefined,\n person: Record<string, unknown> | undefined | null,\n existing: Record<string, unknown> = {},\n): Record<string, unknown> {\n const data: Record<string, unknown> = { ...existing }\n if (!schema) return data\n for (const field of schema.fields) {\n const current = data[field.id]\n if (current != null && current !== '') continue\n const mapped = field.map ? resolvePersonValue(person, field.map) : undefined\n if (mapped != null) {\n data[field.id] = mapped\n } else if (field.defaultValue != null) {\n data[field.id] = field.defaultValue\n }\n }\n return data\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"DocumentFormDialog.d.ts","sourceRoot":"","sources":["../../src/components/DocumentFormDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAA;AAK/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAW1D,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;IAC7B,gBAAgB,CAAC,EAAE,YAAY,CAAA;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,QAAQ,EAAE,uBAAuB,CAAA;IACjC,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EAAE,eAAe,EACzB,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,MAAM,EACN,QAAQ,EACR,KAAK,EACL,OAAO,EACP,MAAM,GACP,EAAE,uBAAuB,qBAiHzB"}
1
+ {"version":3,"file":"DocumentFormDialog.d.ts","sourceRoot":"","sources":["../../src/components/DocumentFormDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAA;AAK/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAY1D,UAAU,uBAAuB;IAC/B,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;IAC7B,gBAAgB,CAAC,EAAE,YAAY,CAAA;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,QAAQ,EAAE,uBAAuB,CAAA;IACjC,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AAED,wBAAgB,kBAAkB,CAAC,EACjC,QAAQ,EAAE,eAAe,EACzB,gBAAgB,EAChB,QAAQ,EACR,UAAU,EACV,MAAM,EACN,QAAQ,EACR,KAAK,EACL,OAAO,EACP,MAAM,GACP,EAAE,uBAAuB,qBAyIzB"}
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ /**
3
+ * O corpo do documento enquanto o modelo não chegou.
4
+ *
5
+ * Um spinner centralizado diz "espere" e nada mais: a área inteira colapsa numa
6
+ * bolinha e, quando o modelo chega, a tela salta de 40px para uma página de
7
+ * formulário. O esqueleto ocupa desde já a forma que vai ser preenchida — moldura,
8
+ * rótulo, campo — então a chegada do conteúdo troca cinza por texto no lugar onde
9
+ * o texto já estava.
10
+ *
11
+ * `rows` é uma aproximação e não tem como não ser: quantos campos o modelo tem é
12
+ * justamente o que ainda está sendo carregado. Cinco é a altura de formulário
13
+ * curto — erra para baixo de propósito, porque crescer ao carregar incomoda
14
+ * menos do que encolher.
15
+ */
16
+ export declare function DocumentBodySkeleton({ rows }: {
17
+ rows?: number;
18
+ }): React.JSX.Element;
19
+ /** O cabeçalho, para quando nem o título do documento se sabe ainda. */
20
+ export declare function DocumentHeaderSkeleton(): React.JSX.Element;
21
+ //# sourceMappingURL=DocumentSkeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocumentSkeleton.d.ts","sourceRoot":"","sources":["../../src/components/DocumentSkeleton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,IAAQ,EAAE,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,qBAWnE;AAED,wEAAwE;AACxE,wBAAgB,sBAAsB,sBAUrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"FormRenderer.d.ts","sourceRoot":"","sources":["../../src/components/FormRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsB,MAAM,OAAO,CAAA;AAW1C,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,UAAU,CAAA;AAExD,UAAU,iBAAiB;IACzB,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAkND,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,iBAAiB,qBA2BnF"}
1
+ {"version":3,"file":"FormRenderer.d.ts","sourceRoot":"","sources":["../../src/components/FormRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsB,MAAM,OAAO,CAAA;AAY1C,OAAO,KAAK,EAAgB,UAAU,EAAE,MAAM,UAAU,CAAA;AAoBxD,UAAU,iBAAiB;IACzB,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAA;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAuUD,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,iBAAiB,qBA2BnF"}
@@ -1 +1 @@
1
- {"version":3,"file":"FormViewer.d.ts","sourceRoot":"","sources":["../../src/components/FormViewer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAKlD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,UAAU,CAAA;AAI1D,UAAU,eAAe;IACvB,QAAQ,EAAE,YAAY,CAAA;IACtB,QAAQ,EAAE,uBAAuB,CAAA;IACjC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,CAAA;CACrC;AASD,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,eAAe,qBAqEtF"}
1
+ {"version":3,"file":"FormViewer.d.ts","sourceRoot":"","sources":["../../src/components/FormViewer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAKlD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,UAAU,CAAA;AAK1D,UAAU,eAAe;IACvB,QAAQ,EAAE,YAAY,CAAA;IACtB,QAAQ,EAAE,uBAAuB,CAAA;IACjC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,CAAA;CACrC;AASD,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,eAAe,qBA0EtF"}
@@ -1 +1 @@
1
- {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/data/mock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAsBtD,wBAAgB,uBAAuB,IAAI,uBAAuB,CA0KjE"}
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/data/mock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAuBtD,wBAAgB,uBAAuB,IAAI,uBAAuB,CAwLjE"}
@@ -1 +1 @@
1
- {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAiGtD,wBAAgB,2BAA2B,IAAI,uBAAuB,CAqTrE"}
1
+ {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/data/supabase.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAqItD,wBAAgB,2BAA2B,IAAI,uBAAuB,CAqVrE"}
@@ -1,10 +1,13 @@
1
- import type { FormTemplate, FormDocument, DocumentFile, TemplateQuery, DocumentQuery, PaginatedResult, CreateTemplateInput, UpdateTemplateInput, CreateDocumentInput, UpdateDocumentInput } from '../types';
1
+ import type { FormTemplate, FormDocument, DocumentFile, TemplateQuery, DocumentQuery, PaginatedResult, CreateTemplateInput, UpdateTemplateInput, CreateDocumentInput, UpdateDocumentInput, TemplateUsage } from '../types';
2
2
  export interface CustomFormsDataProvider {
3
3
  getTemplates(query: TemplateQuery): Promise<PaginatedResult<FormTemplate>>;
4
4
  getTemplateById(id: string): Promise<FormTemplate | null>;
5
5
  createTemplate(input: CreateTemplateInput): Promise<FormTemplate>;
6
6
  updateTemplate(id: string, input: UpdateTemplateInput): Promise<FormTemplate>;
7
7
  deleteTemplate(id: string): Promise<void>;
8
+ /** Uso por modelo, indexado pelo id do modelo. Modelos sem nenhum documento
9
+ * simplesmente não aparecem no mapa. */
10
+ getTemplateUsage(): Promise<Record<string, TemplateUsage>>;
8
11
  getDocuments(query: DocumentQuery): Promise<PaginatedResult<FormDocument>>;
9
12
  getDocumentById(id: string): Promise<FormDocument | null>;
10
13
  createDocument(input: CreateDocumentInput): Promise<FormDocument>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/data/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACpB,MAAM,UAAU,CAAA;AAEjB,MAAM,WAAW,uBAAuB;IAEtC,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAA;IAC1E,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IACzD,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACjE,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAC7E,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAGzC,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAA;IAC1E,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IACzD,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACjE,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAC7E,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAGzC,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAC7D,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACnF,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1C"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/data/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACd,MAAM,UAAU,CAAA;AAEjB,MAAM,WAAW,uBAAuB;IAEtC,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAA;IAC1E,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IACzD,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACjE,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAC7E,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACzC;6CACyC;IACzC,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAA;IAG1D,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAA;IAC1E,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IACzD,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACjE,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAC7E,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAGzC,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAC7D,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IACnF,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1C"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAUnD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AA0CxD,YAAY,EAAE,wBAAwB,EAAE,CAAA;AACxC,OAAO,EAAE,4BAA4B,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAEvH,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,cAAc,CAiL1F"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAUnD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAA;AA2CxD,YAAY,EAAE,wBAAwB,EAAE,CAAA;AACxC,OAAO,EAAE,4BAA4B,EAAE,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAEvH,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,wBAAwB,GAAG,cAAc,CAmL1F"}
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- import { createOrUpdateFormTool, prefillFromPerson, FormRenderer, printDocument } from './chunk-JCAWSDX6.js';
1
+ import { createOrUpdateFormTool, prefillFromPerson, FormRenderer, printDocument } from './chunk-RBLXIKWB.js';
2
2
  import React2, { useState, useCallback, useRef, useEffect } from 'react';
3
- import { registerTranslations, createSafeDataProvider, useTranslation, getSupabaseClientOptional, getActiveTenantId } from '@fayz-ai/core';
4
- import { PluginSettingsPanel, useLimitGuard, invalidateLimit, PermissionGate } from '@fayz-ai/admin';
3
+ import { registerTranslations, createSafeDataProvider, getSupabaseClientOptional, useTranslation, getActiveTenantId } from '@fayz-ai/core';
4
+ import { PluginSettingsPanel, registerTimelineSource, useLimitGuard, invalidateLimit, PermissionGate } from '@fayz-ai/admin';
5
5
  import { create } from 'zustand';
6
6
  import { FileText, Image, Paperclip, Search, Plus, Pencil, Archive, ArrowLeft, Printer, ChevronDown, Upload, Eye } from 'lucide-react';
7
7
  import { Input, Button, Card, CardContent, Badge, useSaveBar, Dropdown, DropdownTrigger, DropdownContent, DropdownSeparator, DropdownLabel, DropdownItem } from '@fayz-ai/ui';
8
- import { jsx, jsxs } from 'react/jsx-runtime';
8
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
9
 
10
10
  // src/data/tables.ts
11
11
  var T = {
@@ -85,6 +85,19 @@ function createMockFormsProvider() {
85
85
  const idx = templates.findIndex((t) => t.id === id);
86
86
  if (idx !== -1) templates[idx] = { ...templates[idx], isDeleted: true };
87
87
  },
88
+ async getTemplateUsage() {
89
+ const usage = {};
90
+ for (const doc of documents) {
91
+ if (doc.isDeleted || !doc.templateId) continue;
92
+ const current = usage[doc.templateId] ?? { documentCount: 0, lastDocumentAt: null };
93
+ current.documentCount += 1;
94
+ if (!current.lastDocumentAt || doc.createdAt > current.lastDocumentAt) {
95
+ current.lastDocumentAt = doc.createdAt;
96
+ }
97
+ usage[doc.templateId] = current;
98
+ }
99
+ return usage;
100
+ },
88
101
  // ── Documents ──────────────────────────────────────────
89
102
  async getDocuments(query) {
90
103
  let filtered = documents.filter((d) => !d.isDeleted);
@@ -189,6 +202,26 @@ function getClient() {
189
202
  if (!supabase) throw new Error("Supabase not initialized");
190
203
  return supabase;
191
204
  }
205
+ var USAGE_FALLBACK_LIMIT = 5e3;
206
+ async function countTemplateUsageClientSide(db, tenantId) {
207
+ try {
208
+ const { data, error, count } = await db.from("v_documents").select("template_id, created_at", { count: "exact" }).eq("tenant_id", tenantId).eq("is_active", true).not("template_id", "is", null).limit(USAGE_FALLBACK_LIMIT);
209
+ if (error) return {};
210
+ if (typeof count === "number" && count > USAGE_FALLBACK_LIMIT) return {};
211
+ const usage = {};
212
+ for (const row of data ?? []) {
213
+ const current = usage[row.template_id] ?? { documentCount: 0, lastDocumentAt: null };
214
+ current.documentCount += 1;
215
+ if (!current.lastDocumentAt || row.created_at > current.lastDocumentAt) {
216
+ current.lastDocumentAt = row.created_at;
217
+ }
218
+ usage[row.template_id] = current;
219
+ }
220
+ return usage;
221
+ } catch {
222
+ return {};
223
+ }
224
+ }
192
225
  function mapTemplate(r) {
193
226
  return {
194
227
  id: r.id,
@@ -336,6 +369,31 @@ function createSupabaseFormsProvider() {
336
369
  const { error } = await db.from(T.templates).update({ is_deleted: true, updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", id);
337
370
  if (error) throw new Error(error.message);
338
371
  },
372
+ // Uso por modelo. Caminho principal: `v_forms_template_usage`, que agrega no
373
+ // banco (004_template_usage.sql) e devolve uma linha por modelo.
374
+ //
375
+ // O fallback existe porque um pool provisionado antes daquela migração não
376
+ // tem a view, e a tela não pode ficar sem o número por causa disso: ele
377
+ // relê as colunas mínimas dos documentos e agrega aqui. É limitado de
378
+ // propósito — acima do teto o número seria mentira, e mentir sobre uma
379
+ // contagem é pior do que omiti-la, então ele desiste em silêncio.
380
+ async getTemplateUsage() {
381
+ const db = getClient();
382
+ const tenantId = getTenantId();
383
+ if (!tenantId) return {};
384
+ const { data, error } = await db.from("v_forms_template_usage").select("template_id, document_count, last_document_at").eq("tenant_id", tenantId);
385
+ if (!error) {
386
+ const usage = {};
387
+ for (const row of data ?? []) {
388
+ usage[row.template_id] = {
389
+ documentCount: Number(row.document_count ?? 0),
390
+ lastDocumentAt: row.last_document_at ?? null
391
+ };
392
+ }
393
+ return usage;
394
+ }
395
+ return countTemplateUsageClientSide(db, tenantId);
396
+ },
339
397
  // ── Documents (public.documents + plg_forms_documents extension) ──
340
398
  async getDocuments(query) {
341
399
  const db = getClient();
@@ -451,6 +509,7 @@ function createCustomFormsStore(provider) {
451
509
  templatesTotal: 0,
452
510
  templatesLoading: false,
453
511
  templatesError: null,
512
+ templateUsage: {},
454
513
  documents: [],
455
514
  documentsTotal: 0,
456
515
  documentsLoading: false,
@@ -470,6 +529,18 @@ function createCustomFormsStore(provider) {
470
529
  set({ templatesLoading: false });
471
530
  }
472
531
  },
532
+ // Separado de `fetchTemplates` porque é outra pergunta e outro custo: a
533
+ // lista precisa dos modelos para desenhar, e o uso é um enfeite que chega
534
+ // depois. Junto, a tela inteira esperaria a agregação; e uma falha na
535
+ // contagem levaria embora a lista, que não tem nada a ver com isso — daí
536
+ // ele engolir o erro em vez de escrevê-lo em `templatesError`.
537
+ async fetchTemplateUsage() {
538
+ try {
539
+ set({ templateUsage: await provider.getTemplateUsage() });
540
+ } catch {
541
+ set({ templateUsage: {} });
542
+ }
543
+ },
473
544
  async fetchTemplateById(id) {
474
545
  set({ activeTemplateLoading: true });
475
546
  try {
@@ -629,6 +700,8 @@ var en = {
629
700
  "customForms.archive": "Archive",
630
701
  "customForms.archiveDocumentConfirm": "Archive this document? It leaves the active list but is kept on file.",
631
702
  "customForms.printPdf": "Print / PDF",
703
+ "customForms.usageCount": "{{count}} filled in",
704
+ "customForms.usageLast": "last on {{date}}",
632
705
  // Registry
633
706
  "registry.form-categories": "Categories",
634
707
  "registry.form-categories.description": "Categories for organizing form templates",
@@ -718,6 +791,8 @@ var ptBR = {
718
791
  "customForms.archive": "Arquivar",
719
792
  "customForms.archiveDocumentConfirm": "Arquivar este documento? Ele sai da lista ativa mas fica guardado.",
720
793
  "customForms.printPdf": "Imprimir / PDF",
794
+ "customForms.usageCount": "{{count}} preenchidos",
795
+ "customForms.usageLast": "\xFAltimo em {{date}}",
721
796
  // Registry
722
797
  "registry.form-categories": "Categorias",
723
798
  "registry.form-categories.description": "Categorias para organizar modelos de formul\xE1rios",
@@ -761,6 +836,7 @@ function TemplateListView({ store, config, onEdit, onNew }) {
761
836
  const [search, setSearch] = useState("");
762
837
  const templates = store((s) => s.templates);
763
838
  const loading = store((s) => s.templatesLoading);
839
+ const usage = store((s) => s.templateUsage);
764
840
  const orgId = getFormsTenantId();
765
841
  useEffect(() => {
766
842
  if (!orgId) return;
@@ -769,6 +845,10 @@ function TemplateListView({ store, config, onEdit, onNew }) {
769
845
  }, 50);
770
846
  return () => clearTimeout(timer);
771
847
  }, [orgId, search]);
848
+ useEffect(() => {
849
+ if (!orgId) return;
850
+ void store.getState().fetchTemplateUsage();
851
+ }, [orgId]);
772
852
  const handleArchive = useCallback(async (template) => {
773
853
  if (!window.confirm(t("customForms.archiveTemplateConfirm"))) return;
774
854
  await store.getState().updateTemplate(template.id, { isActive: false });
@@ -851,6 +931,17 @@ function TemplateListView({ store, config, onEdit, onNew }) {
851
931
  "v",
852
932
  template.version
853
933
  ] })
934
+ ] }),
935
+ /* @__PURE__ */ jsxs("p", { className: "mt-2 text-[10px] text-muted-foreground", children: [
936
+ t("customForms.usageCount", {
937
+ count: String(usage[template.id]?.documentCount ?? 0)
938
+ }),
939
+ usage[template.id]?.lastDocumentAt && /* @__PURE__ */ jsxs(Fragment, { children: [
940
+ /* @__PURE__ */ jsx("span", { className: "px-1", children: "\xB7" }),
941
+ t("customForms.usageLast", {
942
+ date: new Date(usage[template.id].lastDocumentAt).toLocaleDateString()
943
+ })
944
+ ] })
854
945
  ] })
855
946
  ] })
856
947
  },
@@ -917,7 +1008,7 @@ function BuilderWrapper({
917
1008
  onBack
918
1009
  }) {
919
1010
  const FormBuilderLazy = React2.lazy(
920
- () => import('./FormBuilder-JCNHXQXT.js').then((m) => ({ default: m.FormBuilder }))
1011
+ () => import('./FormBuilder-YHJHF6HZ.js').then((m) => ({ default: m.FormBuilder }))
921
1012
  );
922
1013
  return /* @__PURE__ */ jsx(
923
1014
  React2.Suspense,
@@ -1114,6 +1205,21 @@ function DocumentList({ personId, provider, store, onView, onFileDrop }) {
1114
1205
  }
1115
1206
  );
1116
1207
  }
1208
+ function DocumentBodySkeleton({ rows = 5 }) {
1209
+ return /* @__PURE__ */ jsx("div", { className: "space-y-4 rounded-xl border p-4", "aria-hidden": true, children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
1210
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-28 animate-pulse rounded bg-muted" }),
1211
+ /* @__PURE__ */ jsx("div", { className: "h-9 w-full animate-pulse rounded-md bg-muted" })
1212
+ ] }, i)) });
1213
+ }
1214
+ function DocumentHeaderSkeleton() {
1215
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", "aria-hidden": true, children: [
1216
+ /* @__PURE__ */ jsx("div", { className: "h-3.5 w-3.5 shrink-0 animate-pulse rounded bg-muted" }),
1217
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1.5", children: [
1218
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-48 max-w-full animate-pulse rounded bg-muted" }),
1219
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-24 animate-pulse rounded bg-muted" })
1220
+ ] })
1221
+ ] });
1222
+ }
1117
1223
  function generateTitle(templateName, personName) {
1118
1224
  const date = (/* @__PURE__ */ new Date()).toLocaleDateString();
1119
1225
  return personName ? `${templateName} \u2014 ${personName} \u2014 ${date}` : `${templateName} \u2014 ${date}`;
@@ -1190,7 +1296,28 @@ function DocumentFormDialog({
1190
1296
  saveLabel: t("customForms.saveAndComplete")
1191
1297
  });
1192
1298
  if (!template) {
1193
- return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx("div", { className: "h-5 w-5 border-2 border-primary border-t-transparent animate-spin rounded-full" }) });
1299
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
1300
+ existingDocument?.title ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1301
+ /* @__PURE__ */ jsx(
1302
+ "button",
1303
+ {
1304
+ onClick: onBack,
1305
+ className: "flex items-center gap-1 text-sm text-muted-foreground transition-colors hover:text-foreground",
1306
+ children: /* @__PURE__ */ jsx(ArrowLeft, { className: "h-3.5 w-3.5" })
1307
+ }
1308
+ ),
1309
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
1310
+ /* @__PURE__ */ jsx("h3", { className: "truncate text-sm font-semibold", children: existingDocument.title }),
1311
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: new Date(existingDocument.createdAt).toLocaleDateString() })
1312
+ ] })
1313
+ ] }) : /* @__PURE__ */ jsx(DocumentHeaderSkeleton, {}),
1314
+ /* @__PURE__ */ jsx(
1315
+ DocumentBodySkeleton,
1316
+ {
1317
+ rows: Math.min(Math.max(Object.keys(existingDocument?.data ?? {}).length, 3), 8)
1318
+ }
1319
+ )
1320
+ ] });
1194
1321
  }
1195
1322
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
1196
1323
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
@@ -1239,9 +1366,6 @@ function FormViewer({ document: doc, provider, onBack, onEdit }) {
1239
1366
  }, 50);
1240
1367
  return () => clearTimeout(timer);
1241
1368
  }, [doc.templateId, provider]);
1242
- if (!template) {
1243
- return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx("div", { className: "h-5 w-5 border-2 border-primary border-t-transparent animate-spin rounded-full" }) });
1244
- }
1245
1369
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
1246
1370
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1247
1371
  /* @__PURE__ */ jsx(
@@ -1253,7 +1377,7 @@ function FormViewer({ document: doc, provider, onBack, onEdit }) {
1253
1377
  }
1254
1378
  ),
1255
1379
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1256
- /* @__PURE__ */ jsx("h3", { className: "font-semibold text-sm truncate", children: doc.title ?? template.name }),
1380
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold text-sm truncate", children: doc.title ?? template?.name ?? "" }),
1257
1381
  /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: new Date(doc.createdAt).toLocaleDateString() })
1258
1382
  ] }),
1259
1383
  /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: `text-[10px] ${STATUS_COLORS2[doc.status] ?? ""}`, children: t(`customForms.status.${doc.status}`) }),
@@ -1263,7 +1387,8 @@ function FormViewer({ document: doc, provider, onBack, onEdit }) {
1263
1387
  variant: "outline",
1264
1388
  size: "sm",
1265
1389
  className: "h-8",
1266
- onClick: () => printDocument(template, doc),
1390
+ disabled: !template,
1391
+ onClick: () => template && printDocument(template, doc),
1267
1392
  children: [
1268
1393
  /* @__PURE__ */ jsx(Printer, { className: "h-3 w-3 mr-1" }),
1269
1394
  t("customForms.printPdf")
@@ -1275,7 +1400,7 @@ function FormViewer({ document: doc, provider, onBack, onEdit }) {
1275
1400
  t("common.edit")
1276
1401
  ] })
1277
1402
  ] }),
1278
- /* @__PURE__ */ jsx("div", { className: "rounded-xl border p-4", children: /* @__PURE__ */ jsx(
1403
+ template ? /* @__PURE__ */ jsx("div", { className: "rounded-xl border p-4", children: /* @__PURE__ */ jsx(
1279
1404
  FormRenderer,
1280
1405
  {
1281
1406
  schema: template.schema,
@@ -1284,7 +1409,11 @@ function FormViewer({ document: doc, provider, onBack, onEdit }) {
1284
1409
  },
1285
1410
  readOnly: true
1286
1411
  }
1287
- ) })
1412
+ ) }) : (
1413
+ // O documento já diz quantos campos tem: o esqueleto sai da altura certa
1414
+ // em vez de chutar, e a chegada do conteúdo não mexe no scroll.
1415
+ /* @__PURE__ */ jsx(DocumentBodySkeleton, { rows: Math.min(Math.max(Object.keys(doc.data ?? {}).length, 3), 8) })
1416
+ )
1288
1417
  ] });
1289
1418
  }
1290
1419
 
@@ -1514,6 +1643,34 @@ function FileDocumentViewer({ document: doc, onBack }) {
1514
1643
  ] }) })
1515
1644
  ] });
1516
1645
  }
1646
+ function registerFormsTimelineSource() {
1647
+ registerTimelineSource({
1648
+ id: "documents",
1649
+ label: "Documentos",
1650
+ icon: "FileText",
1651
+ tone: "primary",
1652
+ async fetch(args) {
1653
+ const db = getSupabaseClientOptional();
1654
+ if (!db) return [];
1655
+ let query = db.from("v_documents").select("id, title, kind, status, template_name, created_at").eq("tenant_id", args.tenantId).eq("person_id", args.personId).eq("is_active", true).order("created_at", { ascending: false }).limit(args.limit);
1656
+ if (args.before) query = query.lt("created_at", args.before);
1657
+ const { data, error } = await query;
1658
+ if (error) return [];
1659
+ return (data ?? []).map((row) => ({
1660
+ id: `document:${row.id}`,
1661
+ sourceId: "documents",
1662
+ occurredAt: row.created_at,
1663
+ title: row.title ?? row.template_name ?? "Documento",
1664
+ // O modelo só entra como descrição quando o título não veio dele —
1665
+ // senão a linha diria a mesma coisa duas vezes.
1666
+ description: row.template_name && row.template_name !== row.title ? row.template_name : void 0,
1667
+ badge: row.status ?? void 0,
1668
+ icon: row.kind === "image" ? "Image" : row.kind === "attachment" ? "Paperclip" : "FileText",
1669
+ targetTab: "documents"
1670
+ }));
1671
+ }
1672
+ });
1673
+ }
1517
1674
  function registerBuiltInProviders(formsProvider) {
1518
1675
  registerDocumentTypeProvider({
1519
1676
  id: "custom_forms:templates",
@@ -1554,6 +1711,7 @@ function createCustomFormsPlugin(options) {
1554
1711
  );
1555
1712
  const store = createCustomFormsStore(provider);
1556
1713
  registerBuiltInProviders(provider);
1714
+ registerFormsTimelineSource();
1557
1715
  const formRegistries = [
1558
1716
  {
1559
1717
  id: "form-categories",
@@ -1590,9 +1748,6 @@ function createCustomFormsPlugin(options) {
1590
1748
  const SettingsComponent = () => React2.createElement(PluginSettingsPanel, {
1591
1749
  title: config.labels.settingsLabel,
1592
1750
  subtitle: config.labels.settingsSubtitle,
1593
- // The settings shell already renders the section label as the page H1;
1594
- // hide the panel's own duplicate title (keeps the subtitle).
1595
- hideTitle: true,
1596
1751
  customTabs: [
1597
1752
  {
1598
1753
  id: "forms",
@@ -1701,6 +1856,8 @@ function createCustomFormsPlugin(options) {
1701
1856
  audits: true
1702
1857
  }
1703
1858
  ],
1859
+ // Where a submitted form is supposed to land.
1860
+ integrations: ["mailchimp", "rd-station", "zapier"],
1704
1861
  locales: customFormsLocales
1705
1862
  };
1706
1863
  }