Skip to content
This repository was archived by the owner on Jan 30, 2026. It is now read-only.

Commit 4bc3c9f

Browse files
committed
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.
1 parent f752754 commit 4bc3c9f

6 files changed

Lines changed: 71 additions & 14 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ examples/**/yarn.lock
2525

2626
# Dev
2727
dev/**
28+
CLAUDE.md

demo/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type {
55
TemplateField,
66
FieldDefinition,
77
} from "@superdoc-dev/template-builder";
8-
import "superdoc/dist/style.css";
8+
import "superdoc/style.css";
99
import "./App.css";
1010

1111
const availableFields: FieldDefinition[] = [

src/defaults/FieldList.tsx

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,33 @@ export const FieldList: React.FC<FieldListProps> = ({
118118
>
119119
{field.id}
120120
</div>
121-
{field.alias && field.alias !== field.id && (
122-
<div
123-
style={{
124-
fontSize: "12px",
125-
color: "#4b5563",
126-
}}
127-
>
128-
{field.alias}
129-
</div>
130-
)}
121+
<div
122+
style={{
123+
display: "flex",
124+
alignItems: "center",
125+
gap: "6px",
126+
fontSize: "12px",
127+
color: "#4b5563",
128+
}}
129+
>
130+
{field.alias && field.alias !== field.id && (
131+
<span>{field.alias}</span>
132+
)}
133+
{field.mode && (
134+
<span
135+
style={{
136+
fontSize: "10px",
137+
padding: "2px 6px",
138+
borderRadius: "4px",
139+
background: field.mode === "block" ? "#dbeafe" : "#f3f4f6",
140+
color: field.mode === "block" ? "#1e40af" : "#4b5563",
141+
fontWeight: "500",
142+
}}
143+
>
144+
{field.mode}
145+
</span>
146+
)}
147+
</div>
131148
</div>
132149
</div>
133150
))}

src/defaults/FieldMenu.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ export const FieldMenu: React.FC<FieldMenuProps> = ({
1414
}) => {
1515
const [isCreating, setIsCreating] = useState(false);
1616
const [newFieldName, setNewFieldName] = useState("");
17+
const [fieldMode, setFieldMode] = useState<"inline" | "block">("inline");
1718

1819
useEffect(() => {
1920
if (!isVisible) {
2021
setIsCreating(false);
2122
setNewFieldName("");
23+
setFieldMode("inline");
2224
}
2325
}, [isVisible]);
2426

@@ -103,6 +105,7 @@ export const FieldMenu: React.FC<FieldMenuProps> = ({
103105
id: `custom_${Date.now()}`,
104106
label: trimmedName,
105107
category: "Custom",
108+
metadata: { mode: fieldMode },
106109
};
107110

108111
try {
@@ -115,6 +118,7 @@ export const FieldMenu: React.FC<FieldMenuProps> = ({
115118
} finally {
116119
setIsCreating(false);
117120
setNewFieldName("");
121+
setFieldMode("inline");
118122
}
119123
};
120124

@@ -176,6 +180,33 @@ export const FieldMenu: React.FC<FieldMenuProps> = ({
176180
borderRadius: "3px",
177181
}}
178182
/>
183+
<div
184+
style={{
185+
marginTop: "8px",
186+
display: "flex",
187+
gap: "12px",
188+
fontSize: "13px",
189+
}}
190+
>
191+
<label style={{ display: "flex", alignItems: "center", gap: "4px", cursor: "pointer" }}>
192+
<input
193+
type="radio"
194+
value="inline"
195+
checked={fieldMode === "inline"}
196+
onChange={() => setFieldMode("inline")}
197+
/>
198+
Inline
199+
</label>
200+
<label style={{ display: "flex", alignItems: "center", gap: "4px", cursor: "pointer" }}>
201+
<input
202+
type="radio"
203+
value="block"
204+
checked={fieldMode === "block"}
205+
onChange={() => setFieldMode("block")}
206+
/>
207+
Block
208+
</label>
209+
</div>
179210
<div
180211
style={{
181212
marginTop: "8px",

src/index.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,14 @@ const getTemplateFieldsFromEditor = (editor: Editor): Types.TemplateField[] => {
2929
return tags.map((entry: any) => {
3030
const node = entry?.node ?? entry;
3131
const attrs = node?.attrs ?? {};
32+
const nodeType = node?.type?.name || "";
33+
const mode = nodeType.includes("Block") ? "block" : "inline";
3234

3335
return {
3436
id: attrs.id,
3537
alias: attrs.alias || attrs.label || "",
3638
tag: attrs.tag,
39+
mode,
3740
} as Types.TemplateField;
3841
});
3942
};
@@ -55,7 +58,8 @@ const areTemplateFieldsEqual = (
5558
left.id !== right.id ||
5659
left.alias !== right.alias ||
5760
left.tag !== right.tag ||
58-
left.position !== right.position
61+
left.position !== right.position ||
62+
left.mode !== right.mode
5963
) {
6064
return false;
6165
}
@@ -522,12 +526,15 @@ const SuperDocTemplateBuilder = forwardRef<
522526
menuTriggerFromRef.current = null;
523527
resetMenuFilter();
524528

529+
const mode = (field.metadata?.mode as "inline" | "block") || "inline";
530+
525531
if (field.id.startsWith("custom_") && onFieldCreate) {
526532
try {
527533
const createdField = await onFieldCreate(field);
528534

529535
if (createdField) {
530-
insertFieldInternal("inline", {
536+
const createdMode = (createdField.metadata?.mode as "inline" | "block") || mode;
537+
insertFieldInternal(createdMode, {
531538
alias: createdField.label,
532539
category: createdField.category,
533540
metadata: createdField.metadata,
@@ -541,7 +548,7 @@ const SuperDocTemplateBuilder = forwardRef<
541548
}
542549
}
543550

544-
insertFieldInternal("inline", {
551+
insertFieldInternal(mode, {
545552
alias: field.label,
546553
category: field.category,
547554
metadata: field.metadata,

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface TemplateField {
1313
alias: string;
1414
tag?: string;
1515
position?: number;
16+
mode?: "inline" | "block";
1617
}
1718

1819
export interface TriggerEvent {

0 commit comments

Comments
 (0)