@saastro/forms 0.3.0 → 0.5.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/dist/index.d.ts +39 -87
- package/dist/index.js +12 -172
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3717,100 +3717,48 @@ declare function executeSubmitActions(actions: SubmitActionNode[], values: Recor
|
|
|
3717
3717
|
declare function executeSubmitActionsByTrigger(config: FormConfig, triggerType: SubmitTriggerType, values: Record<string, unknown>, triggerValue?: string): Promise<SubmitActionsResult>;
|
|
3718
3718
|
|
|
3719
3719
|
/**
|
|
3720
|
-
*
|
|
3721
|
-
*
|
|
3722
|
-
*
|
|
3723
|
-
* (
|
|
3724
|
-
* Single step, single column.
|
|
3725
|
-
*/
|
|
3726
|
-
declare function createContactTemplate(): FormConfig;
|
|
3727
|
-
|
|
3728
|
-
/**
|
|
3729
|
-
* Newsletter signup template — email + consent.
|
|
3730
|
-
*
|
|
3731
|
-
* GDPR-friendly: a single email field plus an explicit checkbox the
|
|
3732
|
-
* subscriber has to tick (validation: must be true). Single step.
|
|
3733
|
-
*/
|
|
3734
|
-
declare function createNewsletterTemplate(): FormConfig;
|
|
3735
|
-
|
|
3736
|
-
/**
|
|
3737
|
-
* Lead-gen template — name, email, phone, company, message.
|
|
3738
|
-
*
|
|
3739
|
-
* Standard B2B lead-capture: required name + email, optional phone +
|
|
3740
|
-
* company (for context), and a message textarea. Two-column layout on
|
|
3741
|
-
* wide screens so the form doesn't feel huge.
|
|
3742
|
-
*/
|
|
3743
|
-
declare function createLeadGenTemplate(): FormConfig;
|
|
3744
|
-
|
|
3745
|
-
/**
|
|
3746
|
-
* Event RSVP template — name, email, attending, guests, dietary notes.
|
|
3747
|
-
*
|
|
3748
|
-
* For wedding-/conference-style RSVPs: required name + email + answer
|
|
3749
|
-
* to "will you attend?", optional guest count and dietary notes.
|
|
3750
|
-
*/
|
|
3751
|
-
declare function createEventRsvpTemplate(): FormConfig;
|
|
3752
|
-
|
|
3753
|
-
/**
|
|
3754
|
-
* Quote-request template — name, email, company, service, budget, details.
|
|
3755
|
-
*
|
|
3756
|
-
* Captures qualified inbound: required contact info plus a service
|
|
3757
|
-
* type and budget range so the sales team can route the lead before
|
|
3758
|
-
* replying. The free-text "details" field is required so we never get
|
|
3759
|
-
* empty leads.
|
|
3760
|
-
*/
|
|
3761
|
-
declare function createQuoteRequestTemplate(): FormConfig;
|
|
3762
|
-
|
|
3763
|
-
/**
|
|
3764
|
-
* Starter templates for common form patterns. Each factory returns a
|
|
3765
|
-
* fresh `FormConfig` so callers can safely mutate the result (e.g.
|
|
3766
|
-
* append fields) without polluting a shared instance.
|
|
3767
|
-
*
|
|
3768
|
-
* Used by:
|
|
3769
|
-
* - `saastro-hub`'s "New form → Start from" dropdown.
|
|
3770
|
-
* - The form-builder's template picker.
|
|
3771
|
-
*/
|
|
3772
|
-
declare const TEMPLATES: Record<TemplateId, () => FormConfig>;
|
|
3773
|
-
type TemplateId = 'contact' | 'newsletter' | 'lead-gen' | 'event-rsvp' | 'quote-request';
|
|
3774
|
-
/** Static metadata for surfacing templates in pickers without invoking the factory. */
|
|
3775
|
-
interface TemplateMeta {
|
|
3776
|
-
id: TemplateId;
|
|
3777
|
-
label: string;
|
|
3778
|
-
description: string;
|
|
3779
|
-
fieldCount: number;
|
|
3780
|
-
}
|
|
3781
|
-
declare const TEMPLATE_META: readonly TemplateMeta[];
|
|
3782
|
-
|
|
3783
|
-
/**
|
|
3784
|
-
* Build a `CustomSubmitConfig` that routes form submissions to a
|
|
3785
|
-
* Saastro Hub site. Used by Astro / React sites whose forms are
|
|
3786
|
-
* authored in Hub (`builder.saastro.io` embed mode) and stored there.
|
|
3720
|
+
* Build a `CustomSubmitConfig` that routes form submissions to the
|
|
3721
|
+
* Saastro ingestion endpoint (`submit.saastro.io/v1` by default).
|
|
3722
|
+
* Used by Astro / React sites whose forms are authored in Hub
|
|
3723
|
+
* (`builder.saastro.io` embed mode) and stored there.
|
|
3787
3724
|
*
|
|
3788
3725
|
* The flow is:
|
|
3789
3726
|
*
|
|
3790
3727
|
* 1. Walk the field values and split into `payload` (scalar/JSON-safe)
|
|
3791
|
-
* and `files` (instances of File).
|
|
3792
|
-
* files take a separate path.
|
|
3793
|
-
* 2. For each file, POST
|
|
3794
|
-
*
|
|
3795
|
-
*
|
|
3796
|
-
* 3. POST
|
|
3797
|
-
*
|
|
3798
|
-
*
|
|
3799
|
-
*
|
|
3800
|
-
*
|
|
3801
|
-
*
|
|
3802
|
-
* the host app must render the
|
|
3803
|
-
* via the special `
|
|
3804
|
-
* extracts it before sending.
|
|
3728
|
+
* and `files` (instances of File). The endpoint keeps text fields
|
|
3729
|
+
* together; files take a separate path.
|
|
3730
|
+
* 2. For each file, POST `/:siteId/:slug/upload-url` to get a
|
|
3731
|
+
* presigned R2 PUT URL, then PUT the binary directly to that URL.
|
|
3732
|
+
* The Worker never touches the file body — R2 receives it.
|
|
3733
|
+
* 3. POST `/:siteId/:slug/submit` with the textual payload + an
|
|
3734
|
+
* `attachments` array describing the uploaded R2 keys. The Worker
|
|
3735
|
+
* inserts the submission row and dispatches integrations (Sheets
|
|
3736
|
+
* / Resend / etc.) per the form's schema.
|
|
3737
|
+
*
|
|
3738
|
+
* Captcha: if the form schema declares `meta.captchaProvider`
|
|
3739
|
+
* ('turnstile' or 'recaptcha-v3'), the host app must render the widget
|
|
3740
|
+
* and pass the token via the special `_captchaToken` field (legacy
|
|
3741
|
+
* `_turnstile` is accepted too). The helper extracts it before sending.
|
|
3805
3742
|
*
|
|
3806
3743
|
* Honeypot: pass via `_hp` (or whatever `meta.honeypotField` says).
|
|
3807
|
-
* The
|
|
3744
|
+
* The endpoint will silently 200 the request and not store anything if
|
|
3808
3745
|
* the honeypot is non-empty.
|
|
3746
|
+
*
|
|
3747
|
+
* Endpoint history:
|
|
3748
|
+
* - v0.3.x and earlier: `https://hub.saastro.io/api/public/forms/...`
|
|
3749
|
+
* - v0.4.0+: `https://submit.saastro.io/v1/...` (dedicated worker)
|
|
3750
|
+
* See https://docs.forms.saastro.io/migration/v0.4 for details.
|
|
3809
3751
|
*/
|
|
3810
3752
|
|
|
3753
|
+
/** Default canonical ingestion endpoint. Override via `hubUrl` for self-hosting. */
|
|
3754
|
+
declare const DEFAULT_HUB_URL = "https://submit.saastro.io/v1";
|
|
3811
3755
|
interface CreateHubFormSubmitOptions {
|
|
3812
|
-
/**
|
|
3813
|
-
|
|
3756
|
+
/**
|
|
3757
|
+
* Ingestion endpoint base URL (no trailing slash). Defaults to
|
|
3758
|
+
* `https://submit.saastro.io/v1` — the canonical CF Worker.
|
|
3759
|
+
* Override for self-hosted Hub deployments or test envs.
|
|
3760
|
+
*/
|
|
3761
|
+
hubUrl?: string;
|
|
3814
3762
|
siteId: string;
|
|
3815
3763
|
formSlug: string;
|
|
3816
3764
|
}
|
|
@@ -3826,8 +3774,12 @@ interface CreateHubFormSubmitOptions {
|
|
|
3826
3774
|
declare function createHubFormSubmit(opts: CreateHubFormSubmitOptions): CustomSubmitConfig;
|
|
3827
3775
|
|
|
3828
3776
|
interface HubFormProps {
|
|
3829
|
-
/**
|
|
3830
|
-
|
|
3777
|
+
/**
|
|
3778
|
+
* Ingestion endpoint base URL (no trailing slash). Defaults to
|
|
3779
|
+
* `https://submit.saastro.io/v1` — the canonical hosted endpoint.
|
|
3780
|
+
* Override for self-hosted Hub or test envs.
|
|
3781
|
+
*/
|
|
3782
|
+
hubUrl?: string;
|
|
3831
3783
|
siteId: string;
|
|
3832
3784
|
formSlug: string;
|
|
3833
3785
|
/** Custom UI while the schema is being fetched. Defaults to a skeleton. */
|
|
@@ -3918,4 +3870,4 @@ declare function getFieldClass(formLayout?: {
|
|
|
3918
3870
|
*/
|
|
3919
3871
|
declare function getHiddenClasses(hidden?: Partial<Record<Breakpoint, 'visible' | 'hidden'>>): string;
|
|
3920
3872
|
|
|
3921
|
-
export { type AccordionContentProps, type AccordionItemProps, type AccordionProps, type AccordionTriggerProps, BUILD_METHODS, BUILTIN_RESOLVERS, type BaseFieldProps, type Breakpoint$1 as Breakpoint, type BuiltinTransform, type ButtonCardFieldProps, type ButtonCardOption, type ButtonCheckboxFieldProps, type ButtonConfig, type ButtonProps, type ButtonRadioFieldProps, COMMON_CLASSES, COMMON_METHODS, COMMON_STRINGS, type CalendarProps, type CheckboxFieldProps, type CheckboxGroupFieldProps, type CheckboxProps, type ColumnsValue, type ComboboxFieldProps, type CommandEmptyProps, type CommandFieldProps, type CommandGroupProps, type CommandInputProps, type CommandItemProps, type CommandListProps, type CommandProps, type ComponentName, type ComponentOverrides, ComponentProvider, type ComponentProviderProps, type ComponentRegistry, type ComponentRegistryInput, ComponentResolver, type ComponentResolverConfig, type Condition, type ConditionGroup, type ConditionOperator, type CreateHubFormSubmitOptions, type CurrencyFieldProps, type CustomSubmitAction, type CustomSubmitConfig, type DatabowlConfig, type DateFieldProps, type DateRangeFieldProps, type DefaultSubmitConfig, type DefinePlugin, type DialogContentProps, type DialogDescriptionProps, type DialogHeaderProps, type DialogProps, type DialogTitleProps, type DialogTriggerProps, type EmailProvider, type EmailSubmitAction, type EndpointConfig, FIELD_DEFAULTS, FieldBuilder, type FieldConfig, type FieldDescriptionProps, type FieldErrorProps, type FieldLabelProps, type FieldLayoutConfig, type FieldMapEntry, type FieldMapping, type FieldMappingConfig, type FieldProps, FieldRenderer, type FieldResolver, type FieldTransformFn, type Fields, type FileFieldProps, Form, FormBuilder, type FormButtonProps, type FormButtons, FormComponentsProvider, type FormComponentsProviderProps, type FormConfig, type FormControlProps, type FormFieldProps, type FormLayout, type FormPlugin, type FormProps, type FormRef, type FormStepsInfo, type GapValue, type GlobModules, type HiddenFieldProps, type HtmlFieldProps, type HttpAuthConfig, type HttpBodyConfig, type HttpEndpointConfig, type HttpRetryConfig, type HttpSubmitAction, HubForm, type HubFormProps, type InputGroupFieldProps, type InputOTPGroupProps, type InputOTPProps, type InputOTPSlotProps, type InputProps, type InputSize, type IntegrationSubmitAction, InternalComponentProvider, type InternalComponentProviderProps, type LabelProps, MissingComponentFallback, type MissingComponentFallbackProps, type NativeSelectFieldProps, type NativeSelectProps, OPTION_BASED_TYPES, type Option, type OtpFieldProps, type PartialComponentRegistry, PluginManager, type PopoverContentProps, type PopoverProps, type PopoverTriggerProps, type PropertyMapping, type RadioFieldProps, type RadioGroupItemProps, type RadioGroupProps, type RangeFieldProps, type RecaptchaConfig, type RecaptchaPluginConfig, type RepeaterFieldProps, type ResolvedComponents, SUSPENSE_CONFIG, type SchemaType, type SelectContentProps, type SelectFieldProps, type SelectItemProps, type SelectProps, type SelectTriggerProps, type SelectValueProps, type SeparatorProps, type SerializableFieldResolver, type SerializationHint, type SliderFieldProps, type SliderProps, type Step, type StepCondition, type StepInfo, type StepStatus, type Steps, StepsAccordion, StepsNavigation, StepsProgress, type SubmitAction, type SubmitActionCondition, type SubmitActionNode, type SubmitActionResult, type SubmitActionType, type SubmitActionsResult, type SubmitConfig, type SubmitConfirmationConfig, type SubmitExecutionConfig, type SubmitTrigger, type SubmitTriggerType, type SubmitType, type SwitchFieldProps, type SwitchGroupFieldProps, type SwitchProps,
|
|
3873
|
+
export { type AccordionContentProps, type AccordionItemProps, type AccordionProps, type AccordionTriggerProps, BUILD_METHODS, BUILTIN_RESOLVERS, type BaseFieldProps, type Breakpoint$1 as Breakpoint, type BuiltinTransform, type ButtonCardFieldProps, type ButtonCardOption, type ButtonCheckboxFieldProps, type ButtonConfig, type ButtonProps, type ButtonRadioFieldProps, COMMON_CLASSES, COMMON_METHODS, COMMON_STRINGS, type CalendarProps, type CheckboxFieldProps, type CheckboxGroupFieldProps, type CheckboxProps, type ColumnsValue, type ComboboxFieldProps, type CommandEmptyProps, type CommandFieldProps, type CommandGroupProps, type CommandInputProps, type CommandItemProps, type CommandListProps, type CommandProps, type ComponentName, type ComponentOverrides, ComponentProvider, type ComponentProviderProps, type ComponentRegistry, type ComponentRegistryInput, ComponentResolver, type ComponentResolverConfig, type Condition, type ConditionGroup, type ConditionOperator, type CreateHubFormSubmitOptions, type CurrencyFieldProps, type CustomSubmitAction, type CustomSubmitConfig, DEFAULT_HUB_URL, type DatabowlConfig, type DateFieldProps, type DateRangeFieldProps, type DefaultSubmitConfig, type DefinePlugin, type DialogContentProps, type DialogDescriptionProps, type DialogHeaderProps, type DialogProps, type DialogTitleProps, type DialogTriggerProps, type EmailProvider, type EmailSubmitAction, type EndpointConfig, FIELD_DEFAULTS, FieldBuilder, type FieldConfig, type FieldDescriptionProps, type FieldErrorProps, type FieldLabelProps, type FieldLayoutConfig, type FieldMapEntry, type FieldMapping, type FieldMappingConfig, type FieldProps, FieldRenderer, type FieldResolver, type FieldTransformFn, type Fields, type FileFieldProps, Form, FormBuilder, type FormButtonProps, type FormButtons, FormComponentsProvider, type FormComponentsProviderProps, type FormConfig, type FormControlProps, type FormFieldProps, type FormLayout, type FormPlugin, type FormProps, type FormRef, type FormStepsInfo, type GapValue, type GlobModules, type HiddenFieldProps, type HtmlFieldProps, type HttpAuthConfig, type HttpBodyConfig, type HttpEndpointConfig, type HttpRetryConfig, type HttpSubmitAction, HubForm, type HubFormProps, type InputGroupFieldProps, type InputOTPGroupProps, type InputOTPProps, type InputOTPSlotProps, type InputProps, type InputSize, type IntegrationSubmitAction, InternalComponentProvider, type InternalComponentProviderProps, type LabelProps, MissingComponentFallback, type MissingComponentFallbackProps, type NativeSelectFieldProps, type NativeSelectProps, OPTION_BASED_TYPES, type Option, type OtpFieldProps, type PartialComponentRegistry, PluginManager, type PopoverContentProps, type PopoverProps, type PopoverTriggerProps, type PropertyMapping, type RadioFieldProps, type RadioGroupItemProps, type RadioGroupProps, type RangeFieldProps, type RecaptchaConfig, type RecaptchaPluginConfig, type RepeaterFieldProps, type ResolvedComponents, SUSPENSE_CONFIG, type SchemaType, type SelectContentProps, type SelectFieldProps, type SelectItemProps, type SelectProps, type SelectTriggerProps, type SelectValueProps, type SeparatorProps, type SerializableFieldResolver, type SerializationHint, type SliderFieldProps, type SliderProps, type Step, type StepCondition, type StepInfo, type StepStatus, type Steps, StepsAccordion, StepsNavigation, StepsProgress, type SubmitAction, type SubmitActionCondition, type SubmitActionNode, type SubmitActionResult, type SubmitActionType, type SubmitActionsResult, type SubmitConfig, type SubmitConfirmationConfig, type SubmitExecutionConfig, type SubmitTrigger, type SubmitTriggerType, type SubmitType, type SwitchFieldProps, type SwitchGroupFieldProps, type SwitchProps, TYPE_SPECIFIC_PROPERTIES, type TestDataLocale, type TestDataOptions, type TextFieldProps, type TextareaFieldProps, type TextareaProps, type TooltipContentProps, type TooltipProps, type TooltipProviderProps, type TooltipTriggerProps, type UseSubmitConfirmationReturn, VALIDATION_METHODS, type ValidateComponentRegistry, type ValidationContext, type ValidationPresetMeta, type ValidationRules, type WebhookSubmitAction, analyticsPlugin, applyBuiltinTransform, applyFieldMapping, applyFieldMappingSync, applyFieldTransforms, applyTransform, autosavePlugin, compileValidationRules, configureComponents, coreComponents, createComponentRegistry, createHubFormSubmit, createMissingComponentPlaceholder, createShadcnRegistry, databowlAction, databowlPlugin, defaultSubmit, definePlugin, detectLocale, executeCustomAction, executeEmailAction, executeHttpAction, executeSubmitAction, executeSubmitActions, executeSubmitActionsByTrigger, executeWebhookAction, fieldTypeComponents, generateFieldValue, generateTestData, getActionsByTrigger, getAllKnownMethods, getAvailablePresets, getComponentResolver, getFieldClass, getFormGridClass, getHiddenClasses, getInstallCommand, getMinDelayMs, getMissingComponents, getRequiredComponents, globalPluginManager, groupMissingByPackage, iconVariants, iconVariantsConfig, inputVariants, inputVariantsConfig, isAdvancedMapping, isValidationRules, isZodSchema, localStoragePlugin, mergeComponentRegistries, parseGlobModules, pxToRem, recaptchaPlugin, registerPreset, resolvePreset, resolveValue, resolveValueSync, textareaVariants, textareaVariantsConfig, useComponentMode, useComponents, useComputedFields, useFormLayout, useFormState, useFormStepsInfo, useHasComponentProvider, useHiddenFieldResolvers, usePartialComponents, useRecaptcha, useSubmitActionTriggers, useSubmitConfirmation, withComponents };
|
package/dist/index.js
CHANGED
|
@@ -4422,6 +4422,7 @@ var FieldBuilder = class {
|
|
|
4422
4422
|
constructor(name) {
|
|
4423
4423
|
this.name = name;
|
|
4424
4424
|
}
|
|
4425
|
+
name;
|
|
4425
4426
|
config = {};
|
|
4426
4427
|
/**
|
|
4427
4428
|
* Configura el tipo de campo.
|
|
@@ -6799,169 +6800,11 @@ var BUILTIN_RESOLVERS = [
|
|
|
6799
6800
|
{ id: "urlParam", label: "URL Parameter", description: "Value from a URL query parameter" }
|
|
6800
6801
|
];
|
|
6801
6802
|
|
|
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
|
-
|
|
6961
6803
|
// src/lib/createHubFormSubmit.ts
|
|
6804
|
+
var DEFAULT_HUB_URL = "https://submit.saastro.io/v1";
|
|
6962
6805
|
function publicBase({ hubUrl, siteId, formSlug }) {
|
|
6963
|
-
const
|
|
6964
|
-
return `${
|
|
6806
|
+
const base = (hubUrl ?? DEFAULT_HUB_URL).replace(/\/+$/, "");
|
|
6807
|
+
return `${base}/${encodeURIComponent(siteId)}/${encodeURIComponent(formSlug)}`;
|
|
6965
6808
|
}
|
|
6966
6809
|
async function presignAndUpload(base, file) {
|
|
6967
6810
|
const presignRes = await fetch(`${base}/upload-url`, {
|
|
@@ -6999,7 +6842,7 @@ function partitionValues(values) {
|
|
|
6999
6842
|
let turnstileToken = null;
|
|
7000
6843
|
const honeypotEntries = [];
|
|
7001
6844
|
for (const [key, value] of Object.entries(values)) {
|
|
7002
|
-
if (key === "_turnstile") {
|
|
6845
|
+
if (key === "_captchaToken" || key === "_turnstile") {
|
|
7003
6846
|
if (typeof value === "string") turnstileToken = value;
|
|
7004
6847
|
continue;
|
|
7005
6848
|
}
|
|
@@ -7039,7 +6882,10 @@ function createHubFormSubmit(opts) {
|
|
|
7039
6882
|
body: JSON.stringify({
|
|
7040
6883
|
payload,
|
|
7041
6884
|
attachments,
|
|
7042
|
-
|
|
6885
|
+
// Send under the canonical name. The worker also accepts the
|
|
6886
|
+
// legacy `turnstile` field for old SDK callers, but new sends
|
|
6887
|
+
// should use `captchaToken`.
|
|
6888
|
+
captchaToken: turnstileToken ?? void 0,
|
|
7043
6889
|
...honeypotEntry
|
|
7044
6890
|
})
|
|
7045
6891
|
});
|
|
@@ -7083,8 +6929,8 @@ function HubForm({
|
|
|
7083
6929
|
const [state, setState] = useState5({ status: "loading" });
|
|
7084
6930
|
useEffect8(() => {
|
|
7085
6931
|
let cancelled = false;
|
|
7086
|
-
const cleanHub = hubUrl.replace(/\/+$/, "");
|
|
7087
|
-
const url = `${cleanHub}
|
|
6932
|
+
const cleanHub = (hubUrl ?? DEFAULT_HUB_URL).replace(/\/+$/, "");
|
|
6933
|
+
const url = `${cleanHub}/${encodeURIComponent(siteId)}/${encodeURIComponent(formSlug)}.json`;
|
|
7088
6934
|
fetch(url, { headers: { accept: "application/json" } }).then(async (res) => {
|
|
7089
6935
|
if (!res.ok) throw new Error(`schema fetch failed: ${res.status} ${res.statusText}`);
|
|
7090
6936
|
return res.json();
|
|
@@ -7408,6 +7254,7 @@ export {
|
|
|
7408
7254
|
COMMON_STRINGS,
|
|
7409
7255
|
ComponentProvider,
|
|
7410
7256
|
ComponentResolver,
|
|
7257
|
+
DEFAULT_HUB_URL,
|
|
7411
7258
|
FIELD_DEFAULTS,
|
|
7412
7259
|
FieldBuilder,
|
|
7413
7260
|
FieldRenderer,
|
|
@@ -7423,8 +7270,6 @@ export {
|
|
|
7423
7270
|
StepsAccordion,
|
|
7424
7271
|
StepsNavigation,
|
|
7425
7272
|
StepsProgress,
|
|
7426
|
-
TEMPLATES,
|
|
7427
|
-
TEMPLATE_META,
|
|
7428
7273
|
TYPE_SPECIFIC_PROPERTIES,
|
|
7429
7274
|
VALIDATION_METHODS,
|
|
7430
7275
|
analyticsPlugin,
|
|
@@ -7438,13 +7283,8 @@ export {
|
|
|
7438
7283
|
configureComponents,
|
|
7439
7284
|
coreComponents,
|
|
7440
7285
|
createComponentRegistry,
|
|
7441
|
-
createContactTemplate,
|
|
7442
|
-
createEventRsvpTemplate,
|
|
7443
7286
|
createHubFormSubmit,
|
|
7444
|
-
createLeadGenTemplate,
|
|
7445
7287
|
createMissingComponentPlaceholder,
|
|
7446
|
-
createNewsletterTemplate,
|
|
7447
|
-
createQuoteRequestTemplate,
|
|
7448
7288
|
createShadcnRegistry,
|
|
7449
7289
|
databowlAction,
|
|
7450
7290
|
databowlPlugin,
|