From bf3528831c5a719e634d0e000eb99800dc24604e Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 01:55:31 +0000 Subject: [PATCH] Changes Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/components/forms/custom-form-builder.tsx | 50 ++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/components/forms/custom-form-builder.tsx b/src/components/forms/custom-form-builder.tsx index 82536e1..4f415e3 100644 --- a/src/components/forms/custom-form-builder.tsx +++ b/src/components/forms/custom-form-builder.tsx @@ -3,6 +3,11 @@ import { useEditor, EditorContent } from "@tiptap/react"; import StarterKit from "@tiptap/starter-kit"; import Underline from "@tiptap/extension-underline"; import TextAlign from "@tiptap/extension-text-align"; +import Paragraph from "@tiptap/extension-paragraph"; +import Table from "@tiptap/extension-table"; +import TableRow from "@tiptap/extension-table-row"; +import TableCell from "@tiptap/extension-table-cell"; +import TableHeader from "@tiptap/extension-table-header"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; @@ -38,6 +43,11 @@ import { Search, Trash2, FileText, + Table as TableIcon, + Rows, + Columns, + Captions, + X, } from "lucide-react"; import { ClientHomeownerPicker } from "./form-pickers"; import { @@ -62,10 +72,50 @@ import { TextRun, HeadingLevel, AlignmentType, + Table as DocxTable, + TableRow as DocxTableRow, + TableCell as DocxTableCell, + WidthType, + BorderStyle, } from "docx"; import { toast } from "sonner"; import { supabase } from "@/integrations/supabase/client"; +// Paragraph extension with indent (px) + caption flag, persisted as inline styles +const PaddedParagraph = Paragraph.extend({ + addAttributes() { + return { + ...this.parent?.(), + indent: { + default: 0, + parseHTML: (el) => { + const pl = (el as HTMLElement).style.paddingLeft; + if (!pl) return 0; + const n = parseInt(pl, 10); + return isNaN(n) ? 0 : n; + }, + renderHTML: (attrs) => { + const i = Number(attrs.indent ?? 0); + if (!i) return {}; + return { style: `padding-left: ${i}px` }; + }, + }, + caption: { + default: false, + parseHTML: (el) => (el as HTMLElement).getAttribute("data-caption") === "true", + renderHTML: (attrs) => + attrs.caption + ? { + "data-caption": "true", + style: + "text-align:center;font-style:italic;font-size:0.9em;color:#555;margin-top:4px;", + } + : {}, + }, + }; + }, +}); + const FONT_FAMILIES = [ { value: "Bookman Old Style", label: "Bookman Old Style", pdf: "times" }, { value: "Times New Roman", label: "Times New Roman", pdf: "times" },