@page-speed/forms 0.6.3 → 0.6.4
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/{FormContext-Db0L3Kwv.d.ts → FormContext-C6kWSQuv.d.ts} +1 -1
- package/dist/{FormContext-kKZxeb7G.d.cts → FormContext-DLG3GzgL.d.cts} +1 -1
- package/dist/chunk-A7MVZ757.js +701 -0
- package/dist/chunk-A7MVZ757.js.map +1 -0
- package/dist/chunk-DCGSRMZT.cjs +728 -0
- package/dist/chunk-DCGSRMZT.cjs.map +1 -0
- package/dist/chunk-UBDA7CS5.js +3 -0
- package/dist/chunk-UBDA7CS5.js.map +1 -0
- package/dist/chunk-V7JSGFCI.cjs +4 -0
- package/dist/chunk-V7JSGFCI.cjs.map +1 -0
- package/dist/core.cjs +13 -13
- package/dist/core.d.cts +10 -8
- package/dist/core.d.ts +10 -8
- package/dist/core.js +2 -2
- package/dist/index.cjs +12 -12
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/inputs.d.cts +1 -1
- package/dist/inputs.d.ts +1 -1
- package/dist/integration.cjs +101 -3
- package/dist/integration.cjs.map +1 -1
- package/dist/integration.d.cts +103 -18
- package/dist/integration.d.ts +103 -18
- package/dist/integration.js +100 -3
- package/dist/integration.js.map +1 -1
- package/dist/{types-BPxsUGm_.d.ts → types-BhcLAcZe.d.cts} +31 -22
- package/dist/{types-BPxsUGm_.d.cts → types-BhcLAcZe.d.ts} +31 -22
- package/dist/validation-rules.d.cts +1 -1
- package/dist/validation-rules.d.ts +1 -1
- package/dist/validation-utils.d.cts +1 -1
- package/dist/validation-utils.d.ts +1 -1
- package/dist/validation-valibot.d.cts +1 -1
- package/dist/validation-valibot.d.ts +1 -1
- package/dist/validation.d.cts +1 -1
- package/dist/validation.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-3ED2FKXF.cjs +0 -350
- package/dist/chunk-3ED2FKXF.cjs.map +0 -1
- package/dist/chunk-H3YJRLVO.js +0 -326
- package/dist/chunk-H3YJRLVO.js.map +0 -1
- package/dist/chunk-SNSK3TMG.js +0 -373
- package/dist/chunk-SNSK3TMG.js.map +0 -1
- package/dist/chunk-V545YJFP.cjs +0 -397
- package/dist/chunk-V545YJFP.cjs.map +0 -1
package/dist/integration.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export { x as FormFieldType, y as SelectOption, u as generateInitialValues, v as generateValidationSchema, w as getColumnSpanClass } from './types-BPxsUGm_.js';
|
|
2
|
+
import { e as FormSubmissionConfig, t as FormLayoutSettings, u as FormFieldConfig, m as UseFormReturn, B as ButtonGroupFormFieldConfig } from './types-BhcLAcZe.js';
|
|
3
|
+
export { y as FormFieldType, z as SelectOption, v as generateInitialValues, w as generateValidationSchema, x as getColumnSpanClass } from './types-BhcLAcZe.js';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* @page-speed/forms - Rails API Serializer
|
|
@@ -387,12 +386,12 @@ interface PageSpeedFormSubmissionResult {
|
|
|
387
386
|
formData: Record<string, any>;
|
|
388
387
|
responseData: unknown;
|
|
389
388
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
389
|
+
/**
|
|
390
|
+
* PageSpeed-specific extension of the core FormSubmissionConfig.
|
|
391
|
+
* Inherits behavior, customComponent, and newFormSubmissionAction from the
|
|
392
|
+
* base type and adds integration-layer callbacks and redirect support.
|
|
393
|
+
*/
|
|
394
|
+
interface PageSpeedFormSubmissionConfig extends FormSubmissionConfig {
|
|
396
395
|
/**
|
|
397
396
|
* Optional callback triggered on successful submission.
|
|
398
397
|
*/
|
|
@@ -401,14 +400,6 @@ interface PageSpeedFormSubmissionConfig {
|
|
|
401
400
|
* Redirect destination used when behavior is "redirect".
|
|
402
401
|
*/
|
|
403
402
|
redirectUrl?: string;
|
|
404
|
-
/**
|
|
405
|
-
* Custom component rendered when behavior is "renderCustomComponent".
|
|
406
|
-
*/
|
|
407
|
-
customComponent?: ReactNode;
|
|
408
|
-
/**
|
|
409
|
-
* Optional action to allow a fresh submission after success.
|
|
410
|
-
*/
|
|
411
|
-
newFormSubmissionAction?: NewFormSubmissionActionConfig;
|
|
412
403
|
}
|
|
413
404
|
interface PageSpeedFormConfig {
|
|
414
405
|
/**
|
|
@@ -466,6 +457,12 @@ interface PageSpeedFormConfig {
|
|
|
466
457
|
* Optional post-submission behavior configuration.
|
|
467
458
|
*/
|
|
468
459
|
submissionConfig?: PageSpeedFormSubmissionConfig;
|
|
460
|
+
/**
|
|
461
|
+
* Optional layout and presentation settings.
|
|
462
|
+
* Provides a typed home for layout props (formLayout, buttonGroupSize, etc.)
|
|
463
|
+
* so consumers don't need an `as any` cast when passing them alongside API config.
|
|
464
|
+
*/
|
|
465
|
+
formLayoutSettings?: FormLayoutSettings;
|
|
469
466
|
}
|
|
470
467
|
declare class PageSpeedFormSubmissionError extends Error {
|
|
471
468
|
formErrors?: FormErrors;
|
|
@@ -572,4 +569,92 @@ interface DynamicFormFieldProps {
|
|
|
572
569
|
*/
|
|
573
570
|
declare function DynamicFormField({ field, className, uploadProgress, onFileUpload, onFileRemove, isUploading, renderLabel, }: DynamicFormFieldProps): React.JSX.Element;
|
|
574
571
|
|
|
575
|
-
|
|
572
|
+
interface ButtonGroupFormSetup {
|
|
573
|
+
size?: "xs" | "sm" | "default" | "lg";
|
|
574
|
+
submitLabel?: React.ReactNode;
|
|
575
|
+
submitVariant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost";
|
|
576
|
+
submitIconName?: string;
|
|
577
|
+
submitIconComponent?: React.ReactNode;
|
|
578
|
+
}
|
|
579
|
+
interface FormEngineSubmitButtonSetup {
|
|
580
|
+
submitLabel?: React.ReactNode;
|
|
581
|
+
submitVariant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost";
|
|
582
|
+
submitIconName?: string;
|
|
583
|
+
submitIconComponent?: React.ReactNode;
|
|
584
|
+
}
|
|
585
|
+
interface FormEngineStyleRules {
|
|
586
|
+
/** ClassName applied to the div wrapping the `<form>` element */
|
|
587
|
+
formContainer?: string;
|
|
588
|
+
/** ClassName applied to the grid div wrapping all field columns (standard layout) */
|
|
589
|
+
fieldsContainer?: string;
|
|
590
|
+
/** Fallback className applied to each field wrapper when the field has no own className */
|
|
591
|
+
fieldClassName?: string;
|
|
592
|
+
/** className forwarded to the `<form>` element itself via FormStyleConfig */
|
|
593
|
+
formClassName?: string;
|
|
594
|
+
/** className forwarded to the success message container via FormStyleConfig */
|
|
595
|
+
successMessageClassName?: string;
|
|
596
|
+
/** className forwarded to the error message container via FormStyleConfig */
|
|
597
|
+
errorMessageClassName?: string;
|
|
598
|
+
}
|
|
599
|
+
interface FormEngineLayoutSettings {
|
|
600
|
+
styleRules?: FormEngineStyleRules;
|
|
601
|
+
formLayout?: "standard" | "button-group";
|
|
602
|
+
/** Settings for button-group layout (only used when formLayout is "button-group") */
|
|
603
|
+
buttonGroupSetup?: ButtonGroupFormSetup;
|
|
604
|
+
/** Settings for the submit button in standard layout */
|
|
605
|
+
submitButtonSetup?: FormEngineSubmitButtonSetup;
|
|
606
|
+
}
|
|
607
|
+
interface FormEngineProps {
|
|
608
|
+
/** API / submission configuration */
|
|
609
|
+
api?: PageSpeedFormConfig;
|
|
610
|
+
/** Form field definitions */
|
|
611
|
+
fields: (FormFieldConfig | ButtonGroupFormFieldConfig)[];
|
|
612
|
+
/** Layout, style, and submit-button settings */
|
|
613
|
+
formLayoutSettings?: FormEngineLayoutSettings;
|
|
614
|
+
/** Success message shown after a successful submission */
|
|
615
|
+
successMessage?: React.ReactNode;
|
|
616
|
+
/** Custom submit handler (called in addition to any api endpoint) */
|
|
617
|
+
onSubmit?: (values: Record<string, any>) => void | Promise<void>;
|
|
618
|
+
/** Called after a successful submission with the server response */
|
|
619
|
+
onSuccess?: (data: unknown) => void;
|
|
620
|
+
/** Called when submission fails */
|
|
621
|
+
onError?: (error: Error) => void;
|
|
622
|
+
/** Navigation handler for internal redirects (return false to fall back to browser navigation) */
|
|
623
|
+
navigate?: (href: string) => boolean | void;
|
|
624
|
+
/** Reset form values after success @default true */
|
|
625
|
+
resetOnSuccess?: boolean;
|
|
626
|
+
/** File upload tokens to merge into the payload */
|
|
627
|
+
uploadTokens?: string[];
|
|
628
|
+
/** Called when files are selected for upload */
|
|
629
|
+
onFileUpload?: (files: File[]) => Promise<void>;
|
|
630
|
+
/** Called when a file is removed */
|
|
631
|
+
onFileRemove?: (file: File, index: number) => void;
|
|
632
|
+
/** Whether a file upload is in progress */
|
|
633
|
+
isUploading?: boolean;
|
|
634
|
+
/** Per-file upload progress map (fileName → 0-100) */
|
|
635
|
+
uploadProgress?: {
|
|
636
|
+
[fileName: string]: number;
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* FormEngine — declarative form component with built-in API integration.
|
|
641
|
+
*
|
|
642
|
+
* Handles `useContactForm` orchestration internally so callers only need to
|
|
643
|
+
* supply `api`, `fields`, and optional layout/style settings.
|
|
644
|
+
*
|
|
645
|
+
* @example Standard layout
|
|
646
|
+
* ```tsx
|
|
647
|
+
* <FormEngine api={api} fields={fields} formLayoutSettings={{ submitButtonSetup: { submitLabel: "Send" } }} />
|
|
648
|
+
* ```
|
|
649
|
+
*
|
|
650
|
+
* @example Button-group layout
|
|
651
|
+
* ```tsx
|
|
652
|
+
* <FormEngine api={api} fields={[emailField]} formLayoutSettings={{ formLayout: "button-group", buttonGroupSetup: { size: "lg", submitLabel: "Subscribe" } }} />
|
|
653
|
+
* ```
|
|
654
|
+
*/
|
|
655
|
+
declare function FormEngine({ api, fields, formLayoutSettings, successMessage, onSubmit, onSuccess, onError, navigate, resetOnSuccess, uploadTokens, onFileUpload, onFileRemove, isUploading, uploadProgress, }: FormEngineProps): React.JSX.Element;
|
|
656
|
+
declare namespace FormEngine {
|
|
657
|
+
var displayName: string;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
export { type AdaptedComponentProps, type Block, type BlockAdapterOptions, ButtonGroupFormFieldConfig, type ButtonGroupFormSetup, DynamicFormField, type DynamicFormFieldProps, type FileUploadProgress, FormEngine, type FormEngineLayoutSettings, type FormEngineProps, type FormEngineStyleRules, type FormEngineSubmitButtonSetup, type FormErrors, FormFieldConfig, FormLayoutSettings, type PageSpeedFormConfig, type PageSpeedFormMethod, type PageSpeedFormSubmissionConfig, PageSpeedFormSubmissionError, type PageSpeedFormSubmissionFormat, type PageSpeedFormSubmissionResult, type RailsApiConfig, type RailsErrorResponse, type SerializedFormData, type UseContactFormOptions, type UseContactFormReturn, type UseFileUploadOptions, type UseFileUploadReturn, createBlockAdapter, createBlockAdapters, deserializeErrors, isValidEmail, serializeForRails, standardInputTransformer, submitPageSpeedForm, useContactForm, useFileUpload };
|
package/dist/integration.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { useForm, Field } from './chunk-
|
|
1
|
+
import { useForm, Field, Form } from './chunk-A7MVZ757.js';
|
|
2
2
|
import { TextArea, Select, MultiSelect, Radio, Checkbox, CheckboxGroup, DatePicker, DateRangePicker, TimePicker, FileInput } from './chunk-ML6FGUYS.js';
|
|
3
|
-
import { TextInput } from './chunk-J37BGNM6.js';
|
|
3
|
+
import { TextInput, cn, Button } from './chunk-J37BGNM6.js';
|
|
4
4
|
import * as React2 from 'react';
|
|
5
5
|
import { useState, useCallback, useMemo } from 'react';
|
|
6
6
|
|
|
@@ -783,7 +783,104 @@ function DynamicFormField({
|
|
|
783
783
|
))
|
|
784
784
|
);
|
|
785
785
|
}
|
|
786
|
+
function FormEngine({
|
|
787
|
+
api,
|
|
788
|
+
fields,
|
|
789
|
+
formLayoutSettings,
|
|
790
|
+
successMessage,
|
|
791
|
+
onSubmit,
|
|
792
|
+
onSuccess,
|
|
793
|
+
onError,
|
|
794
|
+
navigate,
|
|
795
|
+
resetOnSuccess,
|
|
796
|
+
uploadTokens,
|
|
797
|
+
onFileUpload,
|
|
798
|
+
onFileRemove,
|
|
799
|
+
isUploading,
|
|
800
|
+
uploadProgress
|
|
801
|
+
}) {
|
|
802
|
+
const {
|
|
803
|
+
styleRules,
|
|
804
|
+
formLayout = "standard",
|
|
805
|
+
buttonGroupSetup,
|
|
806
|
+
submitButtonSetup
|
|
807
|
+
} = formLayoutSettings ?? {};
|
|
808
|
+
const isButtonGroup = formLayout === "button-group";
|
|
809
|
+
const normalizedFields = React2.useMemo(
|
|
810
|
+
() => fields.map((f) => ({ ...f, label: f.label ?? f.name })),
|
|
811
|
+
[fields]
|
|
812
|
+
);
|
|
813
|
+
const { form, submissionError, formMethod, resetSubmissionState } = useContactForm({
|
|
814
|
+
formFields: normalizedFields,
|
|
815
|
+
formConfig: api,
|
|
816
|
+
onSubmit,
|
|
817
|
+
onSuccess,
|
|
818
|
+
onError,
|
|
819
|
+
navigate,
|
|
820
|
+
resetOnSuccess,
|
|
821
|
+
uploadTokens
|
|
822
|
+
});
|
|
823
|
+
const legacyFormConfig = React2.useMemo(() => {
|
|
824
|
+
if (isButtonGroup) {
|
|
825
|
+
return {
|
|
826
|
+
formLayout: "button-group",
|
|
827
|
+
buttonGroupSize: buttonGroupSetup?.size,
|
|
828
|
+
submitLabel: buttonGroupSetup?.submitLabel,
|
|
829
|
+
submitVariant: buttonGroupSetup?.submitVariant,
|
|
830
|
+
submitIconName: buttonGroupSetup?.submitIconName,
|
|
831
|
+
submitIconComponent: buttonGroupSetup?.submitIconComponent,
|
|
832
|
+
endpoint: api?.endpoint,
|
|
833
|
+
submissionConfig: api?.submissionConfig
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
return {
|
|
837
|
+
formLayout: "standard",
|
|
838
|
+
endpoint: api?.endpoint,
|
|
839
|
+
submissionConfig: api?.submissionConfig
|
|
840
|
+
};
|
|
841
|
+
}, [isButtonGroup, buttonGroupSetup, api]);
|
|
842
|
+
return /* @__PURE__ */ React2.createElement("div", { className: styleRules?.formContainer }, /* @__PURE__ */ React2.createElement(
|
|
843
|
+
Form,
|
|
844
|
+
{
|
|
845
|
+
form,
|
|
846
|
+
fields: isButtonGroup ? fields : void 0,
|
|
847
|
+
formConfig: legacyFormConfig,
|
|
848
|
+
method: formMethod,
|
|
849
|
+
notificationConfig: {
|
|
850
|
+
submissionError: submissionError ?? void 0,
|
|
851
|
+
successMessage
|
|
852
|
+
},
|
|
853
|
+
styleConfig: {
|
|
854
|
+
formClassName: styleRules?.formClassName,
|
|
855
|
+
successMessageClassName: styleRules?.successMessageClassName,
|
|
856
|
+
errorMessageClassName: styleRules?.errorMessageClassName
|
|
857
|
+
},
|
|
858
|
+
onNewSubmission: resetSubmissionState
|
|
859
|
+
},
|
|
860
|
+
!isButtonGroup && /* @__PURE__ */ React2.createElement(React2.Fragment, null, /* @__PURE__ */ React2.createElement("div", { className: cn("grid grid-cols-12 gap-6", styleRules?.fieldsContainer) }, normalizedFields.map((field) => /* @__PURE__ */ React2.createElement("div", { key: field.name, className: cn(getColumnSpanClass(field.columnSpan ?? 12), "min-w-0") }, /* @__PURE__ */ React2.createElement(
|
|
861
|
+
DynamicFormField,
|
|
862
|
+
{
|
|
863
|
+
field,
|
|
864
|
+
className: field.className ?? styleRules?.fieldClassName,
|
|
865
|
+
uploadProgress,
|
|
866
|
+
onFileUpload,
|
|
867
|
+
onFileRemove,
|
|
868
|
+
isUploading
|
|
869
|
+
}
|
|
870
|
+
)))), /* @__PURE__ */ React2.createElement(
|
|
871
|
+
Button,
|
|
872
|
+
{
|
|
873
|
+
type: "submit",
|
|
874
|
+
variant: submitButtonSetup?.submitVariant ?? "default",
|
|
875
|
+
disabled: form.isSubmitting,
|
|
876
|
+
className: "mt-6 w-full"
|
|
877
|
+
},
|
|
878
|
+
submitButtonSetup?.submitLabel ?? "Submit"
|
|
879
|
+
))
|
|
880
|
+
));
|
|
881
|
+
}
|
|
882
|
+
FormEngine.displayName = "FormEngine";
|
|
786
883
|
|
|
787
|
-
export { DynamicFormField, PageSpeedFormSubmissionError, createBlockAdapter, createBlockAdapters, deserializeErrors, generateInitialValues, generateValidationSchema, getColumnSpanClass, isValidEmail, serializeForRails, standardInputTransformer, submitPageSpeedForm, useContactForm, useFileUpload };
|
|
884
|
+
export { DynamicFormField, FormEngine, PageSpeedFormSubmissionError, createBlockAdapter, createBlockAdapters, deserializeErrors, generateInitialValues, generateValidationSchema, getColumnSpanClass, isValidEmail, serializeForRails, standardInputTransformer, submitPageSpeedForm, useContactForm, useFileUpload };
|
|
788
885
|
//# sourceMappingURL=integration.js.map
|
|
789
886
|
//# sourceMappingURL=integration.js.map
|