From 4bc3c9fbf188e5d3d780dd6e0d2f3d460450ccb1 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Thu, 13 Nov 2025 14:46:58 -0300 Subject: [PATCH 1/3] feat: enhance field handling with mode support in template builder This commit introduces a new 'mode' property to the TemplateField interface, allowing fields to be categorized as either 'inline' or 'block'. Updates to the FieldMenu and FieldList components enable users to select the mode when creating fields, improving the overall flexibility and usability of the template builder. Additionally, the App component's styling import has been corrected for consistency. --- .gitignore | 1 + demo/src/App.tsx | 2 +- src/defaults/FieldList.tsx | 37 +++++++++++++++++++++++++++---------- src/defaults/FieldMenu.tsx | 31 +++++++++++++++++++++++++++++++ src/index.tsx | 13 ++++++++++--- src/types.ts | 1 + 6 files changed, 71 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index c09dd7e..7050ee9 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ examples/**/yarn.lock # Dev dev/** +CLAUDE.md diff --git a/demo/src/App.tsx b/demo/src/App.tsx index 65e4a49..469fe79 100644 --- a/demo/src/App.tsx +++ b/demo/src/App.tsx @@ -5,7 +5,7 @@ import type { TemplateField, FieldDefinition, } from "@superdoc-dev/template-builder"; -import "superdoc/dist/style.css"; +import "superdoc/style.css"; import "./App.css"; const availableFields: FieldDefinition[] = [ diff --git a/src/defaults/FieldList.tsx b/src/defaults/FieldList.tsx index 3d015ba..d5b691a 100644 --- a/src/defaults/FieldList.tsx +++ b/src/defaults/FieldList.tsx @@ -118,16 +118,33 @@ export const FieldList: React.FC = ({ > {field.id} - {field.alias && field.alias !== field.id && ( -
- {field.alias} -
- )} +
+ {field.alias && field.alias !== field.id && ( + {field.alias} + )} + {field.mode && ( + + {field.mode} + + )} +
))} diff --git a/src/defaults/FieldMenu.tsx b/src/defaults/FieldMenu.tsx index 10931da..e71f8bd 100644 --- a/src/defaults/FieldMenu.tsx +++ b/src/defaults/FieldMenu.tsx @@ -14,11 +14,13 @@ export const FieldMenu: React.FC = ({ }) => { const [isCreating, setIsCreating] = useState(false); const [newFieldName, setNewFieldName] = useState(""); + const [fieldMode, setFieldMode] = useState<"inline" | "block">("inline"); useEffect(() => { if (!isVisible) { setIsCreating(false); setNewFieldName(""); + setFieldMode("inline"); } }, [isVisible]); @@ -103,6 +105,7 @@ export const FieldMenu: React.FC = ({ id: `custom_${Date.now()}`, label: trimmedName, category: "Custom", + metadata: { mode: fieldMode }, }; try { @@ -115,6 +118,7 @@ export const FieldMenu: React.FC = ({ } finally { setIsCreating(false); setNewFieldName(""); + setFieldMode("inline"); } }; @@ -176,6 +180,33 @@ export const FieldMenu: React.FC = ({ borderRadius: "3px", }} /> +
+ + +
{ return tags.map((entry: any) => { const node = entry?.node ?? entry; const attrs = node?.attrs ?? {}; + const nodeType = node?.type?.name || ""; + const mode = nodeType.includes("Block") ? "block" : "inline"; return { id: attrs.id, alias: attrs.alias || attrs.label || "", tag: attrs.tag, + mode, } as Types.TemplateField; }); }; @@ -55,7 +58,8 @@ const areTemplateFieldsEqual = ( left.id !== right.id || left.alias !== right.alias || left.tag !== right.tag || - left.position !== right.position + left.position !== right.position || + left.mode !== right.mode ) { return false; } @@ -522,12 +526,15 @@ const SuperDocTemplateBuilder = forwardRef< menuTriggerFromRef.current = null; resetMenuFilter(); + const mode = (field.metadata?.mode as "inline" | "block") || "inline"; + if (field.id.startsWith("custom_") && onFieldCreate) { try { const createdField = await onFieldCreate(field); if (createdField) { - insertFieldInternal("inline", { + const createdMode = (createdField.metadata?.mode as "inline" | "block") || mode; + insertFieldInternal(createdMode, { alias: createdField.label, category: createdField.category, metadata: createdField.metadata, @@ -541,7 +548,7 @@ const SuperDocTemplateBuilder = forwardRef< } } - insertFieldInternal("inline", { + insertFieldInternal(mode, { alias: field.label, category: field.category, metadata: field.metadata, diff --git a/src/types.ts b/src/types.ts index 0450008..19d35a7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -13,6 +13,7 @@ export interface TemplateField { alias: string; tag?: string; position?: number; + mode?: "inline" | "block"; } export interface TriggerEvent { From 0f7bdeb7501832a575173b681f55e1d7882cf047 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Thu, 13 Nov 2025 14:49:08 -0300 Subject: [PATCH 2/3] fix: reset field mode to inline on escape and click events in FieldMenu --- src/defaults/FieldMenu.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/defaults/FieldMenu.tsx b/src/defaults/FieldMenu.tsx index e71f8bd..a3a3871 100644 --- a/src/defaults/FieldMenu.tsx +++ b/src/defaults/FieldMenu.tsx @@ -170,6 +170,7 @@ export const FieldMenu: React.FC = ({ if (event.key === "Escape") { setIsCreating(false); setNewFieldName(""); + setFieldMode("inline"); } }} autoFocus @@ -232,6 +233,7 @@ export const FieldMenu: React.FC = ({ onClick={() => { setIsCreating(false); setNewFieldName(""); + setFieldMode("inline"); }} style={{ padding: "4px 12px", From a16fe1cc8161724eff100772b36978be17dc2489 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Thu, 13 Nov 2025 14:50:51 -0300 Subject: [PATCH 3/3] fix: update stylesheet import path in App component for consistency --- demo/src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/src/App.tsx b/demo/src/App.tsx index 469fe79..65e4a49 100644 --- a/demo/src/App.tsx +++ b/demo/src/App.tsx @@ -5,7 +5,7 @@ import type { TemplateField, FieldDefinition, } from "@superdoc-dev/template-builder"; -import "superdoc/style.css"; +import "superdoc/dist/style.css"; import "./App.css"; const availableFields: FieldDefinition[] = [