@page-speed/forms 0.5.0 → 0.5.2

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.
@@ -1,4 +1,6 @@
1
1
  import * as React from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { d as FormSubmissionBehavior, N as NewFormSubmissionActionConfig, m as UseFormReturn } from './types-CnOCn7b3.cjs';
2
4
 
3
5
  /**
4
6
  * @page-speed/forms - Rails API Serializer
@@ -378,4 +380,299 @@ declare function standardInputTransformer(blockProps: Record<string, unknown>, b
378
380
  */
379
381
  declare function createBlockAdapters<TComponents extends Record<string, React.ComponentType<any>>>(components: TComponents, options?: BlockAdapterOptions): Record<keyof TComponents, React.ComponentType<AdaptedComponentProps>>;
380
382
 
381
- export { type AdaptedComponentProps, type Block, type BlockAdapterOptions, type FormErrors, type RailsApiConfig, type RailsErrorResponse, type SerializedFormData, createBlockAdapter, createBlockAdapters, deserializeErrors, serializeForRails, standardInputTransformer };
383
+ type PageSpeedFormMethod = "post" | "get" | "put" | "patch";
384
+ type PageSpeedFormSubmissionFormat = "json" | "rails";
385
+ interface PageSpeedFormSubmissionResult {
386
+ formData: Record<string, any>;
387
+ responseData: unknown;
388
+ }
389
+ interface PageSpeedFormSubmissionConfig {
390
+ /**
391
+ * Post-submit behavior.
392
+ * @default "showConfirmation"
393
+ */
394
+ behavior?: FormSubmissionBehavior;
395
+ /**
396
+ * Optional callback triggered on successful submission.
397
+ */
398
+ handleFormSubmission?: (result: PageSpeedFormSubmissionResult) => void | Promise<void>;
399
+ /**
400
+ * Redirect destination used when behavior is "redirect".
401
+ */
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
+ }
412
+ interface PageSpeedFormConfig {
413
+ /**
414
+ * API endpoint used for submission (also applied to form action).
415
+ */
416
+ endpoint?: string;
417
+ /**
418
+ * HTTP method for submission.
419
+ * @default "post"
420
+ */
421
+ method?: PageSpeedFormMethod;
422
+ /**
423
+ * Submission format.
424
+ * Defaults to "rails" when apiKey is present, otherwise "json".
425
+ */
426
+ format?: PageSpeedFormSubmissionFormat;
427
+ /**
428
+ * Additional headers for the submission request.
429
+ */
430
+ headers?: Record<string, string>;
431
+ /**
432
+ * Static values merged into the payload (e.g. subject, content).
433
+ */
434
+ values?: Record<string, unknown>;
435
+ /**
436
+ * Rails API key (required for rails format).
437
+ */
438
+ apiKey?: string;
439
+ /**
440
+ * Rails contact category token.
441
+ */
442
+ contactCategoryToken?: string;
443
+ /**
444
+ * Rails location ID.
445
+ */
446
+ locationId?: string;
447
+ /**
448
+ * Rails website ID.
449
+ */
450
+ websiteId?: string;
451
+ /**
452
+ * Rails website form assignment ID.
453
+ */
454
+ websiteFormAssignmentId?: string;
455
+ /**
456
+ * Rails visitor IP address override.
457
+ */
458
+ visitorIpAddress?: string;
459
+ /**
460
+ * Reset form values after a successful submission.
461
+ * @default true
462
+ */
463
+ resetOnSuccess?: boolean;
464
+ /**
465
+ * Optional post-submission behavior configuration.
466
+ */
467
+ submissionConfig?: PageSpeedFormSubmissionConfig;
468
+ }
469
+ declare class PageSpeedFormSubmissionError extends Error {
470
+ formErrors?: FormErrors;
471
+ status?: number;
472
+ constructor(message: string, options?: {
473
+ formErrors?: FormErrors;
474
+ status?: number;
475
+ });
476
+ }
477
+ declare function isValidEmail(value: string): boolean;
478
+ declare function submitPageSpeedForm(values: Record<string, any>, config?: PageSpeedFormConfig): Promise<unknown>;
479
+
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
+ interface FileUploadProgress {
591
+ [fileName: string]: number;
592
+ }
593
+ interface UseFileUploadReturn {
594
+ uploadTokens: string[];
595
+ uploadProgress: FileUploadProgress;
596
+ isUploading: boolean;
597
+ uploadFiles: (files: File[]) => Promise<void>;
598
+ removeFile: (file: File, index: number) => void;
599
+ resetUpload: () => void;
600
+ }
601
+ interface UseFileUploadOptions {
602
+ onError?: (error: Error) => void;
603
+ /**
604
+ * Upload endpoint.
605
+ *
606
+ * Defaults to DashTrack contact form uploads endpoint.
607
+ */
608
+ endpoint?: string;
609
+ }
610
+ /**
611
+ * Upload helper for two-phase contact form uploads.
612
+ */
613
+ declare function useFileUpload(options?: UseFileUploadOptions): UseFileUploadReturn;
614
+
615
+ interface UseContactFormOptions {
616
+ /**
617
+ * Form field configurations.
618
+ */
619
+ formFields: FormFieldConfig[];
620
+ /**
621
+ * Form submission configuration.
622
+ */
623
+ formConfig?: PageSpeedFormConfig;
624
+ /**
625
+ * Optional custom submit handler.
626
+ */
627
+ onSubmit?: (values: Record<string, any>) => void | Promise<void>;
628
+ /**
629
+ * Optional success callback.
630
+ */
631
+ onSuccess?: (data: unknown) => void;
632
+ /**
633
+ * Optional error callback.
634
+ */
635
+ onError?: (error: Error) => void;
636
+ /**
637
+ * Reset form values after successful submission.
638
+ * @default true
639
+ */
640
+ resetOnSuccess?: boolean;
641
+ /**
642
+ * File upload tokens merged into payload.
643
+ */
644
+ uploadTokens?: string[];
645
+ /**
646
+ * Optional app-level navigation handler for internal redirects.
647
+ * Return `false` to force fallback browser navigation.
648
+ */
649
+ navigate?: (href: string) => boolean | void;
650
+ }
651
+ interface UseContactFormReturn {
652
+ form: UseFormReturn<Record<string, any>>;
653
+ isSubmitted: boolean;
654
+ submissionError: string | null;
655
+ formMethod: "get" | "post";
656
+ resetSubmissionState: () => void;
657
+ }
658
+ /**
659
+ * Form orchestration helper for dynamic contact forms.
660
+ */
661
+ declare function useContactForm(options: UseContactFormOptions): UseContactFormReturn;
662
+
663
+ interface DynamicFormFieldProps {
664
+ field: FormFieldConfig;
665
+ className?: string;
666
+ uploadProgress?: {
667
+ [fileName: string]: number;
668
+ };
669
+ onFileUpload?: (files: File[]) => Promise<void>;
670
+ onFileRemove?: (file: File, index: number) => void;
671
+ isUploading?: boolean;
672
+ }
673
+ /**
674
+ * Dynamic renderer for form field schema configuration.
675
+ */
676
+ declare function DynamicFormField({ field, className, uploadProgress, onFileUpload, onFileRemove, isUploading, }: DynamicFormFieldProps): React.JSX.Element;
677
+
678
+ export { type AdaptedComponentProps, type Block, type BlockAdapterOptions, DynamicFormField, type DynamicFormFieldProps, type FileUploadProgress, type FormErrors, type FormFieldConfig, type FormFieldType, type PageSpeedFormConfig, type PageSpeedFormMethod, type PageSpeedFormSubmissionConfig, PageSpeedFormSubmissionError, type PageSpeedFormSubmissionFormat, type PageSpeedFormSubmissionResult, type RailsApiConfig, type RailsErrorResponse, type SelectOption, type SerializedFormData, type UseContactFormOptions, type UseContactFormReturn, type UseFileUploadOptions, type UseFileUploadReturn, createBlockAdapter, createBlockAdapters, deserializeErrors, generateInitialValues, generateValidationSchema, getColumnSpanClass, isValidEmail, serializeForRails, standardInputTransformer, submitPageSpeedForm, useContactForm, useFileUpload };
@@ -1,4 +1,6 @@
1
1
  import * as React from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { d as FormSubmissionBehavior, N as NewFormSubmissionActionConfig, m as UseFormReturn } from './types-CnOCn7b3.js';
