@page-speed/forms 0.6.2 → 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-D_K7lO2V.d.ts → FormContext-C6kWSQuv.d.ts} +1 -1
- package/dist/{FormContext-BHKCZ_du.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-455PI4LV.js → chunk-J37BGNM6.js} +5 -4
- package/dist/chunk-J37BGNM6.js.map +1 -0
- package/dist/{chunk-4ROWNTY6.js → chunk-ML6FGUYS.js} +3 -3
- package/dist/{chunk-4ROWNTY6.js.map → chunk-ML6FGUYS.js.map} +1 -1
- package/dist/{chunk-QRI5TMES.cjs → chunk-QMWZLGON.cjs} +5 -4
- package/dist/chunk-QMWZLGON.cjs.map +1 -0
- package/dist/chunk-UBDA7CS5.js +3 -0
- package/dist/chunk-UBDA7CS5.js.map +1 -0
- package/dist/{chunk-ED4UK63G.cjs → chunk-UQ6JPOBF.cjs} +114 -114
- package/dist/{chunk-ED4UK63G.cjs.map → chunk-UQ6JPOBF.cjs.map} +1 -1
- package/dist/chunk-V7JSGFCI.cjs +4 -0
- package/dist/chunk-V7JSGFCI.cjs.map +1 -0
- package/dist/core.cjs +14 -14
- package/dist/core.d.cts +17 -11
- package/dist/core.d.ts +17 -11
- package/dist/core.js +3 -3
- package/dist/index.cjs +18 -18
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/inputs.cjs +14 -14
- package/dist/inputs.d.cts +8 -2
- package/dist/inputs.d.ts +8 -2
- package/dist/inputs.js +2 -2
- package/dist/integration.cjs +115 -17
- package/dist/integration.cjs.map +1 -1
- package/dist/integration.d.cts +103 -127
- package/dist/integration.d.ts +103 -127
- package/dist/integration.js +101 -4
- package/dist/integration.js.map +1 -1
- package/dist/{types-Fbt73kW_.d.ts → types-BhcLAcZe.d.cts} +149 -22
- package/dist/{types-Fbt73kW_.d.cts → types-BhcLAcZe.d.ts} +149 -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-455PI4LV.js.map +0 -1
- package/dist/chunk-MJYEXJ3U.js +0 -373
- package/dist/chunk-MJYEXJ3U.js.map +0 -1
- package/dist/chunk-MUBEMXI7.cjs +0 -397
- package/dist/chunk-MUBEMXI7.cjs.map +0 -1
- package/dist/chunk-QRI5TMES.cjs.map +0 -1
- package/dist/chunk-RS6AXV5S.cjs +0 -309
- package/dist/chunk-RS6AXV5S.cjs.map +0 -1
- package/dist/chunk-ZEAH6AKP.js +0 -285
- package/dist/chunk-ZEAH6AKP.js.map +0 -1
package/dist/integration.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { e as FormSubmissionConfig, t as FormLayoutSettings, u as FormFieldConfig, m as UseFormReturn, B as ButtonGroupFormFieldConfig } from './types-BhcLAcZe.cjs';
|
|
3
|
+
export { y as FormFieldType, z as SelectOption, v as generateInitialValues, w as generateValidationSchema, x as getColumnSpanClass } from './types-BhcLAcZe.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @page-speed/forms - Rails API Serializer
|
|
@@ -386,12 +386,12 @@ interface PageSpeedFormSubmissionResult {
|
|
|
386
386
|
formData: Record<string, any>;
|
|
387
387
|
responseData: unknown;
|
|
388
388
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
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 {
|
|
395
395
|
/**
|
|
396
396
|
* Optional callback triggered on successful submission.
|
|
397
397
|
*/
|
|
@@ -400,14 +400,6 @@ interface PageSpeedFormSubmissionConfig {
|
|
|
400
400
|
* Redirect destination used when behavior is "redirect".
|
|
401
401
|
*/
|
|
402
402
|
redirectUrl?: string;
|
|
403
|
-
/**
|
|
404
|
-
* Custom component rendered when behavior is "renderCustomComponent".
|
|
405
|
-
*/
|
|
406
|
-
customComponent?: ReactNode;
|
|
407
|
-
/**
|
|
408
|
-
* Optional action to allow a fresh submission after success.
|
|
409
|
-
*/
|
|
410
|
-
newFormSubmissionAction?: NewFormSubmissionActionConfig;
|
|
411
403
|
}
|
|
412
404
|
interface PageSpeedFormConfig {
|
|
413
405
|
/**
|
|
@@ -465,6 +457,12 @@ interface PageSpeedFormConfig {
|
|
|
465
457
|
* Optional post-submission behavior configuration.
|
|
466
458
|
*/
|
|
467
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;
|
|
468
466
|
}
|
|
469
467
|
declare class PageSpeedFormSubmissionError extends Error {
|
|
470
468
|
formErrors?: FormErrors;
|
|
@@ -477,116 +475,6 @@ declare class PageSpeedFormSubmissionError extends Error {
|
|
|
477
475
|
declare function isValidEmail(value: string): boolean;
|
|
478
476
|
declare function submitPageSpeedForm(values: Record<string, any>, config?: PageSpeedFormConfig): Promise<unknown>;
|
|
479
477
|
|
|
480
|
-
/**
|
|
481
|
-
* Dynamic form field schema types and helpers.
|
|
482
|
-
*
|
|
483
|
-
* These utilities are intentionally exposed from the integration layer so
|
|
484
|
-
* block/rendering libraries can share one field schema contract.
|
|
485
|
-
*/
|
|
486
|
-
type FormFieldType = "text" | "email" | "search" | "password" | "tel" | "textarea" | "select" | "radio" | "checkbox" | "checkbox-group" | "number" | "url" | "date" | "date-picker" | "date-range" | "time" | "file" | "multi-select";
|
|
487
|
-
interface SelectOption {
|
|
488
|
-
value: string;
|
|
489
|
-
label: string;
|
|
490
|
-
disabled?: boolean;
|
|
491
|
-
description?: string;
|
|
492
|
-
}
|
|
493
|
-
interface FormFieldConfig {
|
|
494
|
-
/**
|
|
495
|
-
* Unique field name (used as the key in form values)
|
|
496
|
-
*/
|
|
497
|
-
name: string;
|
|
498
|
-
/**
|
|
499
|
-
* Field type
|
|
500
|
-
*/
|
|
501
|
-
type: FormFieldType;
|
|
502
|
-
/**
|
|
503
|
-
* Display label for the field
|
|
504
|
-
*/
|
|
505
|
-
label: string;
|
|
506
|
-
/**
|
|
507
|
-
* Placeholder text
|
|
508
|
-
*/
|
|
509
|
-
placeholder?: string;
|
|
510
|
-
/**
|
|
511
|
-
* Whether the field is required
|
|
512
|
-
* @default false
|
|
513
|
-
*/
|
|
514
|
-
required?: boolean;
|
|
515
|
-
/**
|
|
516
|
-
* Column span in grid layout (1-12)
|
|
517
|
-
* @default 12 (full width)
|
|
518
|
-
*/
|
|
519
|
-
columnSpan?: number;
|
|
520
|
-
/**
|
|
521
|
-
* Options for select/radio/checkbox-group fields
|
|
522
|
-
*/
|
|
523
|
-
options?: SelectOption[];
|
|
524
|
-
/**
|
|
525
|
-
* Number of rows for textarea
|
|
526
|
-
* @default 4
|
|
527
|
-
*/
|
|
528
|
-
rows?: number;
|
|
529
|
-
/**
|
|
530
|
-
* Custom validation function
|
|
531
|
-
* Return undefined for valid, or an error message string for invalid
|
|
532
|
-
*/
|
|
533
|
-
validator?: (value: any, allValues: Record<string, any>) => string | undefined;
|
|
534
|
-
/**
|
|
535
|
-
* Additional CSS classes for the field wrapper
|
|
536
|
-
*/
|
|
537
|
-
className?: string;
|
|
538
|
-
/**
|
|
539
|
-
* Whether the field is disabled
|
|
540
|
-
* @default false
|
|
541
|
-
*/
|
|
542
|
-
disabled?: boolean;
|
|
543
|
-
/**
|
|
544
|
-
* Accepted file types for file inputs (MIME types or extensions)
|
|
545
|
-
* @example ".pdf,.doc,.docx"
|
|
546
|
-
* @example "image/*,application/pdf"
|
|
547
|
-
*/
|
|
548
|
-
accept?: string;
|
|
549
|
-
/**
|
|
550
|
-
* Maximum file size in bytes for file inputs
|
|
551
|
-
* @default 5MB (5 * 1024 * 1024)
|
|
552
|
-
*/
|
|
553
|
-
maxSize?: number;
|
|
554
|
-
/**
|
|
555
|
-
* Maximum number of files for file inputs
|
|
556
|
-
* @default 1
|
|
557
|
-
*/
|
|
558
|
-
maxFiles?: number;
|
|
559
|
-
/**
|
|
560
|
-
* Allow multiple file selection
|
|
561
|
-
* @default false
|
|
562
|
-
*/
|
|
563
|
-
multiple?: boolean;
|
|
564
|
-
/**
|
|
565
|
-
* Description/help text displayed with the field
|
|
566
|
-
*/
|
|
567
|
-
description?: string;
|
|
568
|
-
/**
|
|
569
|
-
* Layout for radio/checkbox groups
|
|
570
|
-
* @default "stacked"
|
|
571
|
-
*/
|
|
572
|
-
layout?: "grid" | "stacked";
|
|
573
|
-
}
|
|
574
|
-
/**
|
|
575
|
-
* Generate initial values object from form field configs.
|
|
576
|
-
*/
|
|
577
|
-
declare function generateInitialValues(fields: FormFieldConfig[]): Record<string, any>;
|
|
578
|
-
/**
|
|
579
|
-
* Generate validation schema from form field configs.
|
|
580
|
-
*/
|
|
581
|
-
declare function generateValidationSchema(fields: FormFieldConfig[]): Record<string, (value: any, allValues: Record<string, any>) => string | undefined>;
|
|
582
|
-
/**
|
|
583
|
-
* Get grid column span class for Tailwind.
|
|
584
|
-
*
|
|
585
|
-
* On small screens the field is always full-width, then from `md` and up the
|
|
586
|
-
* configured span is applied.
|
|
587
|
-
*/
|
|
588
|
-
declare function getColumnSpanClass(span?: number): string;
|
|
589
|
-
|
|
590
478
|
interface FileUploadProgress {
|
|
591
479
|
[fileName: string]: number;
|
|
592
480
|
}
|
|
@@ -681,4 +569,92 @@ interface DynamicFormFieldProps {
|
|
|
681
569
|
*/
|
|
682
570
|
declare function DynamicFormField({ field, className, uploadProgress, onFileUpload, onFileRemove, isUploading, renderLabel, }: DynamicFormFieldProps): React.JSX.Element;
|
|
683
571
|
|
|
684
|
-
|
|
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.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
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';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @page-speed/forms - Rails API Serializer
|
|
@@ -386,12 +386,12 @@ interface PageSpeedFormSubmissionResult {
|
|
|
386
386
|
formData: Record<string, any>;
|
|
387
387
|
responseData: unknown;
|
|
388
388
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
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 {
|
|
395
395
|
/**
|
|
396
396
|
* Optional callback triggered on successful submission.
|
|
397
397
|
*/
|
|
@@ -400,14 +400,6 @@ interface PageSpeedFormSubmissionConfig {
|
|
|
400
400
|
* Redirect destination used when behavior is "redirect".
|
|
401
401
|
*/
|
|
402
402
|
redirectUrl?: string;
|
|
403
|
-
/**
|
|
404
|
-
* Custom component rendered when behavior is "renderCustomComponent".
|
|
405
|
-
*/
|
|
406
|
-
customComponent?: ReactNode;
|
|
407
|
-
/**
|
|
408
|
-
* Optional action to allow a fresh submission after success.
|
|
409
|
-
*/
|
|
410
|
-
newFormSubmissionAction?: NewFormSubmissionActionConfig;
|
|
411
403
|
}
|
|
412
404
|
interface PageSpeedFormConfig {
|
|
413
405
|
/**
|
|
@@ -465,6 +457,12 @@ interface PageSpeedFormConfig {
|
|
|
465
457
|
* Optional post-submission behavior configuration.
|
|
466
458
|
*/
|
|
467
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;
|
|
468
466
|
}
|
|
469
467
|
declare class PageSpeedFormSubmissionError extends Error {
|
|
470
468
|
formErrors?: FormErrors;
|
|
@@ -477,116 +475,6 @@ declare class PageSpeedFormSubmissionError extends Error {
|
|
|
477
475
|
declare function isValidEmail(value: string): boolean;
|
|
478
476
|
declare function submitPageSpeedForm(values: Record<string, any>, config?: PageSpeedFormConfig): Promise<unknown>;
|
|
479
477
|
|
|
480
|
-
/**
|
|
481
|
-
* Dynamic form field schema types and helpers.
|
|
482
|
-
*
|
|
483
|
-
* These utilities are intentionally exposed from the integration layer so
|
|
484
|
-
* block/rendering libraries can share one field schema contract.
|
|
485
|
-
*/
|
|
486
|
-
type FormFieldType = "text" | "email" | "search" | "password" | "tel" | "textarea" | "select" | "radio" | "checkbox" | "checkbox-group" | "number" | "url" | "date" | "date-picker" | "date-range" | "time" | "file" | "multi-select";
|
|
487
|
-
interface SelectOption {
|
|
488
|
-
value: string;
|
|
489
|
-
label: string;
|
|
490
|
-
disabled?: boolean;
|
|
491
|
-
description?: string;
|
|
492
|
-
}
|
|
493
|
-
interface FormFieldConfig {
|
|
494
|
-
/**
|
|
495
|
-
* Unique field name (used as the key in form values)
|
|
496
|
-
*/
|
|
497
|
-
name: string;
|
|
498
|
-
/**
|
|
499
|
-
* Field type
|
|
500
|
-
*/
|
|
501
|
-
type: FormFieldType;
|
|
502
|
-
/**
|
|
503
|
-
* Display label for the field
|
|
504
|
-
*/
|
|
505
|
-
label: string;
|
|
506
|
-
/**
|
|
507
|
-
* Placeholder text
|
|
508
|
-
*/
|
|
509
|
-
placeholder?: string;
|
|
510
|
-
/**
|
|
511
|
-
* Whether the field is required
|
|
512
|
-
* @default false
|
|
513
|
-
*/
|
|
514
|
-
required?: boolean;
|
|
515
|
-
/**
|
|
516
|
-
* Column span in grid layout (1-12)
|
|
517
|
-
* @default 12 (full width)
|
|
518
|
-
*/
|
|
519
|
-
columnSpan?: number;
|
|
520
|
-
/**
|
|
521
|
-
* Options for select/radio/checkbox-group fields
|
|
522
|
-
*/
|
|
523
|
-
options?: SelectOption[];
|
|
524
|
-
/**
|
|
525
|
-
* Number of rows for textarea
|
|
526
|
-
* @default 4
|
|
527
|
-
*/
|
|
528
|
-
rows?: number;
|
|
529
|
-
/**
|
|
530
|
-
* Custom validation function
|
|
531
|
-
* Return undefined for valid, or an error message string for invalid
|
|
532
|
-
*/
|
|
533
|
-
validator?: (value: any, allValues: Record<string, any>) => string | undefined;
|
|
534
|
-
/**
|
|
535
|
-
* Additional CSS classes for the field wrapper
|
|
536
|
-
*/
|
|
537
|
-
className?: string;
|
|
538
|
-
/**
|
|
539
|
-
* Whether the field is disabled
|
|
540
|
-
* @default false
|
|
541
|
-
*/
|
|
542
|
-
disabled?: boolean;
|
|
543
|
-
/**
|
|
544
|
-
* Accepted file types for file inputs (MIME types or extensions)
|
|
545
|
-
* @example ".pdf,.doc,.docx"
|
|
546
|
-
* @example "image/*,application/pdf"
|
|
547
|
-
*/
|
|
548
|
-
accept?: string;
|
|
549
|
-
/**
|
|
550
|
-
* Maximum file size in bytes for file inputs
|
|
551
|
-
* @default 5MB (5 * 1024 * 1024)
|
|
552
|
-
*/
|
|
553
|
-
maxSize?: number;
|
|
554
|
-
/**
|
|
555
|
-
* Maximum number of files for file inputs
|
|
556
|
-
* @default 1
|
|
557
|
-
*/
|
|
558
|
-
maxFiles?: number;
|
|
559
|
-
/**
|
|
560
|
-
* Allow multiple file selection
|
|
561
|
-
* @default false
|
|
562
|
-
*/
|
|
563
|
-
multiple?: boolean;
|
|
564
|
-
/**
|
|
565
|
-
* Description/help text displayed with the field
|
|
566
|
-
*/
|
|
567
|
-
description?: string;
|
|
568
|
-
/**
|
|
569
|
-
* Layout for radio/checkbox groups
|
|
570
|
-
* @default "stacked"
|
|
571
|
-
*/
|
|
572
|
-
layout?: "grid" | "stacked";
|
|
573
|
-
}
|
|
574
|
-
/**
|
|
575
|
-
* Generate initial values object from form field configs.
|
|
576
|
-
*/
|
|
577
|
-
declare function generateInitialValues(fields: FormFieldConfig[]): Record<string, any>;
|
|
578
|
-
/**
|
|
579
|
-
* Generate validation schema from form field configs.
|
|
580
|
-
*/
|
|
581
|
-
declare function generateValidationSchema(fields: FormFieldConfig[]): Record<string, (value: any, allValues: Record<string, any>) => string | undefined>;
|
|
582
|
-
/**
|
|
583
|
-
* Get grid column span class for Tailwind.
|
|
584
|
-
*
|
|
585
|
-
* On small screens the field is always full-width, then from `md` and up the
|
|
586
|
-
* configured span is applied.
|
|
587
|
-
*/
|
|
588
|
-
declare function getColumnSpanClass(span?: number): string;
|
|
589
|
-
|
|
590
478
|
interface FileUploadProgress {
|
|
591
479
|
[fileName: string]: number;
|
|
592
480
|
}
|
|
@@ -681,4 +569,92 @@ interface DynamicFormFieldProps {
|
|
|
681
569
|
*/
|
|
682
570
|
declare function DynamicFormField({ field, className, uploadProgress, onFileUpload, onFileRemove, isUploading, renderLabel, }: DynamicFormFieldProps): React.JSX.Element;
|
|
683
571
|
|
|
684
|
-
|
|
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-
|
|
2
|
-
import { TextArea, Select, MultiSelect, Radio, Checkbox, CheckboxGroup, DatePicker, DateRangePicker, TimePicker, FileInput } from './chunk-
|
|
3
|
-
import { TextInput } from './chunk-
|
|
1
|
+
import { useForm, Field, Form } from './chunk-A7MVZ757.js';
|
|
2
|
+
import { TextArea, Select, MultiSelect, Radio, Checkbox, CheckboxGroup, DatePicker, DateRangePicker, TimePicker, FileInput } from './chunk-ML6FGUYS.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
|