diff --git a/src/components/forms/custom-form-builder.tsx b/src/components/forms/custom-form-builder.tsx index eeedc0b..b135bb9 100644 --- a/src/components/forms/custom-form-builder.tsx +++ b/src/components/forms/custom-form-builder.tsx @@ -4,6 +4,7 @@ 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 Heading from "@tiptap/extension-heading"; import { Table } from "@tiptap/extension-table"; import { TableRow } from "@tiptap/extension-table-row"; import { TableCell } from "@tiptap/extension-table-cell"; @@ -121,6 +122,29 @@ const PaddedParagraph = Paragraph.extend({ }, }); +// Heading with same indent attribute so indent works on H1-H3 too +const PaddedHeading = Heading.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` }; + }, + }, + }; + }, +}); + const FONT_FAMILIES = [ { value: "Bookman Old Style", label: "Bookman Old Style", pdf: "times" }, { value: "Times New Roman", label: "Times New Roman", pdf: "times" }, @@ -268,8 +292,9 @@ export function CustomFormBuilder() { const editor = useEditor({ extensions: [ - StarterKit.configure({ heading: { levels: [1, 2, 3] }, paragraph: false }), + StarterKit.configure({ heading: false, paragraph: false }), PaddedParagraph, + PaddedHeading.configure({ levels: [1, 2, 3] }), Underline, TextAlign.configure({ types: ["heading", "paragraph"] }), Table.configure({ resizable: true, HTMLAttributes: { class: "cf-table" } }), @@ -331,19 +356,39 @@ export function CustomFormBuilder() { const INDENT_STEP = 36; // ~0.5" + const activeIndentNode = (): "heading" | "paragraph" | null => { + if (!editor) return null; + if (editor.isActive("heading")) return "heading"; + if (editor.isActive("paragraph")) return "paragraph"; + return null; + }; + const indent = () => { if (!editor) return; - const cur = Number(editor.getAttributes("paragraph").indent ?? 0); - editor.chain().focus().updateAttributes("paragraph", { indent: cur + INDENT_STEP }).run(); + // Lists: nest the item instead of changing padding + if (editor.isActive("listItem")) { + editor.chain().focus().sinkListItem("listItem").run(); + return; + } + const node = activeIndentNode(); + if (!node) return; + const cur = Number(editor.getAttributes(node).indent ?? 0); + editor.chain().focus().updateAttributes(node, { indent: cur + INDENT_STEP }).run(); }; const outdent = () => { if (!editor) return; - const cur = Number(editor.getAttributes("paragraph").indent ?? 0); + if (editor.isActive("listItem")) { + editor.chain().focus().liftListItem("listItem").run(); + return; + } + const node = activeIndentNode(); + if (!node) return; + const cur = Number(editor.getAttributes(node).indent ?? 0); editor .chain() .focus() - .updateAttributes("paragraph", { indent: Math.max(0, cur - INDENT_STEP) }) + .updateAttributes(node, { indent: Math.max(0, cur - INDENT_STEP) }) .run(); };