2
4
 
3
5
  /**
4
6
  * @page-speed/forms - Rails API Serializer
@@ -378,4 +380,299 @@ declare function standardInputTransformer(blockProps: Record<string, unknown>, b
378
380
  */
379
381
  declare function createBlockAdapters<TComponents extends Record<string, React.ComponentType<any>>>(components: TComponents, options?: BlockAdapterOptions): Record<keyof TComponents, React.ComponentType<AdaptedComponentProps>>;
380
382
 
381
- export { type AdaptedComponentProps, type Block, type BlockAdapterOptions, type FormErrors, type RailsApiConfig, type RailsErrorResponse, type SerializedFormData, createBlockAdapter, createBlockAdapters, deserializeErrors, serializeForRails, standardInputTransformer };
383
+ type PageSpeedFormMethod = "post" | "get" | "put" | "patch";
384
+ type PageSpeedFormSubmissionFormat = "json" | "rails";
385
+ interface PageSpeedFormSubmissionResult {
386
+ formData: Record<string, any>;
387
+ responseData: unknown;
388
+ }
389
+ interface PageSpeedFormSubmissionConfig {
390
+ /**
391
+ * Post-submit behavior.
392
+ * @default "showConfirmation"
393
+ */
394
+ behavior?: FormSubmissionBehavior;
395
+ /**
396
+ * Optional callback triggered on successful submission.
397
+ */
398
+ handleFormSubmission?: (result: PageSpeedFormSubmissionResult) => void | Promise<void>;
399
+ /**
400
+ * Redirect destination used when behavior is "redirect".
401
+ */
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
+ }
412
+ interface PageSpeedFormConfig {
413
+ /**
414
+ * API endpoint used for submission (also applied to form action).
415
+ */
416
+ endpoint?: string;
417
+ /**
418
+ * HTTP method for submission.
419
+ * @default "post"
420
+ */
421
+ method?: PageSpeedFormMethod;
422
+ /**
423
+ * Submission format.
424
+ * Defaults to "rails" when apiKey is present, otherwise "json".
425
+ */
426
+ format?: PageSpeedFormSubmissionFormat;
427
+ /**
428
+ * Additional headers for the submission request.
429
+ */
430
+ headers?: Record<string, string>;
431
+ /**
432
+ * Static values merged into the payload (e.g. subject, content).
433
+ */
434
+ values?: Record<string, unknown>;
435
+ /**
436
+ * Rails API key (required for rails format).
437
+ */
438
+ apiKey?: string;
439
+ /**
440
+ * Rails contact category token.
441
+ */
442
+ contactCategoryToken?: string;
443
+ /**
444
+ * Rails location ID.
445
+ */
446
+ locationId?: string;
447
+ /**
448
+ * Rails website ID.
449
+ */
450
+ websiteId?: string;
451
+ /**
452
+ * Rails website form assignment ID.
453
+ */
454
+ websiteFormAssignmentId?: string;
455
+ /**
456
+ * Rails visitor IP address override.
457
+ */
458
+ visitorIpAddress?: string;
459
+ /**
460
+ * Reset form values after a successful submission.
461
+ * @default true
462
+ */
463
+ resetOnSuccess?: boolean;
464
+ /**
465
+ * Optional post-submission behavior configuration.
466
+ */
467
+ submissionConfig?: PageSpeedFormSubmissionConfig;
468
+ }
469
+ declare class PageSpeedFormSubmissionError extends Error {
470
+ formErrors?: FormErrors;
471
+ status?: number;
472
+ constructor(message: string, options?: {
473
+ formErrors?: FormErrors;
474
+ status?: number;
475
+ });
476
+ }
477
+ declare function isValidEmail(value: string): boolean;
478
+ declare function submitPageSpeedForm(values: Record<string, any>, config?: PageSpeedFormConfig): Promise<unknown>;
479
+
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
+ interface FileUploadProgress {
591
+ [fileName: string]: number;
592
+ }
593
+ interface UseFileUploadReturn {
594
+ uploadTokens: string[];
595
+ uploadProgress: FileUploadProgress;
596
+ isUploading: boolean;
597
+ uploadFiles: (files: File[]) => Promise<void>;
598
+ removeFile: (file: File, index: number) => void;
599
+ resetUpload: () => void;
600
+ }
601
+ interface UseFileUploadOptions {
602
+ onError?: (error: Error) => void;
603
+ /**
604
+ * Upload endpoint.
605
+ *
606
+ * Defaults to DashTrack contact form uploads endpoint.
607
+ */
608
+ endpoint?: string;
609
+ }
610
+ /**
611
+ * Upload helper for two-phase contact form uploads.
612
+ */
613
+ declare function useFileUpload(options?: UseFileUploadOptions): UseFileUploadReturn;
614
+
615
+ interface UseContactFormOptions {
616
+ /**
617
+ * Form field configurations.
618
+ */
619
+ formFields: FormFieldConfig[];
620
+ /**
621
+ * Form submission configuration.
622
+ */
623
+ formConfig?: PageSpeedFormConfig;
624
+ /**
625
+ * Optional custom submit handler.
626
+ */
627
+ onSubmit?: (values: Record<string, any>) => void | Promise<void>;
628
+ /**
629
+ * Optional success callback.
630
+ */
631
+ onSuccess?: (data: unknown) => void;
632
+ /**
633
+ * Optional error callback.
634
+ */
635
+ onError?: (error: Error) => void;
636
+ /**
637
+ * Reset form values after successful submission.
638
+ * @default true
639
+ */
640
+ resetOnSuccess?: boolean;
641
+ /**
642
+ * File upload tokens merged into payload.
643
+ */
644
+ uploadTokens?: string[];
645
+ /**
646
+ * Optional app-level navigation handler for internal redirects.
647
+ * Return `false` to force fallback browser navigation.
648
+ */
649
+ navigate?: (href: string) => boolean | void;
650
+ }
651
+ interface UseContactFormReturn {
652
+ form: UseFormReturn<Record<string, any>>;
653
+ isSubmitted: boolean;
654
+ submissionError: string | null;
655
+ formMethod: "get" | "post";
656
+ resetSubmissionState: () => void;
657
+ }
658
+ /**
659
+ * Form orchestration helper for dynamic contact forms.
660
+ */
661
+ declare function useContactForm(options: UseContactFormOptions): UseContactFormReturn;
662
+
663
+ interface DynamicFormFieldProps {
664
+ field: FormFieldConfig;
665
+ className?: string;
666
+ uploadProgress?: {
667
+ [fileName: string]: number;
668
+ };
669
+ onFileUpload?: (files: File[]) => Promise<void>;
670
+ onFileRemove?: (file: File, index: number) => void;
671
+ isUploading?: boolean;
672
+ }
673
+ /**
674
+ * Dynamic renderer for form field schema configuration.
675
+ */
676
+ declare function DynamicFormField({ field, className, uploadProgress, onFileUpload, onFileRemove, isUploading, }: DynamicFormFieldProps): React.JSX.Element;
677
+
678
+ export { type AdaptedComponentProps, type Block, type BlockAdapterOptions, DynamicFormField, type DynamicFormFieldProps, type FileUploadProgress, type FormErrors, type FormFieldConfig, type FormFieldType, type PageSpeedFormConfig, type PageSpeedFormMethod, type PageSpeedFormSubmissionConfig, PageSpeedFormSubmissionError, type PageSpeedFormSubmissionFormat, type PageSpeedFormSubmissionResult, type RailsApiConfig, type RailsErrorResponse, type SelectOption, type SerializedFormData, type UseContactFormOptions, type UseContactFormReturn, type UseFileUploadOptions, type UseFileUploadReturn, createBlockAdapter, createBlockAdapters, deserializeErrors, generateInitialValues, generateValidationSchema, getColumnSpanClass, isValidEmail, serializeForRails, standardInputTransformer, submitPageSpeedForm, useContactForm, useFileUpload };