@rilaykit/forms 8.0.1 → 9.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +69 -82
- package/dist/index.d.ts +69 -82
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +13 -5
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { ril, FieldValidationConfig, ConditionalBehavior, FormFieldConfig, FormFieldRow, FormValidationConfig, FormValidator, FormConfiguration, ComponentRendererBaseProps, FormBodyRendererProps, ValidationError, ValidationResult, FormRowRendererProps, FormSubmitButtonRendererProps } from '@rilaykit/core';
|
|
3
|
-
export * from '@rilaykit/core';
|
|
2
|
+
import { ril, FieldValidationConfig, ConditionalBehavior, FormFieldConfig, FormFieldRow, FormValidationConfig, FormValidator, FormConfiguration, ComponentRendererBaseProps, FormBodyRendererProps, ValidationError, ValidationResult, MonitoringConfig, FormPerformanceMetrics, FormRowRendererProps, FormSubmitButtonRendererProps } from '@rilaykit/core';
|
|
4
3
|
import React$1 from 'react';
|
|
5
4
|
|
|
6
5
|
/**
|
|
@@ -35,30 +34,46 @@ type FieldConfig<C extends Record<string, any>, T extends keyof C> = {
|
|
|
35
34
|
conditions?: ConditionalBehavior;
|
|
36
35
|
};
|
|
37
36
|
/**
|
|
38
|
-
* Form builder
|
|
37
|
+
* Form builder for creating type-safe form configurations
|
|
39
38
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* row organization, and form configuration generation.
|
|
39
|
+
* DX Notes (How to create a form):
|
|
40
|
+
* - Recommended: use the static factory
|
|
43
41
|
*
|
|
44
|
-
*
|
|
42
|
+
* const rilConfig = ril
|
|
43
|
+
* .create()
|
|
44
|
+
* .addComponent('text', { name: 'Text', renderer: TextInput })
|
|
45
|
+
* .addComponent('email', { name: 'Email', renderer: EmailInput });
|
|
45
46
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
47
|
+
* const myForm = form
|
|
48
|
+
* .create(rilConfig, 'contact-form')
|
|
49
|
+
* .add({ id: 'firstName', type: 'text', props: { label: 'First name' } })
|
|
50
|
+
* .add(
|
|
51
|
+
* { id: 'email', type: 'email', props: { label: 'Email' } },
|
|
52
|
+
* { id: 'role', type: 'text', props: { label: 'Role' } }
|
|
53
|
+
* )
|
|
54
|
+
* .build();
|
|
55
|
+
*
|
|
56
|
+
* - Or instantiate directly:
|
|
57
|
+
*
|
|
58
|
+
* const myForm = new form(rilConfig, 'contact-form')
|
|
59
|
+
* .add({ id: 'firstName', type: 'text' })
|
|
60
|
+
* .build();
|
|
61
|
+
*
|
|
62
|
+
* Why we do not augment ril with .form():
|
|
63
|
+
* - Keep the API explicit and bundler-friendly (no prototype/module augmentation)
|
|
64
|
+
* - Better discoverability and IntelliSense via the builder class
|
|
65
|
+
*
|
|
66
|
+
* Typing & autocomplete:
|
|
67
|
+
* - Types flow from your ril configuration: once components are registered,
|
|
68
|
+
* the `type` and `props` of `.add({ ... })` are fully typed.
|
|
57
69
|
*
|
|
58
|
-
*
|
|
59
|
-
* -
|
|
60
|
-
* -
|
|
61
|
-
* -
|
|
70
|
+
* Adding fields:
|
|
71
|
+
* - Variadic: .add(fieldA, fieldB) => same row (max 3 per row)
|
|
72
|
+
* - Array: .add([fieldA, fieldB]) => explicit single row
|
|
73
|
+
* - >3 fields (variadic) => split across multiple rows automatically
|
|
74
|
+
*
|
|
75
|
+
* Output of .build(): FormConfiguration<C>
|
|
76
|
+
* - id, rows, allFields, renderConfig (from ril), optional validation
|
|
62
77
|
*/
|
|
63
78
|
declare class form<C extends Record<string, any> = Record<string, never>> {
|
|
64
79
|
/** The ril configuration instance containing component definitions */
|
|
@@ -84,17 +99,18 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
|
|
|
84
99
|
*/
|
|
85
100
|
constructor(config: ril<C>, formId?: string);
|
|
86
101
|
/**
|
|
87
|
-
* Static factory
|
|
102
|
+
* Static factory to create a new form builder
|
|
88
103
|
*
|
|
89
|
-
*
|
|
90
|
-
* @param config - The ril configuration instance
|
|
91
|
-
* @param formId - Optional form identifier
|
|
92
|
-
* @returns A new form builder instance
|
|
104
|
+
* Usage (recommended):
|
|
93
105
|
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
106
|
+
* const myForm = form
|
|
107
|
+
* .create(rilConfig, 'my-form')
|
|
108
|
+
* .add({ id: 'email', type: 'email', props: { label: 'Email' } })
|
|
109
|
+
* .build();
|
|
110
|
+
*
|
|
111
|
+
* Why prefer this over `new form(...)`?
|
|
112
|
+
* - Clearer intent and better discoverability
|
|
113
|
+
* - Consistent with other builder APIs
|
|
98
114
|
*/
|
|
99
115
|
static create<Cm extends Record<string, any> = Record<string, never>>(config: ril<Cm>, formId?: string): form<Cm>;
|
|
100
116
|
/**
|
|
@@ -437,7 +453,7 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
|
|
|
437
453
|
* - Render configuration for customization
|
|
438
454
|
* - Form-level validation configuration
|
|
439
455
|
*/
|
|
440
|
-
build(): FormConfiguration
|
|
456
|
+
build(): FormConfiguration<C>;
|
|
441
457
|
/**
|
|
442
458
|
* Exports the form configuration as JSON
|
|
443
459
|
*
|
|
@@ -510,52 +526,9 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
|
|
|
510
526
|
minFieldsInRow: number;
|
|
511
527
|
};
|
|
512
528
|
}
|
|
513
|
-
/**
|
|
514
|
-
* Factory function to create a form builder directly
|
|
515
|
-
*
|
|
516
|
-
* This is a convenience function that provides an alternative to using
|
|
517
|
-
* the class constructor or static create method. It's particularly useful
|
|
518
|
-
* for functional programming styles or when you prefer function calls
|
|
519
|
-
* over class instantiation.
|
|
520
|
-
*
|
|
521
|
-
* @template C - Component configuration map
|
|
522
|
-
* @param config - The ril configuration instance
|
|
523
|
-
* @param formId - Optional form identifier
|
|
524
|
-
* @returns A new form builder instance
|
|
525
|
-
*
|
|
526
|
-
* @example
|
|
527
|
-
* ```typescript
|
|
528
|
-
* const builder = createForm(rilConfig, 'contact-form')
|
|
529
|
-
* .add({ type: 'text', props: { label: 'Name' } })
|
|
530
|
-
* .add({ type: 'email', props: { label: 'Email' } });
|
|
531
|
-
* ```
|
|
532
|
-
*/
|
|
533
|
-
declare function createForm<C extends Record<string, any>>(config: ril<C>, formId?: string): form<C>;
|
|
534
|
-
/**
|
|
535
|
-
* Module augmentation to add createForm method to ril instances
|
|
536
|
-
*
|
|
537
|
-
* This declaration extends the ril interface to include the createForm
|
|
538
|
-
* method, allowing for a more integrated API experience.
|
|
539
|
-
*/
|
|
540
|
-
declare module '@rilaykit/core' {
|
|
541
|
-
interface ril<C extends Record<string, any> = Record<string, never>> {
|
|
542
|
-
/**
|
|
543
|
-
* Creates a new form builder using this ril configuration
|
|
544
|
-
*
|
|
545
|
-
* @param formId - Optional form identifier
|
|
546
|
-
* @returns A new form builder instance
|
|
547
|
-
*
|
|
548
|
-
* @example
|
|
549
|
-
* ```typescript
|
|
550
|
-
* const builder = rilConfig.createForm('my-form');
|
|
551
|
-
* ```
|
|
552
|
-
*/
|
|
553
|
-
form(formId?: string): form<C>;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
529
|
|
|
557
530
|
interface FormProps {
|
|
558
|
-
formConfig: FormConfiguration | form
|
|
531
|
+
formConfig: FormConfiguration<any> | form<any>;
|
|
559
532
|
defaultValues?: Record<string, any>;
|
|
560
533
|
onSubmit?: (data: Record<string, any>) => void | Promise<void>;
|
|
561
534
|
onFieldChange?: (fieldId: string, value: any, formData: Record<string, any>) => void;
|
|
@@ -564,17 +537,16 @@ interface FormProps {
|
|
|
564
537
|
}
|
|
565
538
|
declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, children }: FormProps): react_jsx_runtime.JSX.Element;
|
|
566
539
|
|
|
567
|
-
declare
|
|
540
|
+
declare const FormBody: React$1.NamedExoticComponent<ComponentRendererBaseProps<FormBodyRendererProps>>;
|
|
568
541
|
|
|
569
542
|
interface FormFieldProps {
|
|
570
543
|
fieldId: string;
|
|
571
544
|
disabled?: boolean;
|
|
572
545
|
customProps?: Record<string, any>;
|
|
573
546
|
className?: string;
|
|
574
|
-
/** Force field to be visible even if conditions say otherwise (for debugging) */
|
|
575
547
|
forceVisible?: boolean;
|
|
576
548
|
}
|
|
577
|
-
declare
|
|
549
|
+
declare const FormField: React$1.NamedExoticComponent<FormFieldProps>;
|
|
578
550
|
|
|
579
551
|
interface ConditionEvaluationResult {
|
|
580
552
|
visible: boolean;
|
|
@@ -709,6 +681,21 @@ declare function useFormValidation({ formConfig, formState, conditionsHelpers, s
|
|
|
709
681
|
validateForm: () => Promise<ValidationResult>;
|
|
710
682
|
};
|
|
711
683
|
|
|
684
|
+
interface UseFormMonitoringProps {
|
|
685
|
+
formConfig: FormConfiguration;
|
|
686
|
+
monitoring?: MonitoringConfig;
|
|
687
|
+
enabled?: boolean;
|
|
688
|
+
}
|
|
689
|
+
interface UseFormMonitoringReturn {
|
|
690
|
+
trackFormRender: (renderCount?: number) => void;
|
|
691
|
+
trackFormValidation: (validationErrors: number, fieldCount?: number) => void;
|
|
692
|
+
trackFormSubmission: (success: boolean, fieldCount?: number) => void;
|
|
693
|
+
trackFieldChange: (fieldId: string, componentType: string) => void;
|
|
694
|
+
startPerformanceTracking: (label: string) => void;
|
|
695
|
+
endPerformanceTracking: (label: string) => FormPerformanceMetrics | null;
|
|
696
|
+
}
|
|
697
|
+
declare function useFormMonitoring({ formConfig, enabled, }: UseFormMonitoringProps): UseFormMonitoringReturn;
|
|
698
|
+
|
|
712
699
|
interface FormContextValue {
|
|
713
700
|
formState: FormState;
|
|
714
701
|
formConfig: FormConfiguration;
|
|
@@ -738,7 +725,7 @@ declare function useFormContext(): FormContextValue;
|
|
|
738
725
|
interface FormRowProps extends ComponentRendererBaseProps<FormRowRendererProps> {
|
|
739
726
|
row: FormFieldRow;
|
|
740
727
|
}
|
|
741
|
-
declare
|
|
728
|
+
declare const FormRow: React$1.NamedExoticComponent<FormRowProps>;
|
|
742
729
|
|
|
743
730
|
interface FormSubmitButtonProps extends ComponentRendererBaseProps<FormSubmitButtonRendererProps> {
|
|
744
731
|
/**
|
|
@@ -747,6 +734,6 @@ interface FormSubmitButtonProps extends ComponentRendererBaseProps<FormSubmitBut
|
|
|
747
734
|
*/
|
|
748
735
|
isSubmitting?: boolean;
|
|
749
736
|
}
|
|
750
|
-
declare
|
|
737
|
+
declare const FormSubmitButton: React$1.NamedExoticComponent<FormSubmitButtonProps>;
|
|
751
738
|
|
|
752
|
-
export { type ConditionEvaluationResult, type FieldConfig, Form, type FormAction, FormBody, form as FormBuilder, FormField, FormProvider, FormRow, type FormState, FormSubmitButton, type UseFormConditionsProps, type UseFormConditionsReturn, type UseFormStateProps, type UseFormSubmissionProps, type UseFormValidationProps,
|
|
739
|
+
export { type ConditionEvaluationResult, type FieldConfig, Form, type FormAction, FormBody, form as FormBuilder, FormField, FormProvider, FormRow, type FormState, FormSubmitButton, type UseFormConditionsProps, type UseFormConditionsReturn, type UseFormMonitoringProps, type UseFormMonitoringReturn, type UseFormStateProps, type UseFormSubmissionProps, type UseFormValidationProps, form, useConditionEvaluation, useFormConditions, useFormContext, useFormMonitoring, useFormState, useFormSubmission, useFormValidation, useMultipleConditionEvaluation };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { ril, FieldValidationConfig, ConditionalBehavior, FormFieldConfig, FormFieldRow, FormValidationConfig, FormValidator, FormConfiguration, ComponentRendererBaseProps, FormBodyRendererProps, ValidationError, ValidationResult, FormRowRendererProps, FormSubmitButtonRendererProps } from '@rilaykit/core';
|
|
3
|
-
export * from '@rilaykit/core';
|
|
2
|
+
import { ril, FieldValidationConfig, ConditionalBehavior, FormFieldConfig, FormFieldRow, FormValidationConfig, FormValidator, FormConfiguration, ComponentRendererBaseProps, FormBodyRendererProps, ValidationError, ValidationResult, MonitoringConfig, FormPerformanceMetrics, FormRowRendererProps, FormSubmitButtonRendererProps } from '@rilaykit/core';
|
|
4
3
|
import React$1 from 'react';
|
|
5
4
|
|
|
6
5
|
/**
|
|
@@ -35,30 +34,46 @@ type FieldConfig<C extends Record<string, any>, T extends keyof C> = {
|
|
|
35
34
|
conditions?: ConditionalBehavior;
|
|
36
35
|
};
|
|
37
36
|
/**
|
|
38
|
-
* Form builder
|
|
37
|
+
* Form builder for creating type-safe form configurations
|
|
39
38
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* row organization, and form configuration generation.
|
|
39
|
+
* DX Notes (How to create a form):
|
|
40
|
+
* - Recommended: use the static factory
|
|
43
41
|
*
|
|
44
|
-
*
|
|
42
|
+
* const rilConfig = ril
|
|
43
|
+
* .create()
|
|
44
|
+
* .addComponent('text', { name: 'Text', renderer: TextInput })
|
|
45
|
+
* .addComponent('email', { name: 'Email', renderer: EmailInput });
|
|
45
46
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
47
|
+
* const myForm = form
|
|
48
|
+
* .create(rilConfig, 'contact-form')
|
|
49
|
+
* .add({ id: 'firstName', type: 'text', props: { label: 'First name' } })
|
|
50
|
+
* .add(
|
|
51
|
+
* { id: 'email', type: 'email', props: { label: 'Email' } },
|
|
52
|
+
* { id: 'role', type: 'text', props: { label: 'Role' } }
|
|
53
|
+
* )
|
|
54
|
+
* .build();
|
|
55
|
+
*
|
|
56
|
+
* - Or instantiate directly:
|
|
57
|
+
*
|
|
58
|
+
* const myForm = new form(rilConfig, 'contact-form')
|
|
59
|
+
* .add({ id: 'firstName', type: 'text' })
|
|
60
|
+
* .build();
|
|
61
|
+
*
|
|
62
|
+
* Why we do not augment ril with .form():
|
|
63
|
+
* - Keep the API explicit and bundler-friendly (no prototype/module augmentation)
|
|
64
|
+
* - Better discoverability and IntelliSense via the builder class
|
|
65
|
+
*
|
|
66
|
+
* Typing & autocomplete:
|
|
67
|
+
* - Types flow from your ril configuration: once components are registered,
|
|
68
|
+
* the `type` and `props` of `.add({ ... })` are fully typed.
|
|
57
69
|
*
|
|
58
|
-
*
|
|
59
|
-
* -
|
|
60
|
-
* -
|
|
61
|
-
* -
|
|
70
|
+
* Adding fields:
|
|
71
|
+
* - Variadic: .add(fieldA, fieldB) => same row (max 3 per row)
|
|
72
|
+
* - Array: .add([fieldA, fieldB]) => explicit single row
|
|
73
|
+
* - >3 fields (variadic) => split across multiple rows automatically
|
|
74
|
+
*
|
|
75
|
+
* Output of .build(): FormConfiguration<C>
|
|
76
|
+
* - id, rows, allFields, renderConfig (from ril), optional validation
|
|
62
77
|
*/
|
|
63
78
|
declare class form<C extends Record<string, any> = Record<string, never>> {
|
|
64
79
|
/** The ril configuration instance containing component definitions */
|
|
@@ -84,17 +99,18 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
|
|
|
84
99
|
*/
|
|
85
100
|
constructor(config: ril<C>, formId?: string);
|
|
86
101
|
/**
|
|
87
|
-
* Static factory
|
|
102
|
+
* Static factory to create a new form builder
|
|
88
103
|
*
|
|
89
|
-
*
|
|
90
|
-
* @param config - The ril configuration instance
|
|
91
|
-
* @param formId - Optional form identifier
|
|
92
|
-
* @returns A new form builder instance
|
|
104
|
+
* Usage (recommended):
|
|
93
105
|
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
106
|
+
* const myForm = form
|
|
107
|
+
* .create(rilConfig, 'my-form')
|
|
108
|
+
* .add({ id: 'email', type: 'email', props: { label: 'Email' } })
|
|
109
|
+
* .build();
|
|
110
|
+
*
|
|
111
|
+
* Why prefer this over `new form(...)`?
|
|
112
|
+
* - Clearer intent and better discoverability
|
|
113
|
+
* - Consistent with other builder APIs
|
|
98
114
|
*/
|
|
99
115
|
static create<Cm extends Record<string, any> = Record<string, never>>(config: ril<Cm>, formId?: string): form<Cm>;
|
|
100
116
|
/**
|
|
@@ -437,7 +453,7 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
|
|
|
437
453
|
* - Render configuration for customization
|
|
438
454
|
* - Form-level validation configuration
|
|
439
455
|
*/
|
|
440
|
-
build(): FormConfiguration
|
|
456
|
+
build(): FormConfiguration<C>;
|
|
441
457
|
/**
|
|
442
458
|
* Exports the form configuration as JSON
|
|
443
459
|
*
|
|
@@ -510,52 +526,9 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
|
|
|
510
526
|
minFieldsInRow: number;
|
|
511
527
|
};
|
|
512
528
|
}
|
|
513
|
-
/**
|
|
514
|
-
* Factory function to create a form builder directly
|
|
515
|
-
*
|
|
516
|
-
* This is a convenience function that provides an alternative to using
|
|
517
|
-
* the class constructor or static create method. It's particularly useful
|
|
518
|
-
* for functional programming styles or when you prefer function calls
|
|
519
|
-
* over class instantiation.
|
|
520
|
-
*
|
|
521
|
-
* @template C - Component configuration map
|
|
522
|
-
* @param config - The ril configuration instance
|
|
523
|
-
* @param formId - Optional form identifier
|
|
524
|
-
* @returns A new form builder instance
|
|
525
|
-
*
|
|
526
|
-
* @example
|
|
527
|
-
* ```typescript
|
|
528
|
-
* const builder = createForm(rilConfig, 'contact-form')
|
|
529
|
-
* .add({ type: 'text', props: { label: 'Name' } })
|
|
530
|
-
* .add({ type: 'email', props: { label: 'Email' } });
|
|
531
|
-
* ```
|
|
532
|
-
*/
|
|
533
|
-
declare function createForm<C extends Record<string, any>>(config: ril<C>, formId?: string): form<C>;
|
|
534
|
-
/**
|
|
535
|
-
* Module augmentation to add createForm method to ril instances
|
|
536
|
-
*
|
|
537
|
-
* This declaration extends the ril interface to include the createForm
|
|
538
|
-
* method, allowing for a more integrated API experience.
|
|
539
|
-
*/
|
|
540
|
-
declare module '@rilaykit/core' {
|
|
541
|
-
interface ril<C extends Record<string, any> = Record<string, never>> {
|
|
542
|
-
/**
|
|
543
|
-
* Creates a new form builder using this ril configuration
|
|
544
|
-
*
|
|
545
|
-
* @param formId - Optional form identifier
|
|
546
|
-
* @returns A new form builder instance
|
|
547
|
-
*
|
|
548
|
-
* @example
|
|
549
|
-
* ```typescript
|
|
550
|
-
* const builder = rilConfig.createForm('my-form');
|
|
551
|
-
* ```
|
|
552
|
-
*/
|
|
553
|
-
form(formId?: string): form<C>;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
529
|
|
|
557
530
|
interface FormProps {
|
|
558
|
-
formConfig: FormConfiguration | form
|
|
531
|
+
formConfig: FormConfiguration<any> | form<any>;
|
|
559
532
|
defaultValues?: Record<string, any>;
|
|
560
533
|
onSubmit?: (data: Record<string, any>) => void | Promise<void>;
|
|
561
534
|
onFieldChange?: (fieldId: string, value: any, formData: Record<string, any>) => void;
|
|
@@ -564,17 +537,16 @@ interface FormProps {
|
|
|
564
537
|
}
|
|
565
538
|
declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, children }: FormProps): react_jsx_runtime.JSX.Element;
|
|
566
539
|
|
|
567
|
-
declare
|
|
540
|
+
declare const FormBody: React$1.NamedExoticComponent<ComponentRendererBaseProps<FormBodyRendererProps>>;
|
|
568
541
|
|
|
569
542
|
interface FormFieldProps {
|
|
570
543
|
fieldId: string;
|
|
571
544
|
disabled?: boolean;
|
|
572
545
|
customProps?: Record<string, any>;
|
|
573
546
|
className?: string;
|
|
574
|
-
/** Force field to be visible even if conditions say otherwise (for debugging) */
|
|
575
547
|
forceVisible?: boolean;
|
|
576
548
|
}
|
|
577
|
-
declare
|
|
549
|
+
declare const FormField: React$1.NamedExoticComponent<FormFieldProps>;
|
|
578
550
|
|
|
579
551
|
interface ConditionEvaluationResult {
|
|
580
552
|
visible: boolean;
|
|
@@ -709,6 +681,21 @@ declare function useFormValidation({ formConfig, formState, conditionsHelpers, s
|
|
|
709
681
|
validateForm: () => Promise<ValidationResult>;
|
|
710
682
|
};
|
|
711
683
|
|
|
684
|
+
interface UseFormMonitoringProps {
|
|
685
|
+
formConfig: FormConfiguration;
|
|
686
|
+
monitoring?: MonitoringConfig;
|
|
687
|
+
enabled?: boolean;
|
|
688
|
+
}
|
|
689
|
+
interface UseFormMonitoringReturn {
|
|
690
|
+
trackFormRender: (renderCount?: number) => void;
|
|
691
|
+
trackFormValidation: (validationErrors: number, fieldCount?: number) => void;
|
|
692
|
+
trackFormSubmission: (success: boolean, fieldCount?: number) => void;
|
|
693
|
+
trackFieldChange: (fieldId: string, componentType: string) => void;
|
|
694
|
+
startPerformanceTracking: (label: string) => void;
|
|
695
|
+
endPerformanceTracking: (label: string) => FormPerformanceMetrics | null;
|
|
696
|
+
}
|
|
697
|
+
declare function useFormMonitoring({ formConfig, enabled, }: UseFormMonitoringProps): UseFormMonitoringReturn;
|
|
698
|
+
|
|
712
699
|
interface FormContextValue {
|
|
713
700
|
formState: FormState;
|
|
714
701
|
formConfig: FormConfiguration;
|
|
@@ -738,7 +725,7 @@ declare function useFormContext(): FormContextValue;
|
|
|
738
725
|
interface FormRowProps extends ComponentRendererBaseProps<FormRowRendererProps> {
|
|
739
726
|
row: FormFieldRow;
|
|
740
727
|
}
|
|
741
|
-
declare
|
|
728
|
+
declare const FormRow: React$1.NamedExoticComponent<FormRowProps>;
|
|
742
729
|
|
|
743
730
|
interface FormSubmitButtonProps extends ComponentRendererBaseProps<FormSubmitButtonRendererProps> {
|
|
744
731
|
/**
|
|
@@ -747,6 +734,6 @@ interface FormSubmitButtonProps extends ComponentRendererBaseProps<FormSubmitBut
|
|
|
747
734
|
*/
|
|
748
735
|
isSubmitting?: boolean;
|
|
749
736
|
}
|
|
750
|
-
declare
|
|
737
|
+
declare const FormSubmitButton: React$1.NamedExoticComponent<FormSubmitButtonProps>;
|
|
751
738
|
|
|
752
|
-
export { type ConditionEvaluationResult, type FieldConfig, Form, type FormAction, FormBody, form as FormBuilder, FormField, FormProvider, FormRow, type FormState, FormSubmitButton, type UseFormConditionsProps, type UseFormConditionsReturn, type UseFormStateProps, type UseFormSubmissionProps, type UseFormValidationProps,
|
|
739
|
+
export { type ConditionEvaluationResult, type FieldConfig, Form, type FormAction, FormBody, form as FormBuilder, FormField, FormProvider, FormRow, type FormState, FormSubmitButton, type UseFormConditionsProps, type UseFormConditionsReturn, type UseFormMonitoringProps, type UseFormMonitoringReturn, type UseFormStateProps, type UseFormSubmissionProps, type UseFormValidationProps, form, useConditionEvaluation, useFormConditions, useFormContext, useFormMonitoring, useFormState, useFormSubmission, useFormValidation, useMultipleConditionEvaluation };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var Re=require('react'),core=require('@rilaykit/core'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var Re__default=/*#__PURE__*/_interopDefault(Re);var h=class i{constructor(e,o){this.rows=[];this.idGenerator=new core.IdGenerator;this.config=e,this.formId=o||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,o){return new i(e,o)}createFormField(e){let o=this.config.getComponent(e.type);if(!o)throw new Error(`No component found with type "${e.type}"`);let t;return (o.validation||e.validation)&&(t={validateOnChange:e.validation?.validateOnChange??o.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??o.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??o.validation?.debounceMs,validators:[...o.validation?.validators||[],...e.validation?.validators||[]]}),{id:e.id||this.idGenerator.next("field"),componentId:o.id,props:{...o.defaultProps,...e.props},validation:t,conditions:e.conditions}}createRow(e){if(e.length===0)throw new Error("At least one field is required");if(e.length>3)throw new Error("Maximum 3 fields per row");let o=e.map(t=>this.createFormField(t));return {id:this.idGenerator.next("row"),fields:o,maxColumns:e.length}}add(...e){let o,t=false;if(e.length===1&&Array.isArray(e[0])?(o=e[0],t=true):o=e,o.length===0)throw new Error("At least one field is required");if(t&&o.length>3)throw new Error("Maximum 3 fields per row");if(o.length===1){let r=this.createRow(o);return this.rows.push(r),this}if(o.length<=3){let r=this.createRow(o);return this.rows.push(r),this}for(let r of o){let d=this.createRow([r]);this.rows.push(d);}return this}addSeparateRows(e){for(let o of e)this.add(o);return this}setId(e){return this.formId=e,this}updateField(e,o){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);return Object.assign(t,{...o,props:{...t.props,...o.props}}),this}findField(e){for(let o of this.rows){let t=o.fields.find(r=>r.id===e);if(t)return t}return null}removeField(e){return this.rows=this.rows.map(o=>({...o,fields:o.fields.filter(t=>t.id!==e)})).filter(o=>o.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.idGenerator.reset(),this}setValidation(e){return this.formValidation=e,this}addValidators(e){return this.formValidation||(this.formValidation={validators:[]}),this.formValidation={...this.formValidation,validators:[...this.formValidation.validators||[],...e]},this}addFieldValidation(e,o){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let r={...t.validation,...o,validators:[...t.validation?.validators||[],...o.validators||[]]};return this.updateField(e,{validation:r})}addFieldConditions(e,o){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let r={...t.conditions,...o};return this.updateField(e,{conditions:r})}clone(e){let o=new i(this.config,e||`${this.formId}-clone`);return o.rows=core.deepClone(this.rows),o}validate(){let e=[],o=this.getFields(),t=o.map(r=>r.id);try{core.ensureUnique(t,"field");}catch(r){e.push(r instanceof Error?r.message:String(r));}for(let r of o)this.config.hasComponent(r.componentId)||e.push(`Component "${r.componentId}" not found for field "${r.id}"`);for(let r of this.rows)r.fields.length>3&&e.push(`Row "${r.id}" has ${r.fields.length} fields, maximum is 3`),r.fields.length===0&&e.push(`Row "${r.id}" is empty`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig(),validation:this.formValidation}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows),this}getStats(){let e=this.getFields(),o=this.rows.map(t=>t.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:o.length>0?Math.max(...o):0,minFieldsInRow:o.length>0?Math.min(...o):0}}};function ae(i,e){return h.create(i,e)}core.ril.prototype.form=function(i){return h.create(this,i)};function De(i,e={},o={}){return Re.useMemo(()=>{if(!i)return {visible:o.visible??true,disabled:o.disabled??false,required:o.required??false,readonly:o.readonly??false};let t=r=>{try{return r&&typeof r=="object"&&"build"in r?core.evaluateCondition(r.build(),e):core.evaluateCondition(r,e)}catch(d){return console.warn("Error evaluating condition:",d),false}};return {visible:i.visible?t(i.visible):o.visible??true,disabled:i.disabled?t(i.disabled):o.disabled??false,required:i.required?t(i.required):o.required??false,readonly:i.readonly?t(i.readonly):o.readonly??false}},[i,e,o])}function L(i,e={}){return Re.useMemo(()=>{let o={};for(let[t,r]of Object.entries(i))if(o[t]={visible:true,disabled:false,required:false,readonly:false},r){let d=m=>{try{return m&&typeof m=="object"&&"build"in m?core.evaluateCondition(m.build(),e):core.evaluateCondition(m,e)}catch(s){return console.warn(`Error evaluating condition for field ${t}:`,s),false}};o[t]={visible:r.visible?d(r.visible):true,disabled:r.disabled?d(r.disabled):false,required:r.required?d(r.required):false,readonly:r.readonly?d(r.readonly):false};}return o},[i,e])}function $({formConfig:i,formValues:e}){let o=Re.useMemo(()=>{let l={};for(let a of i.allFields)a.conditions&&(l[a.id]=a.conditions);return l},[i.allFields]),t=Re.useMemo(()=>Object.keys(o).length>0,[o]),r=L(t?o:{},t?e:{}),d=Re.useCallback(l=>r[l],[r]),m=Re.useCallback(l=>{let a=r[l];return a?a.visible:true},[r]),s=Re.useCallback(l=>{let a=r[l];return a?a.disabled:false},[r]),F=Re.useCallback(l=>{let a=r[l];return a?a.required:false},[r]),f=Re.useCallback(l=>{let a=r[l];return a?a.readonly:false},[r]);return Re.useMemo(()=>({fieldConditions:r,hasConditionalFields:t,getFieldCondition:d,isFieldVisible:m,isFieldDisabled:s,isFieldRequired:F,isFieldReadonly:f}),[r,t,d,m,s,F,f])}function ue(i,e){switch(e.type){case "SET_VALUE":return {...i,values:{...i.values,[e.fieldId]:e.value},isDirty:true};case "SET_FIELD_ERRORS":return {...i,errors:{...i.errors,[e.fieldId]:e.errors}};case "SET_FIELD_VALIDATION_STATE":return {...i,validationState:{...i.validationState,[e.fieldId]:e.state}};case "SET_FIELD_TOUCHED":return {...i,touched:{...i.touched,[e.fieldId]:true}};case "SET_SUBMITTING":return {...i,isSubmitting:e.isSubmitting};case "RESET":return {values:e.values||{},errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false};default:return i}}function G({defaultValues:i={},onFieldChange:e}){let o={values:i,errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false},[t,r]=Re.useReducer(ue,o),d=Re.useRef(e);d.current=e;let m=Re.useCallback((u,c)=>{r({type:"SET_VALUE",fieldId:u,value:c}),d.current?.(u,c,{...t.values,[u]:c});},[t.values]),s=Re.useCallback(u=>{r({type:"SET_FIELD_TOUCHED",fieldId:u});},[]),F=Re.useCallback((u,c)=>{r({type:"SET_FIELD_ERRORS",fieldId:u,errors:c});},[]),f=Re.useCallback(u=>{r({type:"SET_FIELD_ERRORS",fieldId:u,errors:[]});},[]),l=Re.useCallback((u,c)=>{r({type:"SET_FIELD_VALIDATION_STATE",fieldId:u,state:c});},[]),a=Re.useCallback(u=>{r({type:"SET_SUBMITTING",isSubmitting:u});},[]),n=Re.useCallback(u=>{r({type:"RESET",values:u});},[]),g=Re.useCallback(()=>{let u=Object.values(t.errors).some(p=>p.length>0),c=Object.values(t.validationState).some(p=>p==="invalid");return !u&&!c},[t.errors,t.validationState]);return {formState:t,setValue:m,setFieldTouched:s,setError:F,clearError:f,setFieldValidationState:l,setSubmitting:a,reset:n,isFormValid:g}}function W({formState:i,onSubmit:e,validateForm:o,setSubmitting:t}){let r=Re.useRef(e);return r.current=e,{submit:Re.useCallback(async m=>{m?.preventDefault();try{return t(!0),(await o()).isValid?(r.current&&await r.current(i.values),!0):!1}catch(s){return console.error("Error during form submission:",s),false}finally{t(false);}},[i.values,o,t])}}function k(){return {isValid:true,errors:[]}}function H({formConfig:i,formState:e,conditionsHelpers:o,setFieldValidationState:t,setError:r}){let d=Re.useCallback(async(s,F)=>{let f=i.allFields.find(n=>n.id===s);if(!f)return k();if(!o.isFieldVisible(s))return r(s,[]),t(s,"valid"),k();if(!f.validation?.validators?.length)return r(s,[]),t(s,"valid"),k();let l=F!==void 0?F:e.values[s],a=core.createValidationContext({fieldId:s,formId:i.id,allFormData:{...e.values,[s]:l}});t(s,"validating");try{let n=await core.runValidatorsAsync(f.validation.validators,l,a),g=o.isFieldRequired(s),u=l==null||l==="";if(g&&u&&!n.errors.some(p=>p.code==="REQUIRED"||p.message.toLowerCase().includes("required"))){let p={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...n.errors]};return r(s,p.errors),t(s,"invalid"),p}return r(s,n.errors),t(s,n.isValid?"valid":"invalid"),n}catch(n){let g={isValid:false,errors:[{message:n instanceof Error?n.message:"Validation failed",code:"VALIDATION_ERROR"}]};return r(s,g.errors),t(s,"invalid"),g}},[i,e.values,o,t,r]),m=Re.useCallback(async()=>{let s=i.allFields.filter(n=>{let g=o.isFieldVisible(n.id),u=n.validation?.validators&&n.validation.validators.length>0;return g&&u}),F=i.allFields.filter(n=>!o.isFieldVisible(n.id));for(let n of F)r(n.id,[]),t(n.id,"valid");let f=await Promise.all(s.map(n=>d(n.id))),l=f.some(n=>!n.isValid),a=k();if(i.validation?.validators?.length){let n=Object.keys(e.values).reduce((u,c)=>(o.isFieldVisible(c)&&(u[c]=e.values[c]),u),{}),g=core.createValidationContext({formId:i.id,allFormData:n});try{a=await core.runValidatorsAsync(i.validation.validators,n,g);}catch(u){a={isValid:false,errors:[{message:u instanceof Error?u.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!l&&a.isValid,errors:[...f.flatMap(n=>n.errors),...a.errors]}},[i,e.values,o,d,r,t]);return {validateField:d,validateForm:m}}var K=Re.createContext(null);function M({children:i,formConfig:e,defaultValues:o={},onSubmit:t,onFieldChange:r,className:d}){let m=Re.useRef(e.id),{formState:s,setValue:F,setFieldTouched:f,reset:l,setError:a,clearError:n,setFieldValidationState:g,setSubmitting:u,isFormValid:c}=G({defaultValues:o,onFieldChange:r}),{fieldConditions:p,hasConditionalFields:b,getFieldCondition:w,isFieldVisible:R,isFieldDisabled:E,isFieldRequired:x,isFieldReadonly:I}=$({formConfig:e,formValues:s.values}),V=Re.useMemo(()=>({hasConditionalFields:b,getFieldCondition:w,isFieldVisible:R,isFieldDisabled:E,isFieldRequired:x,isFieldReadonly:I}),[b,w,R,E,x,I]),{validateField:S,validateForm:P}=H({formConfig:e,formState:s,conditionsHelpers:V,setFieldValidationState:g,setError:a}),{submit:y}=W({formState:s,onSubmit:t,validateForm:P,setSubmitting:u});Re.useEffect(()=>{(m.current===null||e.id!==m.current)&&(m.current=e.id,l(o));},[e.id,l]);let T=Re.useMemo(()=>e,[e]),q=Re.useMemo(()=>({formState:s,formConfig:T,fieldConditions:p,conditionsHelpers:V,setValue:F,setFieldTouched:f,validateField:S,validateForm:P,isFormValid:c,reset:l,submit:y,setError:a,clearError:n}),[s,T,p,V,F,f,S,P,c,l,y,a,n]);return jsxRuntime.jsx(K.Provider,{value:q,children:jsxRuntime.jsx("form",{onSubmit:y,className:d,noValidate:true,children:i})})}function v(){let i=Re.useContext(K);if(!i)throw new Error("useFormContext must be used within a FormProvider");return i}function he({formConfig:i,defaultValues:e,onSubmit:o,onFieldChange:t,children:r}){let d=Re.useMemo(()=>i instanceof h?i.build():i,[i]);return jsxRuntime.jsx(M,{formConfig:d,defaultValues:e,onSubmit:o,onFieldChange:t,children:r})}function _({fieldId:i,disabled:e=false,customProps:o={},className:t,forceVisible:r=false}){let{formState:d,formConfig:m,setValue:s,setFieldTouched:F,validateField:f,conditionsHelpers:l}=v(),a=m.allFields.find(O=>O.id===i);if(!a)throw new Error(`Field with ID "${i}" not found`);let n=m.config.getComponent(a.componentId);if(!n)throw new Error(`Component with ID "${a.componentId}" not found`);let g=d.values[i],u=d.errors[i]||[],c=d.validationState[i]||"idle",p=d.touched[i]||false,b=c==="validating",w=r||l.isFieldVisible(i),R=e||l.isFieldDisabled(i),E=l.isFieldRequired(i),x=l.isFieldReadonly(i);if(!w)return null;let I=Re.useCallback(async O=>{s(i,O),(a.validation?.validateOnChange||p)&&await f(i,O);},[i,s,f,a.validation?.validateOnChange,p]),V=Re.useCallback(async()=>{p||F(i),a.validation?.validateOnBlur!==false&&await f(i);},[i,p,F,f,a.validation?.validateOnBlur]),S={...n.defaultProps??{},...a.props,...o,disabled:R,required:E,readOnly:x},P={id:i,props:S,value:g,onChange:I,onBlur:V,disabled:R,error:u,isValidating:b,touched:p},y=m.renderConfig?.fieldRenderer,T=n.renderer(P),q=n.useFieldRenderer!==false,re=y&&q?y({children:T,id:i,...S,error:u,isValidating:b,touched:p}):T;return jsxRuntime.jsx("div",{className:t,"data-field-id":i,"data-field-type":n.type,"data-field-visible":w,"data-field-disabled":R,"data-field-required":E,"data-field-readonly":x,children:re})}Re__default.default.memo(_);function Z({row:i,className:e,...o}){let{formConfig:t}=v(),r=i.fields.map(m=>jsxRuntime.jsx(_,{fieldId:m.id},m.id)),d={row:i,children:r,className:e};return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormRow",renderer:t.renderConfig?.rowRenderer,props:d,...o,children:r})}var ee=Z;function xe({className:i,...e}){let{formConfig:o}=v(),t=Re.useMemo(()=>o.rows.map(d=>jsxRuntime.jsx(ee,{row:d},d.id)),[o.rows]),r={formConfig:o,children:t,className:i};return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormBody",renderer:o.renderConfig?.bodyRenderer,props:r,...e,children:t})}function Se({className:i,isSubmitting:e,...o}){let{formState:t,submit:r,formConfig:d}=v(),m={isSubmitting:e??t.isSubmitting,onSubmit:r,className:i};return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormSubmitButton",renderer:d.renderConfig?.submitButtonRenderer,props:m,...o})}exports.Form=he;exports.FormBody=xe;exports.FormBuilder=h;exports.FormField=_;exports.FormProvider=M;exports.FormRow=Z;exports.FormSubmitButton=Se;exports.createForm=ae;exports.form=h;exports.useConditionEvaluation=De;exports.useFormConditions=$;exports.useFormContext=v;exports.useFormState=G;exports.useFormSubmission=W;exports.useFormValidation=H;exports.useMultipleConditionEvaluation=L;Object.keys(core).forEach(function(k){if(k!=='default'&&!Object.prototype.hasOwnProperty.call(exports,k))Object.defineProperty(exports,k,{enumerable:true,get:function(){return core[k]}})});
|
|
1
|
+
'use strict';var Ve=require('react'),core=require('@rilaykit/core'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var Ve__default=/*#__PURE__*/_interopDefault(Ve);var V=class i{constructor(e,r){this.rows=[];this.idGenerator=new core.IdGenerator;this.config=e,this.formId=r||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,r){return new i(e,r)}createFormField(e){let r=this.config.getComponent(e.type);if(!r)throw new Error(`No component found with type "${e.type}"`);let t;return (r.validation||e.validation)&&(t={validateOnChange:e.validation?.validateOnChange??r.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??r.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??r.validation?.debounceMs,validators:[...r.validation?.validators||[],...e.validation?.validators||[]]}),{id:e.id||this.idGenerator.next("field"),componentId:r.id,props:{...r.defaultProps,...e.props},validation:t,conditions:e.conditions}}createRow(e){if(e.length===0)throw new Error("At least one field is required");if(e.length>3)throw new Error("Maximum 3 fields per row");let r=e.map(t=>this.createFormField(t));return {id:this.idGenerator.next("row"),fields:r,maxColumns:e.length}}add(...e){let r,t=false;if(e.length===1&&Array.isArray(e[0])?(r=e[0],t=true):r=e,r.length===0)throw new Error("At least one field is required");if(t&&r.length>3)throw new Error("Maximum 3 fields per row");if(r.length===1){let o=this.createRow(r);return this.rows.push(o),this}if(r.length<=3){let o=this.createRow(r);return this.rows.push(o),this}for(let o of r){let d=this.createRow([o]);this.rows.push(d);}return this}addSeparateRows(e){for(let r of e)this.add(r);return this}setId(e){return this.formId=e,this}updateField(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);return Object.assign(t,{...r,props:{...t.props,...r.props}}),this}findField(e){for(let r of this.rows){let t=r.fields.find(o=>o.id===e);if(t)return t}return null}removeField(e){return this.rows=this.rows.map(r=>({...r,fields:r.fields.filter(t=>t.id!==e)})).filter(r=>r.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.idGenerator.reset(),this}setValidation(e){return this.formValidation=e,this}addValidators(e){return this.formValidation||(this.formValidation={validators:[]}),this.formValidation={...this.formValidation,validators:[...this.formValidation.validators||[],...e]},this}addFieldValidation(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let o={...t.validation,...r,validators:[...t.validation?.validators||[],...r.validators||[]]};return this.updateField(e,{validation:o})}addFieldConditions(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let o={...t.conditions,...r};return this.updateField(e,{conditions:o})}clone(e){let r=new i(this.config,e||`${this.formId}-clone`);return r.rows=core.deepClone(this.rows),r}validate(){let e=[],r=this.getFields(),t=r.map(o=>o.id);try{core.ensureUnique(t,"field");}catch(o){e.push(o instanceof Error?o.message:String(o));}for(let o of r)this.config.hasComponent(o.componentId)||e.push(`Component "${o.componentId}" not found for field "${o.id}"`);for(let o of this.rows)o.fields.length>3&&e.push(`Row "${o.id}" has ${o.fields.length} fields, maximum is 3`),o.fields.length===0&&e.push(`Row "${o.id}" is empty`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig(),validation:this.formValidation}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows),this}getStats(){let e=this.getFields(),r=this.rows.map(t=>t.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:r.length>0?Math.max(...r):0,minFieldsInRow:r.length>0?Math.min(...r):0}}};function Le(i,e={},r={}){return Ve.useMemo(()=>{if(!i)return {visible:r.visible??true,disabled:r.disabled??false,required:r.required??false,readonly:r.readonly??false};let t=o=>{try{return o&&typeof o=="object"&&"build"in o?core.evaluateCondition(o.build(),e):core.evaluateCondition(o,e)}catch(d){return console.warn("Error evaluating condition:",d),false}};return {visible:i.visible?t(i.visible):r.visible??true,disabled:i.disabled?t(i.disabled):r.disabled??false,required:i.required?t(i.required):r.required??false,readonly:i.readonly?t(i.readonly):r.readonly??false}},[i,e,r])}function G(i,e={}){return Ve.useMemo(()=>{let r={};for(let[t,o]of Object.entries(i))if(r[t]={visible:true,disabled:false,required:false,readonly:false},o){let d=l=>{try{return l&&typeof l=="object"&&"build"in l?core.evaluateCondition(l.build(),e):core.evaluateCondition(l,e)}catch(u){return console.warn(`Error evaluating condition for field ${t}:`,u),false}};r[t]={visible:o.visible?d(o.visible):true,disabled:o.disabled?d(o.disabled):false,required:o.required?d(o.required):false,readonly:o.readonly?d(o.readonly):false};}return r},[i,e])}function H({formConfig:i,formValues:e}){let r=Ve.useMemo(()=>{let f={};for(let n of i.allFields)n.conditions&&(f[n.id]=n.conditions);return f},[i.allFields]),t=Ve.useMemo(()=>Object.keys(r).length>0,[r]),o=G(t?r:{},t?e:{}),d=Ve.useCallback(f=>o[f],[o]),l=Ve.useCallback(f=>{let n=o[f];return n?n.visible:true},[o]),u=Ve.useCallback(f=>{let n=o[f];return n?n.disabled:false},[o]),p=Ve.useCallback(f=>{let n=o[f];return n?n.required:false},[o]),g=Ve.useCallback(f=>{let n=o[f];return n?n.readonly:false},[o]);return Ve.useMemo(()=>({fieldConditions:o,hasConditionalFields:t,getFieldCondition:d,isFieldVisible:l,isFieldDisabled:u,isFieldRequired:p,isFieldReadonly:g}),[o,t,d,l,u,p,g])}function ce(i,e){switch(e.type){case "SET_VALUE":return {...i,values:{...i.values,[e.fieldId]:e.value},isDirty:true};case "SET_FIELD_ERRORS":return {...i,errors:{...i.errors,[e.fieldId]:e.errors}};case "SET_FIELD_VALIDATION_STATE":return {...i,validationState:{...i.validationState,[e.fieldId]:e.state}};case "SET_FIELD_TOUCHED":return {...i,touched:{...i.touched,[e.fieldId]:true}};case "SET_SUBMITTING":return {...i,isSubmitting:e.isSubmitting};case "RESET":return {values:e.values||{},errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false};default:return i}}function W({defaultValues:i={},onFieldChange:e}){let r={values:i,errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false},[t,o]=Ve.useReducer(ce,r),d=Ve.useRef(e);d.current=e;let l=Ve.useCallback((s,F)=>{o({type:"SET_VALUE",fieldId:s,value:F}),d.current?.(s,F,{...t.values,[s]:F});},[t.values]),u=Ve.useCallback(s=>{o({type:"SET_FIELD_TOUCHED",fieldId:s});},[]),p=Ve.useCallback((s,F)=>{o({type:"SET_FIELD_ERRORS",fieldId:s,errors:F});},[]),g=Ve.useCallback(s=>{o({type:"SET_FIELD_ERRORS",fieldId:s,errors:[]});},[]),f=Ve.useCallback((s,F)=>{o({type:"SET_FIELD_VALIDATION_STATE",fieldId:s,state:F});},[]),n=Ve.useCallback(s=>{o({type:"SET_SUBMITTING",isSubmitting:s});},[]),m=Ve.useCallback(s=>{o({type:"RESET",values:s});},[]),c=Ve.useCallback(()=>{let s=Object.values(t.errors).some(a=>a.length>0),F=Object.values(t.validationState).some(a=>a==="invalid");return !s&&!F},[t.errors,t.validationState]);return {formState:t,setValue:l,setFieldTouched:u,setError:p,clearError:g,setFieldValidationState:f,setSubmitting:n,reset:m,isFormValid:c}}function J({formState:i,onSubmit:e,validateForm:r,setSubmitting:t}){let o=Ve.useRef(e);return o.current=e,{submit:Ve.useCallback(async l=>{l?.preventDefault();try{return t(!0),(await r()).isValid?(o.current&&await o.current(i.values),!0):!1}catch(u){return console.error("Error during form submission:",u),false}finally{t(false);}},[i.values,r,t])}}function B(){return {isValid:true,errors:[]}}function K({formConfig:i,formState:e,conditionsHelpers:r,setFieldValidationState:t,setError:o}){let d=Ve.useRef(i),l=Ve.useRef(r),u=Ve.useRef(t),p=Ve.useRef(o);d.current=i,l.current=r,u.current=t,p.current=o;let g=Ve.useCallback(async(n,m)=>{let c=d.current.allFields.find(a=>a.id===n);if(!c)return B();if(!l.current.isFieldVisible(n))return p.current(n,[]),u.current(n,"valid"),B();if(!c.validation?.validators?.length)return p.current(n,[]),u.current(n,"valid"),B();let s=m!==void 0?m:e.values[n],F=core.createValidationContext({fieldId:n,formId:d.current.id,allFormData:{...e.values,[n]:s}});u.current(n,"validating");try{let a=await core.runValidatorsAsync(c.validation.validators,s,F),h=l.current.isFieldRequired(n),v=s==null||s==="";if(h&&v&&!a.errors.some(C=>C.code==="REQUIRED"||C.message.toLowerCase().includes("required"))){let C={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...a.errors]};return p.current(n,C.errors),u.current(n,"invalid"),C}return p.current(n,a.errors),u.current(n,a.isValid?"valid":"invalid"),a}catch(a){let h={isValid:false,errors:[{message:a instanceof Error?a.message:"Validation failed",code:"VALIDATION_ERROR"}]};return p.current(n,h.errors),u.current(n,"invalid"),h}},[e.values]),f=Ve.useCallback(async()=>{let n=d.current.allFields.filter(a=>{let h=l.current.isFieldVisible(a.id),v=a.validation?.validators&&a.validation.validators.length>0;return h&&v}),m=d.current.allFields.filter(a=>!l.current.isFieldVisible(a.id));for(let a of m)p.current(a.id,[]),u.current(a.id,"valid");let c=await Promise.all(n.map(a=>g(a.id))),s=c.some(a=>!a.isValid),F=B();if(d.current.validation?.validators?.length){let a=Object.keys(e.values).reduce((v,R)=>(l.current.isFieldVisible(R)&&(v[R]=e.values[R]),v),{}),h=core.createValidationContext({formId:d.current.id,allFormData:a});try{F=await core.runValidatorsAsync(d.current.validation.validators,a,h);}catch(v){F={isValid:false,errors:[{message:v instanceof Error?v.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!s&&F.isValid,errors:[...c.flatMap(a=>a.errors),...F.errors]}},[e.values,g]);return {validateField:g,validateForm:f}}function ve({formConfig:i,enabled:e=true}){let r=core.getGlobalMonitor(),t=Ve.useRef(null),o=Ve.useRef(0),d=Ve.useRef(0);Ve.useEffect(()=>{r&&e&&(t.current=r.getProfiler());},[r,e]);let l=Ve.useCallback(m=>{if(!r||!e)return;o.current++;let c={formId:i.id,fieldCount:i.allFields.length,timestamp:Date.now(),duration:0,renderDuration:0,validationDuration:0,validationErrors:0,renderCount:m||o.current};r.track("component_render",`form_${i.id}`,{formId:i.id,fieldCount:i.allFields.length,renderCount:o.current},c,"low");},[r,e,i.id,i.allFields.length]),u=Ve.useCallback((m,c)=>{if(!r||!e)return;let s=t.current?.getMetrics(`form_validation_${i.id}`),F={formId:i.id,fieldCount:c||i.allFields.length,timestamp:Date.now(),duration:s?.duration||0,renderDuration:0,validationDuration:s?.duration||0,validationErrors:m,renderCount:o.current};r.track("form_validation",`form_${i.id}`,{formId:i.id,validationErrors:m,fieldCount:c||i.allFields.length},F,m>0?"medium":"low");},[r,e,i.id,i.allFields.length]),p=Ve.useCallback((m,c)=>{if(!r||!e)return;let s=t.current?.getMetrics(`form_submission_${i.id}`),F={formId:i.id,fieldCount:c||i.allFields.length,timestamp:Date.now(),duration:s?.duration||0,renderDuration:0,validationDuration:0,validationErrors:m?0:1,renderCount:o.current};r.track("form_submission",`form_${i.id}`,{formId:i.id,success:m,fieldCount:c||i.allFields.length,fieldChanges:d.current},F,m?"low":"high");},[r,e,i.id,i.allFields.length]),g=Ve.useCallback((m,c)=>{!r||!e||(d.current++,r.track("component_update",`field_${m}`,{formId:i.id,fieldId:m,componentType:c,changeCount:d.current},void 0,"low"));},[r,e,i.id]),f=Ve.useCallback(m=>{!t.current||!e||t.current.start(m,{formId:i.id,renderCount:o.current});},[e,i.id]),n=Ve.useCallback(m=>{if(!t.current||!e)return null;let c=t.current.end(m);return c?{...c,formId:i.id,fieldCount:i.allFields.length,renderDuration:c.duration,validationDuration:0,validationErrors:0}:null},[e,i.id,i.allFields.length]);return {trackFormRender:l,trackFormValidation:u,trackFormSubmission:p,trackFieldChange:g,startPerformanceTracking:f,endPerformanceTracking:n}}var Y=Ve.createContext(null);function A({children:i,formConfig:e,defaultValues:r={},onSubmit:t,onFieldChange:o,className:d}){let l=Ve.useRef(e.id),{formState:u,setValue:p,setFieldTouched:g,reset:f,setError:n,clearError:m,setFieldValidationState:c,setSubmitting:s,isFormValid:F}=W({defaultValues:r,onFieldChange:o}),{fieldConditions:a,hasConditionalFields:h,getFieldCondition:v,isFieldVisible:R,isFieldDisabled:C,isFieldRequired:E,isFieldReadonly:T}=H({formConfig:e,formValues:u.values}),y=Ve.useMemo(()=>({hasConditionalFields:h,getFieldCondition:v,isFieldVisible:R,isFieldDisabled:C,isFieldRequired:E,isFieldReadonly:T}),[h,v,R,C,E,T]),{validateField:D,validateForm:_}=K({formConfig:e,formState:u,conditionsHelpers:y,setFieldValidationState:c,setError:n}),{submit:O}=J({formState:u,onSubmit:t,validateForm:_,setSubmitting:s});Ve.useEffect(()=>{(l.current===null||e.id!==l.current)&&(l.current=e.id,console.log("resetting form",r),f(r));},[e.id,f]);let L=Ve.useMemo(()=>e,[e]),se=Ve.useMemo(()=>({formState:u,formConfig:L,fieldConditions:a,conditionsHelpers:y,setValue:p,setFieldTouched:g,validateField:D,validateForm:_,isFormValid:F,reset:f,submit:O,setError:n,clearError:m}),[u,L,a,y,p,g,D,_,F,f,O,n,m]);return jsxRuntime.jsx(Y.Provider,{value:se,children:jsxRuntime.jsx("form",{onSubmit:O,className:d,noValidate:true,children:i})})}function b(){let i=Ve.useContext(Y);if(!i)throw new Error("useFormContext must be used within a FormProvider");return i}function we({formConfig:i,defaultValues:e,onSubmit:r,onFieldChange:t,children:o}){let d=Ve.useMemo(()=>i instanceof V?i.build():i,[i]);return jsxRuntime.jsx(A,{formConfig:d,defaultValues:e,onSubmit:r,onFieldChange:t,children:o})}var $=Ve__default.default.memo(function({fieldId:e,disabled:r=false,customProps:t={},className:o,forceVisible:d=false}){let{formState:l,formConfig:u,setValue:p,setFieldTouched:g,validateField:f,conditionsHelpers:n}=b(),m=u.allFields.find(y=>y.id===e);if(!m)throw new Error(`Field with ID "${e}" not found`);let c=u.config.getComponent(m.componentId);if(!c)throw new Error(`Component with ID "${m.componentId}" not found`);let s=Ve.useMemo(()=>({value:l.values[e],errors:l.errors[e]||[],validationState:l.validationState[e]||"idle",isTouched:l.touched[e]||false}),[l.values[e],l.errors[e],l.validationState[e],l.touched[e]]),F=s.validationState==="validating",a=Ve.useMemo(()=>({isVisible:d||n.isFieldVisible(e),isFieldDisabled:r||n.isFieldDisabled(e),isFieldRequired:n.isFieldRequired(e),isFieldReadonly:n.isFieldReadonly(e)}),[d,n.isFieldVisible(e),r,n.isFieldDisabled(e),n.isFieldRequired(e),n.isFieldReadonly(e)]);if(!a.isVisible)return null;let h=Ve.useCallback(async y=>{p(e,y),(m.validation?.validateOnChange||s.isTouched)&&await f(e,y);},[e,p,f,m.validation?.validateOnChange,s.isTouched]),v=Ve.useCallback(async()=>{s.isTouched||g(e),m.validation?.validateOnBlur!==false&&await f(e);},[e,s.isTouched,g,f,m.validation?.validateOnBlur]),R=Ve.useMemo(()=>({...c.defaultProps??{},...m.props,...t,disabled:a.isFieldDisabled,required:a.isFieldRequired,readOnly:a.isFieldReadonly}),[c.defaultProps,m.props,t,a.isFieldDisabled,a.isFieldRequired,a.isFieldReadonly]),C=Ve.useMemo(()=>({id:e,props:R,value:s.value,onChange:h,onBlur:v,disabled:a.isFieldDisabled,error:s.errors,isValidating:F,touched:s.isTouched}),[e,R,s.value,h,v,a.isFieldDisabled,s.errors,F,s.isTouched]),E=Ve.useMemo(()=>c.renderer(C),[c.renderer,C]),T=Ve.useMemo(()=>{let y=u.renderConfig?.fieldRenderer,D=c.useFieldRenderer!==false;return y&&D?y({children:E,id:e,...R,error:s.errors,isValidating:F,touched:s.isTouched}):E},[u.renderConfig?.fieldRenderer,c.useFieldRenderer,E,e,R,s.errors,F,s.isTouched]);return jsxRuntime.jsx("div",{className:o,"data-field-id":e,"data-field-type":c.type,"data-field-visible":a.isVisible,"data-field-disabled":a.isFieldDisabled,"data-field-required":a.isFieldRequired,"data-field-readonly":a.isFieldReadonly,children:T})});var oe=Ve__default.default.memo(function({row:e,className:r,...t}){let{formConfig:o}=b(),d=Ve.useMemo(()=>e.fields.map(u=>jsxRuntime.jsx($,{fieldId:u.id},u.id)),[e.fields]),l=Ve.useMemo(()=>({row:e,children:d,className:r}),[e,d,r]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormRow",renderer:o.renderConfig?.rowRenderer,props:l,...t,children:d})}),ie=oe;var Me=Ve__default.default.memo(function({className:e,...r}){let{formConfig:t}=b(),o=Ve.useMemo(()=>t.rows.map(l=>jsxRuntime.jsx(ie,{row:l},l.id)),[t.rows]),d=Ve.useMemo(()=>({formConfig:t,children:o,className:e}),[t,o,e]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormBody",renderer:t.renderConfig?.bodyRenderer,props:d,...r,children:o})});var Oe=Ve__default.default.memo(function({className:e,isSubmitting:r,...t}){let{formState:o,submit:d,formConfig:l}=b(),u=Ve.useMemo(()=>({isSubmitting:r??o.isSubmitting,onSubmit:d,className:e}),[r,o.isSubmitting,d,e]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormSubmitButton",renderer:l.renderConfig?.submitButtonRenderer,props:u,...t})});exports.Form=we;exports.FormBody=Me;exports.FormBuilder=V;exports.FormField=$;exports.FormProvider=A;exports.FormRow=oe;exports.FormSubmitButton=Oe;exports.form=V;exports.useConditionEvaluation=Le;exports.useFormConditions=H;exports.useFormContext=b;exports.useFormMonitoring=ve;exports.useFormState=W;exports.useFormSubmission=J;exports.useFormValidation=K;exports.useMultipleConditionEvaluation=G;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import Re,{createContext,useCallback,useContext,useMemo,useReducer,useRef,useEffect}from'react';import {ril,IdGenerator,deepClone,ensureUnique,createValidationContext,runValidatorsAsync,ComponentRendererWrapper,evaluateCondition}from'@rilaykit/core';export*from'@rilaykit/core';import {jsx}from'react/jsx-runtime';var h=class i{constructor(e,o){this.rows=[];this.idGenerator=new IdGenerator;this.config=e,this.formId=o||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,o){return new i(e,o)}createFormField(e){let o=this.config.getComponent(e.type);if(!o)throw new Error(`No component found with type "${e.type}"`);let t;return (o.validation||e.validation)&&(t={validateOnChange:e.validation?.validateOnChange??o.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??o.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??o.validation?.debounceMs,validators:[...o.validation?.validators||[],...e.validation?.validators||[]]}),{id:e.id||this.idGenerator.next("field"),componentId:o.id,props:{...o.defaultProps,...e.props},validation:t,conditions:e.conditions}}createRow(e){if(e.length===0)throw new Error("At least one field is required");if(e.length>3)throw new Error("Maximum 3 fields per row");let o=e.map(t=>this.createFormField(t));return {id:this.idGenerator.next("row"),fields:o,maxColumns:e.length}}add(...e){let o,t=false;if(e.length===1&&Array.isArray(e[0])?(o=e[0],t=true):o=e,o.length===0)throw new Error("At least one field is required");if(t&&o.length>3)throw new Error("Maximum 3 fields per row");if(o.length===1){let r=this.createRow(o);return this.rows.push(r),this}if(o.length<=3){let r=this.createRow(o);return this.rows.push(r),this}for(let r of o){let d=this.createRow([r]);this.rows.push(d);}return this}addSeparateRows(e){for(let o of e)this.add(o);return this}setId(e){return this.formId=e,this}updateField(e,o){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);return Object.assign(t,{...o,props:{...t.props,...o.props}}),this}findField(e){for(let o of this.rows){let t=o.fields.find(r=>r.id===e);if(t)return t}return null}removeField(e){return this.rows=this.rows.map(o=>({...o,fields:o.fields.filter(t=>t.id!==e)})).filter(o=>o.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.idGenerator.reset(),this}setValidation(e){return this.formValidation=e,this}addValidators(e){return this.formValidation||(this.formValidation={validators:[]}),this.formValidation={...this.formValidation,validators:[...this.formValidation.validators||[],...e]},this}addFieldValidation(e,o){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let r={...t.validation,...o,validators:[...t.validation?.validators||[],...o.validators||[]]};return this.updateField(e,{validation:r})}addFieldConditions(e,o){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let r={...t.conditions,...o};return this.updateField(e,{conditions:r})}clone(e){let o=new i(this.config,e||`${this.formId}-clone`);return o.rows=deepClone(this.rows),o}validate(){let e=[],o=this.getFields(),t=o.map(r=>r.id);try{ensureUnique(t,"field");}catch(r){e.push(r instanceof Error?r.message:String(r));}for(let r of o)this.config.hasComponent(r.componentId)||e.push(`Component "${r.componentId}" not found for field "${r.id}"`);for(let r of this.rows)r.fields.length>3&&e.push(`Row "${r.id}" has ${r.fields.length} fields, maximum is 3`),r.fields.length===0&&e.push(`Row "${r.id}" is empty`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig(),validation:this.formValidation}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows),this}getStats(){let e=this.getFields(),o=this.rows.map(t=>t.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:o.length>0?Math.max(...o):0,minFieldsInRow:o.length>0?Math.min(...o):0}}};function ae(i,e){return h.create(i,e)}ril.prototype.form=function(i){return h.create(this,i)};function De(i,e={},o={}){return useMemo(()=>{if(!i)return {visible:o.visible??true,disabled:o.disabled??false,required:o.required??false,readonly:o.readonly??false};let t=r=>{try{return r&&typeof r=="object"&&"build"in r?evaluateCondition(r.build(),e):evaluateCondition(r,e)}catch(d){return console.warn("Error evaluating condition:",d),false}};return {visible:i.visible?t(i.visible):o.visible??true,disabled:i.disabled?t(i.disabled):o.disabled??false,required:i.required?t(i.required):o.required??false,readonly:i.readonly?t(i.readonly):o.readonly??false}},[i,e,o])}function L(i,e={}){return useMemo(()=>{let o={};for(let[t,r]of Object.entries(i))if(o[t]={visible:true,disabled:false,required:false,readonly:false},r){let d=m=>{try{return m&&typeof m=="object"&&"build"in m?evaluateCondition(m.build(),e):evaluateCondition(m,e)}catch(s){return console.warn(`Error evaluating condition for field ${t}:`,s),false}};o[t]={visible:r.visible?d(r.visible):true,disabled:r.disabled?d(r.disabled):false,required:r.required?d(r.required):false,readonly:r.readonly?d(r.readonly):false};}return o},[i,e])}function $({formConfig:i,formValues:e}){let o=useMemo(()=>{let l={};for(let a of i.allFields)a.conditions&&(l[a.id]=a.conditions);return l},[i.allFields]),t=useMemo(()=>Object.keys(o).length>0,[o]),r=L(t?o:{},t?e:{}),d=useCallback(l=>r[l],[r]),m=useCallback(l=>{let a=r[l];return a?a.visible:true},[r]),s=useCallback(l=>{let a=r[l];return a?a.disabled:false},[r]),F=useCallback(l=>{let a=r[l];return a?a.required:false},[r]),f=useCallback(l=>{let a=r[l];return a?a.readonly:false},[r]);return useMemo(()=>({fieldConditions:r,hasConditionalFields:t,getFieldCondition:d,isFieldVisible:m,isFieldDisabled:s,isFieldRequired:F,isFieldReadonly:f}),[r,t,d,m,s,F,f])}function ue(i,e){switch(e.type){case "SET_VALUE":return {...i,values:{...i.values,[e.fieldId]:e.value},isDirty:true};case "SET_FIELD_ERRORS":return {...i,errors:{...i.errors,[e.fieldId]:e.errors}};case "SET_FIELD_VALIDATION_STATE":return {...i,validationState:{...i.validationState,[e.fieldId]:e.state}};case "SET_FIELD_TOUCHED":return {...i,touched:{...i.touched,[e.fieldId]:true}};case "SET_SUBMITTING":return {...i,isSubmitting:e.isSubmitting};case "RESET":return {values:e.values||{},errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false};default:return i}}function G({defaultValues:i={},onFieldChange:e}){let o={values:i,errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false},[t,r]=useReducer(ue,o),d=useRef(e);d.current=e;let m=useCallback((u,c)=>{r({type:"SET_VALUE",fieldId:u,value:c}),d.current?.(u,c,{...t.values,[u]:c});},[t.values]),s=useCallback(u=>{r({type:"SET_FIELD_TOUCHED",fieldId:u});},[]),F=useCallback((u,c)=>{r({type:"SET_FIELD_ERRORS",fieldId:u,errors:c});},[]),f=useCallback(u=>{r({type:"SET_FIELD_ERRORS",fieldId:u,errors:[]});},[]),l=useCallback((u,c)=>{r({type:"SET_FIELD_VALIDATION_STATE",fieldId:u,state:c});},[]),a=useCallback(u=>{r({type:"SET_SUBMITTING",isSubmitting:u});},[]),n=useCallback(u=>{r({type:"RESET",values:u});},[]),g=useCallback(()=>{let u=Object.values(t.errors).some(p=>p.length>0),c=Object.values(t.validationState).some(p=>p==="invalid");return !u&&!c},[t.errors,t.validationState]);return {formState:t,setValue:m,setFieldTouched:s,setError:F,clearError:f,setFieldValidationState:l,setSubmitting:a,reset:n,isFormValid:g}}function W({formState:i,onSubmit:e,validateForm:o,setSubmitting:t}){let r=useRef(e);return r.current=e,{submit:useCallback(async m=>{m?.preventDefault();try{return t(!0),(await o()).isValid?(r.current&&await r.current(i.values),!0):!1}catch(s){return console.error("Error during form submission:",s),false}finally{t(false);}},[i.values,o,t])}}function k(){return {isValid:true,errors:[]}}function H({formConfig:i,formState:e,conditionsHelpers:o,setFieldValidationState:t,setError:r}){let d=useCallback(async(s,F)=>{let f=i.allFields.find(n=>n.id===s);if(!f)return k();if(!o.isFieldVisible(s))return r(s,[]),t(s,"valid"),k();if(!f.validation?.validators?.length)return r(s,[]),t(s,"valid"),k();let l=F!==void 0?F:e.values[s],a=createValidationContext({fieldId:s,formId:i.id,allFormData:{...e.values,[s]:l}});t(s,"validating");try{let n=await runValidatorsAsync(f.validation.validators,l,a),g=o.isFieldRequired(s),u=l==null||l==="";if(g&&u&&!n.errors.some(p=>p.code==="REQUIRED"||p.message.toLowerCase().includes("required"))){let p={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...n.errors]};return r(s,p.errors),t(s,"invalid"),p}return r(s,n.errors),t(s,n.isValid?"valid":"invalid"),n}catch(n){let g={isValid:false,errors:[{message:n instanceof Error?n.message:"Validation failed",code:"VALIDATION_ERROR"}]};return r(s,g.errors),t(s,"invalid"),g}},[i,e.values,o,t,r]),m=useCallback(async()=>{let s=i.allFields.filter(n=>{let g=o.isFieldVisible(n.id),u=n.validation?.validators&&n.validation.validators.length>0;return g&&u}),F=i.allFields.filter(n=>!o.isFieldVisible(n.id));for(let n of F)r(n.id,[]),t(n.id,"valid");let f=await Promise.all(s.map(n=>d(n.id))),l=f.some(n=>!n.isValid),a=k();if(i.validation?.validators?.length){let n=Object.keys(e.values).reduce((u,c)=>(o.isFieldVisible(c)&&(u[c]=e.values[c]),u),{}),g=createValidationContext({formId:i.id,allFormData:n});try{a=await runValidatorsAsync(i.validation.validators,n,g);}catch(u){a={isValid:false,errors:[{message:u instanceof Error?u.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!l&&a.isValid,errors:[...f.flatMap(n=>n.errors),...a.errors]}},[i,e.values,o,d,r,t]);return {validateField:d,validateForm:m}}var K=createContext(null);function M({children:i,formConfig:e,defaultValues:o={},onSubmit:t,onFieldChange:r,className:d}){let m=useRef(e.id),{formState:s,setValue:F,setFieldTouched:f,reset:l,setError:a,clearError:n,setFieldValidationState:g,setSubmitting:u,isFormValid:c}=G({defaultValues:o,onFieldChange:r}),{fieldConditions:p,hasConditionalFields:b,getFieldCondition:w,isFieldVisible:R,isFieldDisabled:E,isFieldRequired:x,isFieldReadonly:I}=$({formConfig:e,formValues:s.values}),V=useMemo(()=>({hasConditionalFields:b,getFieldCondition:w,isFieldVisible:R,isFieldDisabled:E,isFieldRequired:x,isFieldReadonly:I}),[b,w,R,E,x,I]),{validateField:S,validateForm:P}=H({formConfig:e,formState:s,conditionsHelpers:V,setFieldValidationState:g,setError:a}),{submit:y}=W({formState:s,onSubmit:t,validateForm:P,setSubmitting:u});useEffect(()=>{(m.current===null||e.id!==m.current)&&(m.current=e.id,l(o));},[e.id,l]);let T=useMemo(()=>e,[e]),q=useMemo(()=>({formState:s,formConfig:T,fieldConditions:p,conditionsHelpers:V,setValue:F,setFieldTouched:f,validateField:S,validateForm:P,isFormValid:c,reset:l,submit:y,setError:a,clearError:n}),[s,T,p,V,F,f,S,P,c,l,y,a,n]);return jsx(K.Provider,{value:q,children:jsx("form",{onSubmit:y,className:d,noValidate:true,children:i})})}function v(){let i=useContext(K);if(!i)throw new Error("useFormContext must be used within a FormProvider");return i}function he({formConfig:i,defaultValues:e,onSubmit:o,onFieldChange:t,children:r}){let d=useMemo(()=>i instanceof h?i.build():i,[i]);return jsx(M,{formConfig:d,defaultValues:e,onSubmit:o,onFieldChange:t,children:r})}function _({fieldId:i,disabled:e=false,customProps:o={},className:t,forceVisible:r=false}){let{formState:d,formConfig:m,setValue:s,setFieldTouched:F,validateField:f,conditionsHelpers:l}=v(),a=m.allFields.find(O=>O.id===i);if(!a)throw new Error(`Field with ID "${i}" not found`);let n=m.config.getComponent(a.componentId);if(!n)throw new Error(`Component with ID "${a.componentId}" not found`);let g=d.values[i],u=d.errors[i]||[],c=d.validationState[i]||"idle",p=d.touched[i]||false,b=c==="validating",w=r||l.isFieldVisible(i),R=e||l.isFieldDisabled(i),E=l.isFieldRequired(i),x=l.isFieldReadonly(i);if(!w)return null;let I=useCallback(async O=>{s(i,O),(a.validation?.validateOnChange||p)&&await f(i,O);},[i,s,f,a.validation?.validateOnChange,p]),V=useCallback(async()=>{p||F(i),a.validation?.validateOnBlur!==false&&await f(i);},[i,p,F,f,a.validation?.validateOnBlur]),S={...n.defaultProps??{},...a.props,...o,disabled:R,required:E,readOnly:x},P={id:i,props:S,value:g,onChange:I,onBlur:V,disabled:R,error:u,isValidating:b,touched:p},y=m.renderConfig?.fieldRenderer,T=n.renderer(P),q=n.useFieldRenderer!==false,re=y&&q?y({children:T,id:i,...S,error:u,isValidating:b,touched:p}):T;return jsx("div",{className:t,"data-field-id":i,"data-field-type":n.type,"data-field-visible":w,"data-field-disabled":R,"data-field-required":E,"data-field-readonly":x,children:re})}Re.memo(_);function Z({row:i,className:e,...o}){let{formConfig:t}=v(),r=i.fields.map(m=>jsx(_,{fieldId:m.id},m.id)),d={row:i,children:r,className:e};return jsx(ComponentRendererWrapper,{name:"FormRow",renderer:t.renderConfig?.rowRenderer,props:d,...o,children:r})}var ee=Z;function xe({className:i,...e}){let{formConfig:o}=v(),t=useMemo(()=>o.rows.map(d=>jsx(ee,{row:d},d.id)),[o.rows]),r={formConfig:o,children:t,className:i};return jsx(ComponentRendererWrapper,{name:"FormBody",renderer:o.renderConfig?.bodyRenderer,props:r,...e,children:t})}function Se({className:i,isSubmitting:e,...o}){let{formState:t,submit:r,formConfig:d}=v(),m={isSubmitting:e??t.isSubmitting,onSubmit:r,className:i};return jsx(ComponentRendererWrapper,{name:"FormSubmitButton",renderer:d.renderConfig?.submitButtonRenderer,props:m,...o})}export{he as Form,xe as FormBody,h as FormBuilder,_ as FormField,M as FormProvider,Z as FormRow,Se as FormSubmitButton,ae as createForm,h as form,De as useConditionEvaluation,$ as useFormConditions,v as useFormContext,G as useFormState,W as useFormSubmission,H as useFormValidation,L as useMultipleConditionEvaluation};
|
|
1
|
+
import Ve,{createContext,useMemo,useCallback,useContext,useReducer,useRef,useEffect}from'react';import {ComponentRendererWrapper,IdGenerator,deepClone,ensureUnique,createValidationContext,runValidatorsAsync,getGlobalMonitor,evaluateCondition}from'@rilaykit/core';import {jsx}from'react/jsx-runtime';var V=class i{constructor(e,r){this.rows=[];this.idGenerator=new IdGenerator;this.config=e,this.formId=r||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,r){return new i(e,r)}createFormField(e){let r=this.config.getComponent(e.type);if(!r)throw new Error(`No component found with type "${e.type}"`);let t;return (r.validation||e.validation)&&(t={validateOnChange:e.validation?.validateOnChange??r.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??r.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??r.validation?.debounceMs,validators:[...r.validation?.validators||[],...e.validation?.validators||[]]}),{id:e.id||this.idGenerator.next("field"),componentId:r.id,props:{...r.defaultProps,...e.props},validation:t,conditions:e.conditions}}createRow(e){if(e.length===0)throw new Error("At least one field is required");if(e.length>3)throw new Error("Maximum 3 fields per row");let r=e.map(t=>this.createFormField(t));return {id:this.idGenerator.next("row"),fields:r,maxColumns:e.length}}add(...e){let r,t=false;if(e.length===1&&Array.isArray(e[0])?(r=e[0],t=true):r=e,r.length===0)throw new Error("At least one field is required");if(t&&r.length>3)throw new Error("Maximum 3 fields per row");if(r.length===1){let o=this.createRow(r);return this.rows.push(o),this}if(r.length<=3){let o=this.createRow(r);return this.rows.push(o),this}for(let o of r){let d=this.createRow([o]);this.rows.push(d);}return this}addSeparateRows(e){for(let r of e)this.add(r);return this}setId(e){return this.formId=e,this}updateField(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);return Object.assign(t,{...r,props:{...t.props,...r.props}}),this}findField(e){for(let r of this.rows){let t=r.fields.find(o=>o.id===e);if(t)return t}return null}removeField(e){return this.rows=this.rows.map(r=>({...r,fields:r.fields.filter(t=>t.id!==e)})).filter(r=>r.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.idGenerator.reset(),this}setValidation(e){return this.formValidation=e,this}addValidators(e){return this.formValidation||(this.formValidation={validators:[]}),this.formValidation={...this.formValidation,validators:[...this.formValidation.validators||[],...e]},this}addFieldValidation(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let o={...t.validation,...r,validators:[...t.validation?.validators||[],...r.validators||[]]};return this.updateField(e,{validation:o})}addFieldConditions(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let o={...t.conditions,...r};return this.updateField(e,{conditions:o})}clone(e){let r=new i(this.config,e||`${this.formId}-clone`);return r.rows=deepClone(this.rows),r}validate(){let e=[],r=this.getFields(),t=r.map(o=>o.id);try{ensureUnique(t,"field");}catch(o){e.push(o instanceof Error?o.message:String(o));}for(let o of r)this.config.hasComponent(o.componentId)||e.push(`Component "${o.componentId}" not found for field "${o.id}"`);for(let o of this.rows)o.fields.length>3&&e.push(`Row "${o.id}" has ${o.fields.length} fields, maximum is 3`),o.fields.length===0&&e.push(`Row "${o.id}" is empty`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig(),validation:this.formValidation}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows),this}getStats(){let e=this.getFields(),r=this.rows.map(t=>t.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:r.length>0?Math.max(...r):0,minFieldsInRow:r.length>0?Math.min(...r):0}}};function Le(i,e={},r={}){return useMemo(()=>{if(!i)return {visible:r.visible??true,disabled:r.disabled??false,required:r.required??false,readonly:r.readonly??false};let t=o=>{try{return o&&typeof o=="object"&&"build"in o?evaluateCondition(o.build(),e):evaluateCondition(o,e)}catch(d){return console.warn("Error evaluating condition:",d),false}};return {visible:i.visible?t(i.visible):r.visible??true,disabled:i.disabled?t(i.disabled):r.disabled??false,required:i.required?t(i.required):r.required??false,readonly:i.readonly?t(i.readonly):r.readonly??false}},[i,e,r])}function G(i,e={}){return useMemo(()=>{let r={};for(let[t,o]of Object.entries(i))if(r[t]={visible:true,disabled:false,required:false,readonly:false},o){let d=l=>{try{return l&&typeof l=="object"&&"build"in l?evaluateCondition(l.build(),e):evaluateCondition(l,e)}catch(u){return console.warn(`Error evaluating condition for field ${t}:`,u),false}};r[t]={visible:o.visible?d(o.visible):true,disabled:o.disabled?d(o.disabled):false,required:o.required?d(o.required):false,readonly:o.readonly?d(o.readonly):false};}return r},[i,e])}function H({formConfig:i,formValues:e}){let r=useMemo(()=>{let f={};for(let n of i.allFields)n.conditions&&(f[n.id]=n.conditions);return f},[i.allFields]),t=useMemo(()=>Object.keys(r).length>0,[r]),o=G(t?r:{},t?e:{}),d=useCallback(f=>o[f],[o]),l=useCallback(f=>{let n=o[f];return n?n.visible:true},[o]),u=useCallback(f=>{let n=o[f];return n?n.disabled:false},[o]),p=useCallback(f=>{let n=o[f];return n?n.required:false},[o]),g=useCallback(f=>{let n=o[f];return n?n.readonly:false},[o]);return useMemo(()=>({fieldConditions:o,hasConditionalFields:t,getFieldCondition:d,isFieldVisible:l,isFieldDisabled:u,isFieldRequired:p,isFieldReadonly:g}),[o,t,d,l,u,p,g])}function ce(i,e){switch(e.type){case "SET_VALUE":return {...i,values:{...i.values,[e.fieldId]:e.value},isDirty:true};case "SET_FIELD_ERRORS":return {...i,errors:{...i.errors,[e.fieldId]:e.errors}};case "SET_FIELD_VALIDATION_STATE":return {...i,validationState:{...i.validationState,[e.fieldId]:e.state}};case "SET_FIELD_TOUCHED":return {...i,touched:{...i.touched,[e.fieldId]:true}};case "SET_SUBMITTING":return {...i,isSubmitting:e.isSubmitting};case "RESET":return {values:e.values||{},errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false};default:return i}}function W({defaultValues:i={},onFieldChange:e}){let r={values:i,errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false},[t,o]=useReducer(ce,r),d=useRef(e);d.current=e;let l=useCallback((s,F)=>{o({type:"SET_VALUE",fieldId:s,value:F}),d.current?.(s,F,{...t.values,[s]:F});},[t.values]),u=useCallback(s=>{o({type:"SET_FIELD_TOUCHED",fieldId:s});},[]),p=useCallback((s,F)=>{o({type:"SET_FIELD_ERRORS",fieldId:s,errors:F});},[]),g=useCallback(s=>{o({type:"SET_FIELD_ERRORS",fieldId:s,errors:[]});},[]),f=useCallback((s,F)=>{o({type:"SET_FIELD_VALIDATION_STATE",fieldId:s,state:F});},[]),n=useCallback(s=>{o({type:"SET_SUBMITTING",isSubmitting:s});},[]),m=useCallback(s=>{o({type:"RESET",values:s});},[]),c=useCallback(()=>{let s=Object.values(t.errors).some(a=>a.length>0),F=Object.values(t.validationState).some(a=>a==="invalid");return !s&&!F},[t.errors,t.validationState]);return {formState:t,setValue:l,setFieldTouched:u,setError:p,clearError:g,setFieldValidationState:f,setSubmitting:n,reset:m,isFormValid:c}}function J({formState:i,onSubmit:e,validateForm:r,setSubmitting:t}){let o=useRef(e);return o.current=e,{submit:useCallback(async l=>{l?.preventDefault();try{return t(!0),(await r()).isValid?(o.current&&await o.current(i.values),!0):!1}catch(u){return console.error("Error during form submission:",u),false}finally{t(false);}},[i.values,r,t])}}function B(){return {isValid:true,errors:[]}}function K({formConfig:i,formState:e,conditionsHelpers:r,setFieldValidationState:t,setError:o}){let d=useRef(i),l=useRef(r),u=useRef(t),p=useRef(o);d.current=i,l.current=r,u.current=t,p.current=o;let g=useCallback(async(n,m)=>{let c=d.current.allFields.find(a=>a.id===n);if(!c)return B();if(!l.current.isFieldVisible(n))return p.current(n,[]),u.current(n,"valid"),B();if(!c.validation?.validators?.length)return p.current(n,[]),u.current(n,"valid"),B();let s=m!==void 0?m:e.values[n],F=createValidationContext({fieldId:n,formId:d.current.id,allFormData:{...e.values,[n]:s}});u.current(n,"validating");try{let a=await runValidatorsAsync(c.validation.validators,s,F),h=l.current.isFieldRequired(n),v=s==null||s==="";if(h&&v&&!a.errors.some(C=>C.code==="REQUIRED"||C.message.toLowerCase().includes("required"))){let C={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...a.errors]};return p.current(n,C.errors),u.current(n,"invalid"),C}return p.current(n,a.errors),u.current(n,a.isValid?"valid":"invalid"),a}catch(a){let h={isValid:false,errors:[{message:a instanceof Error?a.message:"Validation failed",code:"VALIDATION_ERROR"}]};return p.current(n,h.errors),u.current(n,"invalid"),h}},[e.values]),f=useCallback(async()=>{let n=d.current.allFields.filter(a=>{let h=l.current.isFieldVisible(a.id),v=a.validation?.validators&&a.validation.validators.length>0;return h&&v}),m=d.current.allFields.filter(a=>!l.current.isFieldVisible(a.id));for(let a of m)p.current(a.id,[]),u.current(a.id,"valid");let c=await Promise.all(n.map(a=>g(a.id))),s=c.some(a=>!a.isValid),F=B();if(d.current.validation?.validators?.length){let a=Object.keys(e.values).reduce((v,R)=>(l.current.isFieldVisible(R)&&(v[R]=e.values[R]),v),{}),h=createValidationContext({formId:d.current.id,allFormData:a});try{F=await runValidatorsAsync(d.current.validation.validators,a,h);}catch(v){F={isValid:false,errors:[{message:v instanceof Error?v.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!s&&F.isValid,errors:[...c.flatMap(a=>a.errors),...F.errors]}},[e.values,g]);return {validateField:g,validateForm:f}}function ve({formConfig:i,enabled:e=true}){let r=getGlobalMonitor(),t=useRef(null),o=useRef(0),d=useRef(0);useEffect(()=>{r&&e&&(t.current=r.getProfiler());},[r,e]);let l=useCallback(m=>{if(!r||!e)return;o.current++;let c={formId:i.id,fieldCount:i.allFields.length,timestamp:Date.now(),duration:0,renderDuration:0,validationDuration:0,validationErrors:0,renderCount:m||o.current};r.track("component_render",`form_${i.id}`,{formId:i.id,fieldCount:i.allFields.length,renderCount:o.current},c,"low");},[r,e,i.id,i.allFields.length]),u=useCallback((m,c)=>{if(!r||!e)return;let s=t.current?.getMetrics(`form_validation_${i.id}`),F={formId:i.id,fieldCount:c||i.allFields.length,timestamp:Date.now(),duration:s?.duration||0,renderDuration:0,validationDuration:s?.duration||0,validationErrors:m,renderCount:o.current};r.track("form_validation",`form_${i.id}`,{formId:i.id,validationErrors:m,fieldCount:c||i.allFields.length},F,m>0?"medium":"low");},[r,e,i.id,i.allFields.length]),p=useCallback((m,c)=>{if(!r||!e)return;let s=t.current?.getMetrics(`form_submission_${i.id}`),F={formId:i.id,fieldCount:c||i.allFields.length,timestamp:Date.now(),duration:s?.duration||0,renderDuration:0,validationDuration:0,validationErrors:m?0:1,renderCount:o.current};r.track("form_submission",`form_${i.id}`,{formId:i.id,success:m,fieldCount:c||i.allFields.length,fieldChanges:d.current},F,m?"low":"high");},[r,e,i.id,i.allFields.length]),g=useCallback((m,c)=>{!r||!e||(d.current++,r.track("component_update",`field_${m}`,{formId:i.id,fieldId:m,componentType:c,changeCount:d.current},void 0,"low"));},[r,e,i.id]),f=useCallback(m=>{!t.current||!e||t.current.start(m,{formId:i.id,renderCount:o.current});},[e,i.id]),n=useCallback(m=>{if(!t.current||!e)return null;let c=t.current.end(m);return c?{...c,formId:i.id,fieldCount:i.allFields.length,renderDuration:c.duration,validationDuration:0,validationErrors:0}:null},[e,i.id,i.allFields.length]);return {trackFormRender:l,trackFormValidation:u,trackFormSubmission:p,trackFieldChange:g,startPerformanceTracking:f,endPerformanceTracking:n}}var Y=createContext(null);function A({children:i,formConfig:e,defaultValues:r={},onSubmit:t,onFieldChange:o,className:d}){let l=useRef(e.id),{formState:u,setValue:p,setFieldTouched:g,reset:f,setError:n,clearError:m,setFieldValidationState:c,setSubmitting:s,isFormValid:F}=W({defaultValues:r,onFieldChange:o}),{fieldConditions:a,hasConditionalFields:h,getFieldCondition:v,isFieldVisible:R,isFieldDisabled:C,isFieldRequired:E,isFieldReadonly:T}=H({formConfig:e,formValues:u.values}),y=useMemo(()=>({hasConditionalFields:h,getFieldCondition:v,isFieldVisible:R,isFieldDisabled:C,isFieldRequired:E,isFieldReadonly:T}),[h,v,R,C,E,T]),{validateField:D,validateForm:_}=K({formConfig:e,formState:u,conditionsHelpers:y,setFieldValidationState:c,setError:n}),{submit:O}=J({formState:u,onSubmit:t,validateForm:_,setSubmitting:s});useEffect(()=>{(l.current===null||e.id!==l.current)&&(l.current=e.id,console.log("resetting form",r),f(r));},[e.id,f]);let L=useMemo(()=>e,[e]),se=useMemo(()=>({formState:u,formConfig:L,fieldConditions:a,conditionsHelpers:y,setValue:p,setFieldTouched:g,validateField:D,validateForm:_,isFormValid:F,reset:f,submit:O,setError:n,clearError:m}),[u,L,a,y,p,g,D,_,F,f,O,n,m]);return jsx(Y.Provider,{value:se,children:jsx("form",{onSubmit:O,className:d,noValidate:true,children:i})})}function b(){let i=useContext(Y);if(!i)throw new Error("useFormContext must be used within a FormProvider");return i}function we({formConfig:i,defaultValues:e,onSubmit:r,onFieldChange:t,children:o}){let d=useMemo(()=>i instanceof V?i.build():i,[i]);return jsx(A,{formConfig:d,defaultValues:e,onSubmit:r,onFieldChange:t,children:o})}var $=Ve.memo(function({fieldId:e,disabled:r=false,customProps:t={},className:o,forceVisible:d=false}){let{formState:l,formConfig:u,setValue:p,setFieldTouched:g,validateField:f,conditionsHelpers:n}=b(),m=u.allFields.find(y=>y.id===e);if(!m)throw new Error(`Field with ID "${e}" not found`);let c=u.config.getComponent(m.componentId);if(!c)throw new Error(`Component with ID "${m.componentId}" not found`);let s=useMemo(()=>({value:l.values[e],errors:l.errors[e]||[],validationState:l.validationState[e]||"idle",isTouched:l.touched[e]||false}),[l.values[e],l.errors[e],l.validationState[e],l.touched[e]]),F=s.validationState==="validating",a=useMemo(()=>({isVisible:d||n.isFieldVisible(e),isFieldDisabled:r||n.isFieldDisabled(e),isFieldRequired:n.isFieldRequired(e),isFieldReadonly:n.isFieldReadonly(e)}),[d,n.isFieldVisible(e),r,n.isFieldDisabled(e),n.isFieldRequired(e),n.isFieldReadonly(e)]);if(!a.isVisible)return null;let h=useCallback(async y=>{p(e,y),(m.validation?.validateOnChange||s.isTouched)&&await f(e,y);},[e,p,f,m.validation?.validateOnChange,s.isTouched]),v=useCallback(async()=>{s.isTouched||g(e),m.validation?.validateOnBlur!==false&&await f(e);},[e,s.isTouched,g,f,m.validation?.validateOnBlur]),R=useMemo(()=>({...c.defaultProps??{},...m.props,...t,disabled:a.isFieldDisabled,required:a.isFieldRequired,readOnly:a.isFieldReadonly}),[c.defaultProps,m.props,t,a.isFieldDisabled,a.isFieldRequired,a.isFieldReadonly]),C=useMemo(()=>({id:e,props:R,value:s.value,onChange:h,onBlur:v,disabled:a.isFieldDisabled,error:s.errors,isValidating:F,touched:s.isTouched}),[e,R,s.value,h,v,a.isFieldDisabled,s.errors,F,s.isTouched]),E=useMemo(()=>c.renderer(C),[c.renderer,C]),T=useMemo(()=>{let y=u.renderConfig?.fieldRenderer,D=c.useFieldRenderer!==false;return y&&D?y({children:E,id:e,...R,error:s.errors,isValidating:F,touched:s.isTouched}):E},[u.renderConfig?.fieldRenderer,c.useFieldRenderer,E,e,R,s.errors,F,s.isTouched]);return jsx("div",{className:o,"data-field-id":e,"data-field-type":c.type,"data-field-visible":a.isVisible,"data-field-disabled":a.isFieldDisabled,"data-field-required":a.isFieldRequired,"data-field-readonly":a.isFieldReadonly,children:T})});var oe=Ve.memo(function({row:e,className:r,...t}){let{formConfig:o}=b(),d=useMemo(()=>e.fields.map(u=>jsx($,{fieldId:u.id},u.id)),[e.fields]),l=useMemo(()=>({row:e,children:d,className:r}),[e,d,r]);return jsx(ComponentRendererWrapper,{name:"FormRow",renderer:o.renderConfig?.rowRenderer,props:l,...t,children:d})}),ie=oe;var Me=Ve.memo(function({className:e,...r}){let{formConfig:t}=b(),o=useMemo(()=>t.rows.map(l=>jsx(ie,{row:l},l.id)),[t.rows]),d=useMemo(()=>({formConfig:t,children:o,className:e}),[t,o,e]);return jsx(ComponentRendererWrapper,{name:"FormBody",renderer:t.renderConfig?.bodyRenderer,props:d,...r,children:o})});var Oe=Ve.memo(function({className:e,isSubmitting:r,...t}){let{formState:o,submit:d,formConfig:l}=b(),u=useMemo(()=>({isSubmitting:r??o.isSubmitting,onSubmit:d,className:e}),[r,o.isSubmitting,d,e]);return jsx(ComponentRendererWrapper,{name:"FormSubmitButton",renderer:l.renderConfig?.submitButtonRenderer,props:u,...t})});export{we as Form,Me as FormBody,V as FormBuilder,$ as FormField,A as FormProvider,oe as FormRow,Oe as FormSubmitButton,V as form,Le as useConditionEvaluation,H as useFormConditions,b as useFormContext,ve as useFormMonitoring,W as useFormState,J as useFormSubmission,K as useFormValidation,G as useMultipleConditionEvaluation};
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rilaykit/forms",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.1",
|
|
4
4
|
"description": "Form building utilities and components for RilayKit",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
7
15
|
"files": [
|
|
8
16
|
"dist"
|
|
9
17
|
],
|
|
@@ -24,7 +32,7 @@
|
|
|
24
32
|
"url": "https://github.com/andyoucreate/rilay/issues"
|
|
25
33
|
},
|
|
26
34
|
"dependencies": {
|
|
27
|
-
"@rilaykit/core": "
|
|
35
|
+
"@rilaykit/core": "9.0.1"
|
|
28
36
|
},
|
|
29
37
|
"peerDependencies": {
|
|
30
38
|
"react": ">=18.0.0",
|
|
@@ -34,11 +42,11 @@
|
|
|
34
42
|
"@testing-library/jest-dom": "^6.6.3",
|
|
35
43
|
"@testing-library/react": "^16.3.0",
|
|
36
44
|
"@testing-library/user-event": "^14.6.1",
|
|
37
|
-
"@types/react": "^18.
|
|
38
|
-
"@types/react-dom": "^18.
|
|
45
|
+
"@types/react": "^18.3.23",
|
|
46
|
+
"@types/react-dom": "^18.3.0",
|
|
39
47
|
"react": "^18.3.1",
|
|
40
48
|
"react-dom": "^18.3.1",
|
|
41
|
-
"typescript": "^5.3
|
|
49
|
+
"typescript": "^5.8.3",
|
|
42
50
|
"vitest": "^3.2.4"
|
|
43
51
|
},
|
|
44
52
|
"publishConfig": {
|