form-page-builder 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/index.cjs +14 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +13 -51
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -619,6 +619,8 @@ interface TemplateChange {
|
|
|
619
619
|
interface FormBuilderFeatures {
|
|
620
620
|
/** Editable form title input in the Toolbar. Default true. */
|
|
621
621
|
naming?: boolean;
|
|
622
|
+
/** Render the form title as a heading above the fields in Preview. Default false — the host usually shows the form name in its own chrome. */
|
|
623
|
+
formTitle?: boolean;
|
|
622
624
|
/**
|
|
623
625
|
* Templates library. `true` (default) = full CRUD + toolbar "Save"; `false` = hidden.
|
|
624
626
|
* `{ manage: false }` = pick-and-apply only (no save/overwrite/delete). `{ max }` caps the count (default 5).
|
|
@@ -698,6 +700,9 @@ declare function serializeTemplate(document: FormDocument): string;
|
|
|
698
700
|
/** Accepts a `serializeTemplate` envelope or a bare document (e.g. "View JSON" output); `null` if not a document. */
|
|
699
701
|
declare function parseTemplate(raw: string | null | undefined): DocumentFields | null;
|
|
700
702
|
|
|
703
|
+
/** Current document schema version — stamped on everything persisted. */
|
|
704
|
+
declare const DOCUMENT_VERSION: 5;
|
|
705
|
+
|
|
701
706
|
declare const DRAFT_KEY = "form-page-builder:draft";
|
|
702
707
|
declare const INDEX_KEY = "form-page-builder:index";
|
|
703
708
|
declare const formKey: (id: string) => string;
|
|
@@ -706,4 +711,4 @@ declare const savedFormId: (key: string) => string | null;
|
|
|
706
711
|
/** Copy/paste-template scratch slot — always localStorage, never the StorageAdapter. */
|
|
707
712
|
declare const CLIPBOARD_KEY = "form-page-builder:clipboard";
|
|
708
713
|
|
|
709
|
-
export { CLIPBOARD_KEY, type CheckboxField, type CheckboxGroupField, type ChromeShape, type ContentBlockType, DARK_THEME, DEFAULT_THEME, DRAFT_KEY, type DocumentFields, type FieldPatch, type FieldType, FormBuilder, type FormBuilderFeatures, type FormBuilderHandle, type FormBuilderProps, type FormDocument, type FormField, type FormTemplate, INDEX_KEY, type ImageField, type InputField, type InputFieldType, type LanguageOption, type LocalizedString, type Option, type ParagraphField, type RadioField, type SavedFormMeta, type Section, type SelectField, type StorageAdapter, type StringsShape, type SubmitPayload, type SubmitStyle, type TemplateChange, type TextareaField, type Theme, type ThemeLayout, type ThemeOverrides, type ToggleField, FormBuilder as default, formKey, localStorageAdapter, parseTemplate, savedFormId, serializeTemplate };
|
|
714
|
+
export { CLIPBOARD_KEY, type CheckboxField, type CheckboxGroupField, type ChromeShape, type ContentBlockType, DARK_THEME, DEFAULT_THEME, DOCUMENT_VERSION, DRAFT_KEY, type DocumentFields, type FieldPatch, type FieldType, FormBuilder, type FormBuilderFeatures, type FormBuilderHandle, type FormBuilderProps, type FormDocument, type FormField, type FormTemplate, INDEX_KEY, type ImageField, type InputField, type InputFieldType, type LanguageOption, type LocalizedString, type Option, type ParagraphField, type RadioField, type SavedFormMeta, type Section, type SelectField, type StorageAdapter, type StringsShape, type SubmitPayload, type SubmitStyle, type TemplateChange, type TextareaField, type Theme, type ThemeLayout, type ThemeOverrides, type ToggleField, FormBuilder as default, formKey, localStorageAdapter, parseTemplate, savedFormId, serializeTemplate };
|
package/dist/index.d.ts
CHANGED
|
@@ -619,6 +619,8 @@ interface TemplateChange {
|
|
|
619
619
|
interface FormBuilderFeatures {
|
|
620
620
|
/** Editable form title input in the Toolbar. Default true. */
|
|
621
621
|
naming?: boolean;
|
|
622
|
+
/** Render the form title as a heading above the fields in Preview. Default false — the host usually shows the form name in its own chrome. */
|
|
623
|
+
formTitle?: boolean;
|
|
622
624
|
/**
|
|
623
625
|
* Templates library. `true` (default) = full CRUD + toolbar "Save"; `false` = hidden.
|
|
624
626
|
* `{ manage: false }` = pick-and-apply only (no save/overwrite/delete). `{ max }` caps the count (default 5).
|
|
@@ -698,6 +700,9 @@ declare function serializeTemplate(document: FormDocument): string;
|
|
|
698
700
|
/** Accepts a `serializeTemplate` envelope or a bare document (e.g. "View JSON" output); `null` if not a document. */
|
|
699
701
|
declare function parseTemplate(raw: string | null | undefined): DocumentFields | null;
|
|
700
702
|
|
|
703
|
+
/** Current document schema version — stamped on everything persisted. */
|
|
704
|
+
declare const DOCUMENT_VERSION: 5;
|
|
705
|
+
|
|
701
706
|
declare const DRAFT_KEY = "form-page-builder:draft";
|
|
702
707
|
declare const INDEX_KEY = "form-page-builder:index";
|
|
703
708
|
declare const formKey: (id: string) => string;
|
|
@@ -706,4 +711,4 @@ declare const savedFormId: (key: string) => string | null;
|
|
|
706
711
|
/** Copy/paste-template scratch slot — always localStorage, never the StorageAdapter. */
|
|
707
712
|
declare const CLIPBOARD_KEY = "form-page-builder:clipboard";
|
|
708
713
|
|
|
709
|
-
export { CLIPBOARD_KEY, type CheckboxField, type CheckboxGroupField, type ChromeShape, type ContentBlockType, DARK_THEME, DEFAULT_THEME, DRAFT_KEY, type DocumentFields, type FieldPatch, type FieldType, FormBuilder, type FormBuilderFeatures, type FormBuilderHandle, type FormBuilderProps, type FormDocument, type FormField, type FormTemplate, INDEX_KEY, type ImageField, type InputField, type InputFieldType, type LanguageOption, type LocalizedString, type Option, type ParagraphField, type RadioField, type SavedFormMeta, type Section, type SelectField, type StorageAdapter, type StringsShape, type SubmitPayload, type SubmitStyle, type TemplateChange, type TextareaField, type Theme, type ThemeLayout, type ThemeOverrides, type ToggleField, FormBuilder as default, formKey, localStorageAdapter, parseTemplate, savedFormId, serializeTemplate };
|
|
714
|
+
export { CLIPBOARD_KEY, type CheckboxField, type CheckboxGroupField, type ChromeShape, type ContentBlockType, DARK_THEME, DEFAULT_THEME, DOCUMENT_VERSION, DRAFT_KEY, type DocumentFields, type FieldPatch, type FieldType, FormBuilder, type FormBuilderFeatures, type FormBuilderHandle, type FormBuilderProps, type FormDocument, type FormField, type FormTemplate, INDEX_KEY, type ImageField, type InputField, type InputFieldType, type LanguageOption, type LocalizedString, type Option, type ParagraphField, type RadioField, type SavedFormMeta, type Section, type SelectField, type StorageAdapter, type StringsShape, type SubmitPayload, type SubmitStyle, type TemplateChange, type TextareaField, type Theme, type ThemeLayout, type ThemeOverrides, type ToggleField, FormBuilder as default, formKey, localStorageAdapter, parseTemplate, savedFormId, serializeTemplate };
|
package/dist/index.js
CHANGED
|
@@ -558,12 +558,8 @@ function defaultSection(titleEn = "") {
|
|
|
558
558
|
return { id: genSectionId(), title: bi(titleEn, ""), background: "", collapsed: false, fields: [] };
|
|
559
559
|
}
|
|
560
560
|
|
|
561
|
-
// src/lib/submittable.ts
|
|
562
|
-
function sectionHasFormFields(section) {
|
|
563
|
-
return section.fields.some((f) => !getMeta(f.type).isContent);
|
|
564
|
-
}
|
|
565
|
-
|
|
566
561
|
// src/lib/migrate.ts
|
|
562
|
+
var DOCUMENT_VERSION = 5;
|
|
567
563
|
function migrateField(field) {
|
|
568
564
|
let f = { ...field };
|
|
569
565
|
if (LEGACY_INPUT_TYPES.includes(f.type)) f = { ...f, type: "input", inputType: f.type };
|
|
@@ -594,25 +590,6 @@ function migrateField(field) {
|
|
|
594
590
|
function migrateFields(fields) {
|
|
595
591
|
return (fields || []).map(migrateField);
|
|
596
592
|
}
|
|
597
|
-
function synthesizeButtonField(label, style, scope) {
|
|
598
|
-
const resolvedLabel = typeof label === "string" && label ? bi(label) : label && typeof label === "object" && (label.en || label.ja) ? label : bi("Submit", "");
|
|
599
|
-
return {
|
|
600
|
-
id: nextId(),
|
|
601
|
-
type: "button",
|
|
602
|
-
label: resolvedLabel,
|
|
603
|
-
hideLabel: false,
|
|
604
|
-
width: "1/1",
|
|
605
|
-
verticalAlign: "top",
|
|
606
|
-
labelPosition: "top",
|
|
607
|
-
showIcon: false,
|
|
608
|
-
displayIcon: "Type",
|
|
609
|
-
action: "submit",
|
|
610
|
-
submitScope: scope,
|
|
611
|
-
buttonStyle: style || { color: "", size: "md" },
|
|
612
|
-
href: "",
|
|
613
|
-
target: "_self"
|
|
614
|
-
};
|
|
615
|
-
}
|
|
616
593
|
function migrateDocument(raw) {
|
|
617
594
|
if (!raw) return null;
|
|
618
595
|
const title = typeof raw.title === "string" ? bi(raw.title) : raw.title || bi();
|
|
@@ -629,25 +606,6 @@ function migrateDocument(raw) {
|
|
|
629
606
|
} else {
|
|
630
607
|
sections = [{ ...defaultSection(), fields: migrateFields(raw.fields || []) }];
|
|
631
608
|
}
|
|
632
|
-
const legacy = raw.version === void 0 || raw.version < 5;
|
|
633
|
-
if (legacy) {
|
|
634
|
-
resyncIdCounter(sections.flatMap((s) => s.fields));
|
|
635
|
-
const submitMode = raw.submitMode === "perSection" ? "perSection" : "combined";
|
|
636
|
-
const submitLabel = raw.submitLabel;
|
|
637
|
-
const submitStyle = raw.submitStyle || { color: "", size: "md" };
|
|
638
|
-
if (submitMode === "perSection" && raw.sections) {
|
|
639
|
-
sections = sections.map((s, i) => {
|
|
640
|
-
if (!sectionHasFormFields(s)) return s;
|
|
641
|
-
const rawSection = raw.sections[i] || {};
|
|
642
|
-
const label = rawSection.submitLabel || submitLabel;
|
|
643
|
-
const style = rawSection.submitStyle || submitStyle;
|
|
644
|
-
return { ...s, fields: [...s.fields, synthesizeButtonField(label, style, "section")] };
|
|
645
|
-
});
|
|
646
|
-
} else if (sections.some(sectionHasFormFields)) {
|
|
647
|
-
const lastIdx = sections.length - 1;
|
|
648
|
-
sections = sections.map((s, i) => i === lastIdx ? { ...s, fields: [...s.fields, synthesizeButtonField(submitLabel, submitStyle, "form")] } : s);
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
609
|
return { title, themeOverrides, sections };
|
|
652
610
|
}
|
|
653
611
|
|
|
@@ -675,6 +633,7 @@ function parseTemplate(raw) {
|
|
|
675
633
|
var DEFAULT_MAX_TEMPLATES = 5;
|
|
676
634
|
var DEFAULT_FEATURES = {
|
|
677
635
|
naming: true,
|
|
636
|
+
formTitle: false,
|
|
678
637
|
templates: { enabled: true, manage: true, max: DEFAULT_MAX_TEMPLATES },
|
|
679
638
|
templateClipboard: true,
|
|
680
639
|
newForm: true,
|
|
@@ -1038,7 +997,7 @@ function usePersistence({
|
|
|
1038
997
|
if (autosaveTimer.current) clearTimeout(autosaveTimer.current);
|
|
1039
998
|
autosaveTimer.current = setTimeout(async () => {
|
|
1040
999
|
try {
|
|
1041
|
-
await storage.set(DRAFT_KEY, JSON.stringify({ ...document2, currentFormId }));
|
|
1000
|
+
await storage.set(DRAFT_KEY, JSON.stringify({ version: DOCUMENT_VERSION, ...document2, currentFormId }));
|
|
1042
1001
|
setSaveState("saved");
|
|
1043
1002
|
} catch {
|
|
1044
1003
|
setSaveState("error");
|
|
@@ -1061,7 +1020,7 @@ function usePersistence({
|
|
|
1061
1020
|
try {
|
|
1062
1021
|
const newTitle = bi(name, "");
|
|
1063
1022
|
const docToSave = { ...document2, title: newTitle };
|
|
1064
|
-
await storage.set(formKey(id), JSON.stringify({ ...docToSave, id, updatedAt: now }));
|
|
1023
|
+
await storage.set(formKey(id), JSON.stringify({ version: DOCUMENT_VERSION, ...docToSave, id, updatedAt: now }));
|
|
1065
1024
|
const next = [...savedForms, { id, title: name, updatedAt: now }];
|
|
1066
1025
|
await storage.set(INDEX_KEY, JSON.stringify(next));
|
|
1067
1026
|
setSavedForms(next);
|
|
@@ -1084,7 +1043,7 @@ function usePersistence({
|
|
|
1084
1043
|
const now = Date.now();
|
|
1085
1044
|
setTemplateState("saving");
|
|
1086
1045
|
try {
|
|
1087
|
-
await storage.set(formKey(currentFormId), JSON.stringify({ ...document2, id: currentFormId, updatedAt: now }));
|
|
1046
|
+
await storage.set(formKey(currentFormId), JSON.stringify({ version: DOCUMENT_VERSION, ...document2, id: currentFormId, updatedAt: now }));
|
|
1088
1047
|
const next = savedForms.map((f) => f.id === currentFormId ? { ...f, title: t(document2.title, "en"), updatedAt: now } : f);
|
|
1089
1048
|
setSavedForms(next);
|
|
1090
1049
|
await storage.set(INDEX_KEY, JSON.stringify(next));
|
|
@@ -1909,6 +1868,8 @@ function FieldTicket({
|
|
|
1909
1868
|
{
|
|
1910
1869
|
...dropZoneHandlers,
|
|
1911
1870
|
onClick: onSelect,
|
|
1871
|
+
className: `fb-field fb-field--${field.type} fb-field--${field.id}`,
|
|
1872
|
+
"data-field-id": field.id,
|
|
1912
1873
|
style: {
|
|
1913
1874
|
...styles.ticket,
|
|
1914
1875
|
flex: `1 1 calc(${widthPct} - 10px)`,
|
|
@@ -2438,16 +2399,16 @@ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome
|
|
|
2438
2399
|
return /* @__PURE__ */ jsxs12("div", { style: styles.previewWrap, children: [
|
|
2439
2400
|
/* @__PURE__ */ jsxs12("div", { style: { width: "100%", maxWidth, display: "flex", flexDirection: "column", alignItems: "center" }, children: [
|
|
2440
2401
|
features.deviceToggle && /* @__PURE__ */ jsx14("div", { style: styles.previewToolbar, children: /* @__PURE__ */ jsx14(Segmented, { options: deviceOptions, value: device, onChange: setDevice }) }),
|
|
2441
|
-
/* @__PURE__ */ jsxs12("div", { style: { ...styles.previewCard, maxWidth, width: "100%" }, children: [
|
|
2442
|
-
/* @__PURE__ */ jsx14("h2", { style: styles.previewTitle, children: t(title, language) }),
|
|
2402
|
+
/* @__PURE__ */ jsxs12("div", { className: "fb-form", style: { ...styles.previewCard, maxWidth, width: "100%" }, children: [
|
|
2403
|
+
features.formTitle && /* @__PURE__ */ jsx14("h2", { style: styles.previewTitle, children: t(title, language) }),
|
|
2443
2404
|
allFields.length === 0 && /* @__PURE__ */ jsx14("p", { style: { color: "var(--fb-muted)", fontSize: 14 }, children: strings.addFieldsHint }),
|
|
2444
2405
|
sections.map((section) => {
|
|
2445
|
-
return /* @__PURE__ */ jsxs12("div", { style: { background: section.background || "transparent", padding: section.background ? 16 : 0, borderRadius: section.background ? 10 : 0, marginBottom: "var(--fb-space-section)" }, children: [
|
|
2406
|
+
return /* @__PURE__ */ jsxs12("div", { className: "fb-section", "data-section-id": section.id, style: { background: section.background || "transparent", padding: section.background ? 16 : 0, borderRadius: section.background ? 10 : 0, marginBottom: "var(--fb-space-section)" }, children: [
|
|
2446
2407
|
t(section.title, language) && /* @__PURE__ */ jsx14("h3", { style: styles.sectionRuntimeTitle, children: t(section.title, language) }),
|
|
2447
2408
|
/* @__PURE__ */ jsx14("div", { style: styles.previewGrid, children: section.fields.map((field) => {
|
|
2448
2409
|
const width = effectiveWidth(field.width, device);
|
|
2449
2410
|
const flexBasis = `1 1 calc(${WIDTH_PERCENT[width]} - 14px)`;
|
|
2450
|
-
return /* @__PURE__ */ jsxs12("div", { style: { flex: flexBasis, minWidth: 0, alignSelf: ALIGN_MAP[field.verticalAlign || "top"] }, children: [
|
|
2411
|
+
return /* @__PURE__ */ jsxs12("div", { className: `fb-field fb-field--${field.type} fb-field--${field.id}`, "data-field-id": field.id, style: { flex: flexBasis, minWidth: 0, alignSelf: ALIGN_MAP[field.verticalAlign || "top"] }, children: [
|
|
2451
2412
|
/* @__PURE__ */ jsx14(FieldBlock, { field, lang: language, onFieldChange, strings, chrome, error: errors[field.id], onButtonAction: handleButtonAction }),
|
|
2452
2413
|
field.type === "button" && field.id === attemptedButtonId && Object.keys(errors).length > 0 && /* @__PURE__ */ jsxs12("p", { style: styles.formErrorNote, children: [
|
|
2453
2414
|
/* @__PURE__ */ jsx14(CircleAlert2, { size: 13 }),
|
|
@@ -2742,7 +2703,7 @@ var FormBuilder = forwardRef(function FormBuilder2({
|
|
|
2742
2703
|
ensureActiveSection: () => doc.setActiveSectionId((prev) => prev ?? doc.sections[0]?.id ?? null)
|
|
2743
2704
|
});
|
|
2744
2705
|
const jsonDoc = useMemo2(() => ({
|
|
2745
|
-
version:
|
|
2706
|
+
version: DOCUMENT_VERSION,
|
|
2746
2707
|
title: doc.title,
|
|
2747
2708
|
theme,
|
|
2748
2709
|
themeOverrides,
|
|
@@ -3019,6 +2980,7 @@ export {
|
|
|
3019
2980
|
CLIPBOARD_KEY,
|
|
3020
2981
|
DARK_THEME,
|
|
3021
2982
|
DEFAULT_THEME,
|
|
2983
|
+
DOCUMENT_VERSION,
|
|
3022
2984
|
DRAFT_KEY,
|
|
3023
2985
|
FormBuilder_default as FormBuilder,
|
|
3024
2986
|
INDEX_KEY,
|