Fixed indent state in editor

X-Lovable-Edit-ID: edt-3f8c8588-8d67-4be2-a84a-6691637e0d58
Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
gpt-engineer-app[bot]
2026-04-18 16:31:28 +00:00
co-authored by renee-png
+50 -5
View File
@@ -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();
};