@saastro/forms 0.2.0 → 0.2.1
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/cli.js +129 -2
- package/dist/{DateRenderers-3JUQNLKJ.js → DateRenderers-QKRBXFC6.js} +2 -2
- package/dist/{chunk-GHDCNAWC.js → chunk-G2ZSBYVS.js} +4 -2
- package/dist/{chunk-GHDCNAWC.js.map → chunk-G2ZSBYVS.js.map} +1 -1
- package/dist/index.d.ts +86 -2
- package/dist/index.js +237 -5
- package/dist/index.js.map +1 -1
- package/package.json +10 -5
- /package/dist/{DateRenderers-3JUQNLKJ.js.map → DateRenderers-QKRBXFC6.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
useHasComponentProvider,
|
|
12
12
|
usePartialComponents,
|
|
13
13
|
withComponents
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-G2ZSBYVS.js";
|
|
15
15
|
import {
|
|
16
16
|
applyBuiltinTransform,
|
|
17
17
|
applyFieldMapping,
|
|
@@ -1362,7 +1362,7 @@ function renderSwitchGroupField(fieldConfig, ctx) {
|
|
|
1362
1362
|
import { Suspense, lazy } from "react";
|
|
1363
1363
|
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1364
1364
|
var DateRenderersLazy = lazy(
|
|
1365
|
-
() => import("./DateRenderers-
|
|
1365
|
+
() => import("./DateRenderers-QKRBXFC6.js").then((m) => ({ default: m.DateRenderers }))
|
|
1366
1366
|
);
|
|
1367
1367
|
function renderDateField(fieldConfig, ctx, control, name) {
|
|
1368
1368
|
return /* @__PURE__ */ jsx7(
|
|
@@ -6799,6 +6799,165 @@ var BUILTIN_RESOLVERS = [
|
|
|
6799
6799
|
{ id: "urlParam", label: "URL Parameter", description: "Value from a URL query parameter" }
|
|
6800
6800
|
];
|
|
6801
6801
|
|
|
6802
|
+
// src/templates/contact.ts
|
|
6803
|
+
function createContactTemplate() {
|
|
6804
|
+
return FormBuilder.create("contact").layout("auto").columns(1).gap(4).addField(
|
|
6805
|
+
"name",
|
|
6806
|
+
(f) => f.type("text").label("Name").placeholder("Your full name").required("Please enter your name").minLength(2, "Name must be at least 2 characters")
|
|
6807
|
+
).addField(
|
|
6808
|
+
"email",
|
|
6809
|
+
(f) => f.type("email").label("Email").placeholder("you@example.com").required("Please enter your email").email("Please enter a valid email address")
|
|
6810
|
+
).addField(
|
|
6811
|
+
"message",
|
|
6812
|
+
(f) => f.type("textarea").label("Message").placeholder("How can we help?").required("Please write a short message").minLength(10, "Message must be at least 10 characters")
|
|
6813
|
+
).addStep("main", ["name", "email", "message"]).initialStep("main").buttons({
|
|
6814
|
+
submit: { type: "submit", label: "Send message" },
|
|
6815
|
+
align: "end"
|
|
6816
|
+
}).build();
|
|
6817
|
+
}
|
|
6818
|
+
|
|
6819
|
+
// src/templates/newsletter.ts
|
|
6820
|
+
function createNewsletterTemplate() {
|
|
6821
|
+
return FormBuilder.create("newsletter").layout("auto").columns(1).gap(4).addField(
|
|
6822
|
+
"email",
|
|
6823
|
+
(f) => f.type("email").label("Email").placeholder("you@example.com").required("Please enter your email").email("Please enter a valid email address")
|
|
6824
|
+
).addField(
|
|
6825
|
+
"consent",
|
|
6826
|
+
(f) => f.type("checkbox").label("I agree to receive newsletter emails").required("You must agree to receive the newsletter")
|
|
6827
|
+
).addStep("main", ["email", "consent"]).initialStep("main").buttons({
|
|
6828
|
+
submit: { type: "submit", label: "Subscribe" },
|
|
6829
|
+
align: "end"
|
|
6830
|
+
}).build();
|
|
6831
|
+
}
|
|
6832
|
+
|
|
6833
|
+
// src/templates/lead-gen.ts
|
|
6834
|
+
function createLeadGenTemplate() {
|
|
6835
|
+
return FormBuilder.create("lead-gen").layout("auto").columns(2).gap(4).addField(
|
|
6836
|
+
"name",
|
|
6837
|
+
(f) => f.type("text").label("Full name").placeholder("Jane Doe").required("Please enter your name").minLength(2, "Name must be at least 2 characters").columns({ default: 1 })
|
|
6838
|
+
).addField(
|
|
6839
|
+
"email",
|
|
6840
|
+
(f) => f.type("email").label("Work email").placeholder("jane@acme.com").required("Please enter your email").email("Please enter a valid email address").columns({ default: 1 })
|
|
6841
|
+
).addField(
|
|
6842
|
+
"phone",
|
|
6843
|
+
(f) => f.type("tel").label("Phone").placeholder("+1 555 0123").optional().columns({ default: 1 })
|
|
6844
|
+
).addField(
|
|
6845
|
+
"company",
|
|
6846
|
+
(f) => f.type("text").label("Company").placeholder("Acme Inc.").optional().columns({ default: 1 })
|
|
6847
|
+
).addField(
|
|
6848
|
+
"message",
|
|
6849
|
+
(f) => f.type("textarea").label("What are you looking to solve?").placeholder("A few words about your project or use case").required("Please describe your need briefly").minLength(10, "Message must be at least 10 characters").columns({ default: 2 })
|
|
6850
|
+
).addStep("main", ["name", "email", "phone", "company", "message"]).initialStep("main").buttons({
|
|
6851
|
+
submit: { type: "submit", label: "Request a call" },
|
|
6852
|
+
align: "end"
|
|
6853
|
+
}).build();
|
|
6854
|
+
}
|
|
6855
|
+
|
|
6856
|
+
// src/templates/event-rsvp.ts
|
|
6857
|
+
function createEventRsvpTemplate() {
|
|
6858
|
+
return FormBuilder.create("event-rsvp").layout("auto").columns(2).gap(4).addField(
|
|
6859
|
+
"name",
|
|
6860
|
+
(f) => f.type("text").label("Full name").placeholder("Jane Doe").required("Please enter your name").minLength(2, "Name must be at least 2 characters").columns({ default: 1 })
|
|
6861
|
+
).addField(
|
|
6862
|
+
"email",
|
|
6863
|
+
(f) => f.type("email").label("Email").placeholder("jane@example.com").required("Please enter your email").email("Please enter a valid email address").columns({ default: 1 })
|
|
6864
|
+
).addField(
|
|
6865
|
+
"attending",
|
|
6866
|
+
(f) => f.type("radio").label("Will you attend?").options([
|
|
6867
|
+
{ label: "Yes, I will be there", value: "yes" },
|
|
6868
|
+
{ label: "No, I cannot make it", value: "no" },
|
|
6869
|
+
{ label: "Not sure yet", value: "maybe" }
|
|
6870
|
+
]).required("Please pick one").columns({ default: 2 })
|
|
6871
|
+
).addField(
|
|
6872
|
+
"guests",
|
|
6873
|
+
(f) => f.type("number").label("Number of guests (including yourself)").min(1).max(10).optional().columns({ default: 1 })
|
|
6874
|
+
).addField(
|
|
6875
|
+
"dietary",
|
|
6876
|
+
(f) => f.type("textarea").label("Dietary notes").placeholder("Allergies, preferences, etc.").optional().columns({ default: 2 })
|
|
6877
|
+
).addStep("main", ["name", "email", "attending", "guests", "dietary"]).initialStep("main").buttons({
|
|
6878
|
+
submit: { type: "submit", label: "Send RSVP" },
|
|
6879
|
+
align: "end"
|
|
6880
|
+
}).build();
|
|
6881
|
+
}
|
|
6882
|
+
|
|
6883
|
+
// src/templates/quote-request.ts
|
|
6884
|
+
function createQuoteRequestTemplate() {
|
|
6885
|
+
return FormBuilder.create("quote-request").layout("auto").columns(2).gap(4).addField(
|
|
6886
|
+
"name",
|
|
6887
|
+
(f) => f.type("text").label("Full name").placeholder("Jane Doe").required("Please enter your name").minLength(2, "Name must be at least 2 characters").columns({ default: 1 })
|
|
6888
|
+
).addField(
|
|
6889
|
+
"email",
|
|
6890
|
+
(f) => f.type("email").label("Work email").placeholder("jane@acme.com").required("Please enter your email").email("Please enter a valid email address").columns({ default: 1 })
|
|
6891
|
+
).addField(
|
|
6892
|
+
"company",
|
|
6893
|
+
(f) => f.type("text").label("Company").placeholder("Acme Inc.").required("Please enter your company name").columns({ default: 1 })
|
|
6894
|
+
).addField(
|
|
6895
|
+
"service",
|
|
6896
|
+
(f) => f.type("select").label("Service type").placeholder("Pick the closest match").options([
|
|
6897
|
+
{ label: "Design", value: "design" },
|
|
6898
|
+
{ label: "Development", value: "development" },
|
|
6899
|
+
{ label: "Consulting", value: "consulting" },
|
|
6900
|
+
{ label: "Other", value: "other" }
|
|
6901
|
+
]).required("Please pick a service").columns({ default: 1 })
|
|
6902
|
+
).addField(
|
|
6903
|
+
"budget",
|
|
6904
|
+
(f) => f.type("select").label("Estimated budget").placeholder("Pick a range").options([
|
|
6905
|
+
{ label: "Under $5k", value: "under-5k" },
|
|
6906
|
+
{ label: "$5k \u2013 $25k", value: "5k-25k" },
|
|
6907
|
+
{ label: "$25k \u2013 $100k", value: "25k-100k" },
|
|
6908
|
+
{ label: "$100k+", value: "100k+" },
|
|
6909
|
+
{ label: "Not sure yet", value: "unknown" }
|
|
6910
|
+
]).required("Please pick a budget range").columns({ default: 2 })
|
|
6911
|
+
).addField(
|
|
6912
|
+
"details",
|
|
6913
|
+
(f) => f.type("textarea").label("Project details").placeholder("Goals, timeline, anything we should know").required("Please share a few sentences about the project").minLength(20, "Project details must be at least 20 characters").columns({ default: 2 })
|
|
6914
|
+
).addStep("main", ["name", "email", "company", "service", "budget", "details"]).initialStep("main").buttons({
|
|
6915
|
+
submit: { type: "submit", label: "Request a quote" },
|
|
6916
|
+
align: "end"
|
|
6917
|
+
}).build();
|
|
6918
|
+
}
|
|
6919
|
+
|
|
6920
|
+
// src/templates/index.ts
|
|
6921
|
+
var TEMPLATES = {
|
|
6922
|
+
contact: createContactTemplate,
|
|
6923
|
+
newsletter: createNewsletterTemplate,
|
|
6924
|
+
"lead-gen": createLeadGenTemplate,
|
|
6925
|
+
"event-rsvp": createEventRsvpTemplate,
|
|
6926
|
+
"quote-request": createQuoteRequestTemplate
|
|
6927
|
+
};
|
|
6928
|
+
var TEMPLATE_META = [
|
|
6929
|
+
{
|
|
6930
|
+
id: "contact",
|
|
6931
|
+
label: "Contact",
|
|
6932
|
+
description: "Name, email, and a message. The classic three-field form.",
|
|
6933
|
+
fieldCount: 3
|
|
6934
|
+
},
|
|
6935
|
+
{
|
|
6936
|
+
id: "newsletter",
|
|
6937
|
+
label: "Newsletter",
|
|
6938
|
+
description: "Email plus a GDPR-friendly consent checkbox.",
|
|
6939
|
+
fieldCount: 2
|
|
6940
|
+
},
|
|
6941
|
+
{
|
|
6942
|
+
id: "lead-gen",
|
|
6943
|
+
label: "Lead generation",
|
|
6944
|
+
description: "Name, work email, phone, company, and a brief message.",
|
|
6945
|
+
fieldCount: 5
|
|
6946
|
+
},
|
|
6947
|
+
{
|
|
6948
|
+
id: "event-rsvp",
|
|
6949
|
+
label: "Event RSVP",
|
|
6950
|
+
description: "Name, email, attendance answer, guest count, and dietary notes.",
|
|
6951
|
+
fieldCount: 5
|
|
6952
|
+
},
|
|
6953
|
+
{
|
|
6954
|
+
id: "quote-request",
|
|
6955
|
+
label: "Quote request",
|
|
6956
|
+
description: "Contact info plus service type, budget range, and a details field.",
|
|
6957
|
+
fieldCount: 6
|
|
6958
|
+
}
|
|
6959
|
+
];
|
|
6960
|
+
|
|
6802
6961
|
// src/lib/createHubFormSubmit.ts
|
|
6803
6962
|
function publicBase({ hubUrl, siteId, formSlug }) {
|
|
6804
6963
|
const cleanHub = hubUrl.replace(/\/+$/, "");
|
|
@@ -6894,14 +7053,31 @@ function createHubFormSubmit(opts) {
|
|
|
6894
7053
|
}
|
|
6895
7054
|
|
|
6896
7055
|
// src/components/HubForm.tsx
|
|
6897
|
-
import { useEffect as useEffect8, useState as useState5 } from "react";
|
|
7056
|
+
import { useEffect as useEffect8, useMemo as useMemo7, useState as useState5 } from "react";
|
|
6898
7057
|
import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
7058
|
+
function isRenderableSchema(value) {
|
|
7059
|
+
if (!value || typeof value !== "object") return false;
|
|
7060
|
+
const schema = value;
|
|
7061
|
+
const fields = schema.fields;
|
|
7062
|
+
const steps = schema.steps;
|
|
7063
|
+
if (!fields || typeof fields !== "object" || Object.keys(fields).length === 0) {
|
|
7064
|
+
return false;
|
|
7065
|
+
}
|
|
7066
|
+
if (!steps || typeof steps !== "object" || Object.keys(steps).length === 0) {
|
|
7067
|
+
return false;
|
|
7068
|
+
}
|
|
7069
|
+
return true;
|
|
7070
|
+
}
|
|
6899
7071
|
function HubForm({
|
|
6900
7072
|
hubUrl,
|
|
6901
7073
|
siteId,
|
|
6902
7074
|
formSlug,
|
|
6903
7075
|
loadingFallback,
|
|
6904
7076
|
errorFallback,
|
|
7077
|
+
unconfiguredFallback,
|
|
7078
|
+
successFallback,
|
|
7079
|
+
onSuccess,
|
|
7080
|
+
onError,
|
|
6905
7081
|
formProps
|
|
6906
7082
|
}) {
|
|
6907
7083
|
const [state, setState] = useState5({ status: "loading" });
|
|
@@ -6913,7 +7089,12 @@ function HubForm({
|
|
|
6913
7089
|
if (!res.ok) throw new Error(`schema fetch failed: ${res.status} ${res.statusText}`);
|
|
6914
7090
|
return res.json();
|
|
6915
7091
|
}).then((schema) => {
|
|
6916
|
-
if (
|
|
7092
|
+
if (cancelled) return;
|
|
7093
|
+
if (isRenderableSchema(schema)) {
|
|
7094
|
+
setState({ status: "ready", schema });
|
|
7095
|
+
} else {
|
|
7096
|
+
setState({ status: "unconfigured" });
|
|
7097
|
+
}
|
|
6917
7098
|
}).catch((err) => {
|
|
6918
7099
|
if (!cancelled) {
|
|
6919
7100
|
setState({
|
|
@@ -6926,6 +7107,23 @@ function HubForm({
|
|
|
6926
7107
|
cancelled = true;
|
|
6927
7108
|
};
|
|
6928
7109
|
}, [hubUrl, siteId, formSlug]);
|
|
7110
|
+
const wrappedSubmit = useMemo7(() => {
|
|
7111
|
+
const base = createHubFormSubmit({ hubUrl, siteId, formSlug });
|
|
7112
|
+
return {
|
|
7113
|
+
type: "custom",
|
|
7114
|
+
async onSubmit(values) {
|
|
7115
|
+
try {
|
|
7116
|
+
await base.onSubmit(values);
|
|
7117
|
+
onSuccess?.(values);
|
|
7118
|
+
setState({ status: "submitted" });
|
|
7119
|
+
} catch (err) {
|
|
7120
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
7121
|
+
onError?.(error);
|
|
7122
|
+
throw error;
|
|
7123
|
+
}
|
|
7124
|
+
}
|
|
7125
|
+
};
|
|
7126
|
+
}, [hubUrl, siteId, formSlug, onSuccess, onError]);
|
|
6929
7127
|
if (state.status === "loading") {
|
|
6930
7128
|
return loadingFallback ?? /* @__PURE__ */ jsx14("div", { "data-saastro-hubform-loading": true, style: loadingStyle, children: "Loading\u2026" });
|
|
6931
7129
|
}
|
|
@@ -6936,9 +7134,17 @@ function HubForm({
|
|
|
6936
7134
|
state.error
|
|
6937
7135
|
] });
|
|
6938
7136
|
}
|
|
7137
|
+
if (state.status === "unconfigured") {
|
|
7138
|
+
if (unconfiguredFallback !== void 0) return /* @__PURE__ */ jsx14(Fragment3, { children: unconfiguredFallback });
|
|
7139
|
+
return /* @__PURE__ */ jsx14("div", { role: "status", style: unconfiguredStyle, "data-saastro-hubform-unconfigured": true, children: "This form has not been configured yet. Open it in the Hub builder to add fields." });
|
|
7140
|
+
}
|
|
7141
|
+
if (state.status === "submitted") {
|
|
7142
|
+
if (successFallback !== void 0) return /* @__PURE__ */ jsx14(Fragment3, { children: successFallback });
|
|
7143
|
+
return /* @__PURE__ */ jsx14("div", { role: "status", style: successStyle, "data-saastro-hubform-submitted": true, children: "Thanks \u2014 we'll get back to you soon." });
|
|
7144
|
+
}
|
|
6939
7145
|
const config = {
|
|
6940
7146
|
...state.schema,
|
|
6941
|
-
submit:
|
|
7147
|
+
submit: wrappedSubmit
|
|
6942
7148
|
};
|
|
6943
7149
|
return /* @__PURE__ */ jsx14(Form, { ...formProps, config });
|
|
6944
7150
|
}
|
|
@@ -6958,6 +7164,25 @@ var errorStyle = {
|
|
|
6958
7164
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
6959
7165
|
fontSize: "0.875rem"
|
|
6960
7166
|
};
|
|
7167
|
+
var unconfiguredStyle = {
|
|
7168
|
+
padding: "1rem",
|
|
7169
|
+
background: "#fffbeb",
|
|
7170
|
+
color: "#92400e",
|
|
7171
|
+
border: "1px solid #fcd34d",
|
|
7172
|
+
borderRadius: "0.375rem",
|
|
7173
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
7174
|
+
fontSize: "0.875rem"
|
|
7175
|
+
};
|
|
7176
|
+
var successStyle = {
|
|
7177
|
+
padding: "1.25rem 1rem",
|
|
7178
|
+
background: "#ecfdf5",
|
|
7179
|
+
color: "#065f46",
|
|
7180
|
+
border: "1px solid #6ee7b7",
|
|
7181
|
+
borderRadius: "0.375rem",
|
|
7182
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
7183
|
+
fontSize: "0.95rem",
|
|
7184
|
+
textAlign: "center"
|
|
7185
|
+
};
|
|
6961
7186
|
|
|
6962
7187
|
// src/utils/testDataGenerator.ts
|
|
6963
7188
|
var SPANISH_PATTERNS = [
|
|
@@ -7198,6 +7423,8 @@ export {
|
|
|
7198
7423
|
StepsAccordion,
|
|
7199
7424
|
StepsNavigation,
|
|
7200
7425
|
StepsProgress,
|
|
7426
|
+
TEMPLATES,
|
|
7427
|
+
TEMPLATE_META,
|
|
7201
7428
|
TYPE_SPECIFIC_PROPERTIES,
|
|
7202
7429
|
VALIDATION_METHODS,
|
|
7203
7430
|
analyticsPlugin,
|
|
@@ -7211,8 +7438,13 @@ export {
|
|
|
7211
7438
|
configureComponents,
|
|
7212
7439
|
coreComponents,
|
|
7213
7440
|
createComponentRegistry,
|
|
7441
|
+
createContactTemplate,
|
|
7442
|
+
createEventRsvpTemplate,
|
|
7214
7443
|
createHubFormSubmit,
|
|
7444
|
+
createLeadGenTemplate,
|
|
7215
7445
|
createMissingComponentPlaceholder,
|
|
7446
|
+
createNewsletterTemplate,
|
|
7447
|
+
createQuoteRequestTemplate,
|
|
7216
7448
|
createShadcnRegistry,
|
|
7217
7449
|
databowlAction,
|
|
7218
7450
|
databowlPlugin,
|