@rilaykit/forms 1.3.0 → 2.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 CHANGED
@@ -1,84 +1,24 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { FormConfiguration, ValidationError, ValidationResult, FormFieldRow, ril, ValidationConfig, ConditionalConfig, FormFieldConfig } from '@rilaykit/core';
2
+ import { ril, ValidationConfig, ConditionalConfig, FormFieldConfig, FormFieldRow, FormConfiguration, RendererChildrenFunction, FormBodyRendererProps, ValidationError, ValidationResult, FormRowRendererProps, FormSubmitButtonRendererProps } from '@rilaykit/core';
3
3
  export * from '@rilaykit/core';
4
4
  export { createZodValidator, ril } from '@rilaykit/core';
5
5
  import * as React$1 from 'react';
6
6
  import React__default from 'react';
7
7
 
8
- interface FormProps {
9
- formConfig: FormConfiguration;
10
- defaultValues?: Record<string, any>;
11
- onSubmit?: (data: Record<string, any>) => void | Promise<void>;
12
- onFieldChange?: (fieldId: string, value: any, formData: Record<string, any>) => void;
13
- className?: string;
14
- children: React.ReactNode;
15
- }
16
- declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, children }: FormProps): react_jsx_runtime.JSX.Element;
17
-
18
- interface FormBodyProps {
19
- className?: string;
20
- }
21
- declare function FormBody({ className }: FormBodyProps): React$1.ReactElement<any, string | React$1.JSXElementConstructor<any>>;
22
-
23
- interface FormFieldProps {
24
- fieldId: string;
25
- disabled?: boolean;
26
- customProps?: Record<string, any>;
27
- className?: string;
28
- }
29
- declare function FormField({ fieldId, disabled, customProps, className, }: FormFieldProps): react_jsx_runtime.JSX.Element | null;
30
-
31
- interface FormState {
32
- values: Record<string, any>;
33
- errors: Record<string, ValidationError[]>;
34
- warnings: Record<string, ValidationError[]>;
35
- touched: Set<string>;
36
- isValidating: Set<string>;
37
- isDirty: boolean;
38
- isValid: boolean;
39
- isSubmitting: boolean;
40
- }
41
- interface FormContextValue {
42
- formState: FormState;
43
- formConfig: FormConfiguration;
44
- setValue: (fieldId: string, value: any) => void;
45
- setError: (fieldId: string, errors: ValidationError[]) => void;
46
- setWarning: (fieldId: string, warnings: ValidationError[]) => void;
47
- clearError: (fieldId: string) => void;
48
- clearWarning: (fieldId: string) => void;
49
- markFieldTouched: (fieldId: string) => void;
50
- setFieldValidating: (fieldId: string, isValidating: boolean) => void;
51
- validateField: (fieldId: string, value?: any) => Promise<ValidationResult>;
52
- validateAllFields: () => Promise<boolean>;
53
- reset: (values?: Record<string, any>) => void;
54
- submit: (event?: React__default.FormEvent) => Promise<boolean>;
55
- }
56
- interface FormProviderProps {
57
- children: React__default.ReactNode;
58
- formConfig: FormConfiguration;
59
- defaultValues?: Record<string, any>;
60
- onSubmit?: (data: Record<string, any>) => void | Promise<void>;
61
- onFieldChange?: (fieldId: string, value: any, formData: Record<string, any>) => void;
62
- className?: string;
8
+ interface FieldConfig {
9
+ id: string;
10
+ type: string;
11
+ props?: Record<string, any>;
12
+ validation?: ValidationConfig;
13
+ conditional?: ConditionalConfig;
63
14
  }
64
- declare function FormProvider({ children, formConfig, defaultValues, onSubmit, onFieldChange, className, }: FormProviderProps): react_jsx_runtime.JSX.Element;
65
- declare function useFormContext(): FormContextValue;
66
-
67
- interface FormRowProps {
68
- row: FormFieldRow;
69
- className?: string;
15
+ interface RowOptions {
16
+ spacing?: 'tight' | 'normal' | 'loose';
17
+ alignment?: 'start' | 'center' | 'end' | 'stretch';
70
18
  }
71
- declare function FormRow({ row, className }: FormRowProps): React$1.ReactElement<any, string | React$1.JSXElementConstructor<any>>;
72
-
73
- interface FormSubmitButtonProps {
74
- className?: string;
75
- children?: React__default.ReactNode;
76
- }
77
- declare function FormSubmitButton({ className, children }: FormSubmitButtonProps): React__default.ReactElement<any, string | React__default.JSXElementConstructor<any>>;
78
-
79
19
  /**
80
20
  * Form builder class for creating form configurations
81
- * Simplified API with matrix support
21
+ * Simplified API with matrix support and auto-build capability
82
22
  */
83
23
  declare class form {
84
24
  private config;
@@ -88,115 +28,79 @@ declare class form {
88
28
  constructor(config: ril, formId?: string);
89
29
  static create(config: ril, formId?: string): form;
90
30
  /**
91
- * Add a single field (takes full width)
92
- * @param fieldId - Unique field identifier
93
- * @param componentType - Component type (e.g., 'text', 'email')
94
- * @param props - Props to pass to the component
95
- * @param options - Additional options
96
- * @returns form instance for chaining
31
+ * Helper method to create a FormFieldConfig from a FieldConfig
32
+ */
33
+ private createFormField;
34
+ /**
35
+ * Helper method to create a row with validation
97
36
  */
98
- addField(fieldId: string, componentType: string, props?: Record<string, any>, options?: {
99
- validation?: ValidationConfig;
100
- conditional?: ConditionalConfig;
101
- }): this;
37
+ private createRow;
38
+ /**
39
+ * Add a single field using simplified FieldConfig object
40
+ */
41
+ addField(fieldConfig: FieldConfig): this;
102
42
  /**
103
43
  * Add multiple fields on the same row (max 3 fields)
104
- * @param fieldConfigs - Array of field configurations for the row
105
- * @param rowOptions - Row configuration options
106
- * @returns form instance for chaining
107
- */
108
- addRowFields(fieldConfigs: Array<{
109
- fieldId: string;
110
- componentType: string;
111
- props?: Record<string, any>;
112
- validation?: ValidationConfig;
113
- conditional?: ConditionalConfig;
114
- }>, rowOptions?: {
115
- spacing?: 'tight' | 'normal' | 'loose';
116
- alignment?: 'start' | 'center' | 'end' | 'stretch';
117
- }): this;
44
+ */
45
+ addRowFields(fieldConfigs: FieldConfig[], rowOptions?: RowOptions): this;
118
46
  /**
119
47
  * Add multiple fields, each on its own row
120
- * @param fieldConfigs - Array of field configurations
121
- * @returns form instance for chaining
122
48
  */
123
- addFields(fieldConfigs: Array<{
124
- fieldId: string;
125
- componentType: string;
126
- props?: Record<string, any>;
127
- validation?: ValidationConfig;
128
- conditional?: ConditionalConfig;
129
- }>): this;
49
+ addFields(fieldConfigs: FieldConfig[]): this;
130
50
  /**
131
51
  * Set form ID
132
- * @param id - Form identifier
133
- * @returns form instance for chaining
134
52
  */
135
53
  setId(id: string): this;
136
54
  /**
137
55
  * Update field configuration
138
- * @param fieldId - Field identifier
139
- * @param updates - Updates to apply
140
- * @returns form instance for chaining
141
56
  */
142
57
  updateField(fieldId: string, updates: Partial<Omit<FormFieldConfig, 'id'>>): this;
58
+ /**
59
+ * Helper method to find a field by ID
60
+ */
61
+ private findField;
143
62
  /**
144
63
  * Remove a field from the form
145
- * @param fieldId - Field identifier
146
- * @returns form instance for chaining
147
64
  */
148
65
  removeField(fieldId: string): this;
149
66
  /**
150
67
  * Get field configuration by ID
151
- * @param fieldId - Field identifier
152
- * @returns Field configuration or undefined
153
68
  */
154
69
  getField(fieldId: string): FormFieldConfig | undefined;
155
70
  /**
156
71
  * Get all fields as a flat array
157
- * @returns Array of field configurations
158
72
  */
159
73
  getFields(): FormFieldConfig[];
160
74
  /**
161
75
  * Get all rows
162
- * @returns Array of row configurations
163
76
  */
164
77
  getRows(): FormFieldRow[];
165
78
  /**
166
79
  * Clear all fields and rows
167
- * @returns form instance for chaining
168
80
  */
169
81
  clear(): this;
170
82
  /**
171
83
  * Clone the current form builder
172
- * @param newFormId - ID for the cloned form
173
- * @returns New form instance
174
84
  */
175
85
  clone(newFormId?: string): form;
176
86
  /**
177
87
  * Validate the form configuration
178
- * @returns Array of validation errors
179
88
  */
180
89
  validate(): string[];
181
90
  /**
182
91
  * Build the final form configuration with matrix support
183
- * @returns Complete form configuration with matrix structure
184
92
  */
185
93
  build(): FormConfiguration;
186
94
  /**
187
95
  * Export form configuration as JSON
188
- * @returns JSON representation of the form
189
96
  */
190
97
  toJSON(): any;
191
98
  /**
192
99
  * Import form configuration from JSON
193
- * @param json - JSON representation of the form
194
- * @returns form instance for chaining
195
100
  */
196
101
  fromJSON(json: any): this;
197
102
  /**
198
103
  * Get form statistics
199
- * @returns Object with form statistics
200
104
  */
201
105
  getStats(): {
202
106
  totalFields: number;
@@ -206,5 +110,87 @@ declare class form {
206
110
  minFieldsInRow: number;
207
111
  };
208
112
  }
113
+ /**
114
+ * Factory function to create a form builder directly
115
+ */
116
+ declare function createForm(config: ril, formId?: string): form;
117
+ declare module '@rilaykit/core' {
118
+ interface ril {
119
+ createForm(formId?: string): form;
120
+ }
121
+ }
122
+
123
+ interface FormProps {
124
+ formConfig: FormConfiguration | form;
125
+ defaultValues?: Record<string, any>;
126
+ onSubmit?: (data: Record<string, any>) => void | Promise<void>;
127
+ onFieldChange?: (fieldId: string, value: any, formData: Record<string, any>) => void;
128
+ className?: string;
129
+ children: React.ReactNode;
130
+ }
131
+ declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, children }: FormProps): react_jsx_runtime.JSX.Element;
132
+
133
+ interface FormBodyProps {
134
+ className?: string;
135
+ children?: React.ReactNode | RendererChildrenFunction<FormBodyRendererProps>;
136
+ renderAs?: 'default' | 'children' | boolean;
137
+ }
138
+ declare function FormBody({ className, children, renderAs }: FormBodyProps): React$1.ReactNode;
139
+
140
+ interface FormFieldProps {
141
+ fieldId: string;
142
+ disabled?: boolean;
143
+ customProps?: Record<string, any>;
144
+ className?: string;
145
+ }
146
+ declare function FormField({ fieldId, disabled, customProps, className, }: FormFieldProps): react_jsx_runtime.JSX.Element | null;
147
+
148
+ interface FormState {
149
+ values: Record<string, any>;
150
+ errors: Record<string, ValidationError[]>;
151
+ touched: Set<string>;
152
+ isValidating: Set<string>;
153
+ isDirty: boolean;
154
+ isValid: boolean;
155
+ isSubmitting: boolean;
156
+ }
157
+ interface FormContextValue {
158
+ formState: FormState;
159
+ formConfig: FormConfiguration;
160
+ setValue: (fieldId: string, value: any) => void;
161
+ setError: (fieldId: string, errors: ValidationError[]) => void;
162
+ clearError: (fieldId: string) => void;
163
+ markFieldTouched: (fieldId: string) => void;
164
+ setFieldValidating: (fieldId: string, isValidating: boolean) => void;
165
+ validateField: (fieldId: string, value?: any) => Promise<ValidationResult>;
166
+ validateAllFields: () => Promise<boolean>;
167
+ reset: (values?: Record<string, any>) => void;
168
+ submit: (event?: React__default.FormEvent) => Promise<boolean>;
169
+ }
170
+ interface FormProviderProps {
171
+ children: React__default.ReactNode;
172
+ formConfig: FormConfiguration;
173
+ defaultValues?: Record<string, any>;
174
+ onSubmit?: (data: Record<string, any>) => void | Promise<void>;
175
+ onFieldChange?: (fieldId: string, value: any, formData: Record<string, any>) => void;
176
+ className?: string;
177
+ }
178
+ declare function FormProvider({ children, formConfig, defaultValues, onSubmit, onFieldChange, className, }: FormProviderProps): react_jsx_runtime.JSX.Element;
179
+ declare function useFormContext(): FormContextValue;
180
+
181
+ interface FormRowProps {
182
+ row: FormFieldRow;
183
+ className?: string;
184
+ children?: React.ReactNode | RendererChildrenFunction<FormRowRendererProps>;
185
+ renderAs?: 'default' | 'children' | boolean;
186
+ }
187
+ declare function FormRow({ row, className, children, renderAs }: FormRowProps): React$1.ReactNode;
188
+
189
+ interface FormSubmitButtonProps {
190
+ className?: string;
191
+ children?: React__default.ReactNode | RendererChildrenFunction<FormSubmitButtonRendererProps>;
192
+ renderAs?: 'default' | 'children' | boolean;
193
+ }
194
+ declare function FormSubmitButton({ className, children, renderAs }: FormSubmitButtonProps): React__default.ReactNode;
209
195
 
210
- export { Form, FormBody, type FormBodyProps, form as FormBuilder, type FormContextValue, FormField, type FormFieldProps, type FormProps, FormProvider, type FormProviderProps, FormRow, type FormRowProps, type FormState, FormSubmitButton, type FormSubmitButtonProps, form, useFormContext };
196
+ export { type FieldConfig, Form, FormBody, type FormBodyProps, form as FormBuilder, type FormContextValue, FormField, type FormFieldProps, type FormProps, FormProvider, type FormProviderProps, FormRow, type FormRowProps, type FormState, FormSubmitButton, type FormSubmitButtonProps, createForm, form, useFormContext };
package/dist/index.d.ts CHANGED
@@ -1,84 +1,24 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { FormConfiguration, ValidationError, ValidationResult, FormFieldRow, ril, ValidationConfig, ConditionalConfig, FormFieldConfig } from '@rilaykit/core';
2
+ import { ril, ValidationConfig, ConditionalConfig, FormFieldConfig, FormFieldRow, FormConfiguration, RendererChildrenFunction, FormBodyRendererProps, ValidationError, ValidationResult, FormRowRendererProps, FormSubmitButtonRendererProps } from '@rilaykit/core';
3
3
  export * from '@rilaykit/core';
4
4
  export { createZodValidator, ril } from '@rilaykit/core';
5
5
  import * as React$1 from 'react';
6
6
  import React__default from 'react';
7
7
 
8
- interface FormProps {
9
- formConfig: FormConfiguration;
10
- defaultValues?: Record<string, any>;
11
- onSubmit?: (data: Record<string, any>) => void | Promise<void>;
12
- onFieldChange?: (fieldId: string, value: any, formData: Record<string, any>) => void;
13
- className?: string;
14
- children: React.ReactNode;
15
- }
16
- declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, children }: FormProps): react_jsx_runtime.JSX.Element;
17
-
18
- interface FormBodyProps {
19
- className?: string;
20
- }
21
- declare function FormBody({ className }: FormBodyProps): React$1.ReactElement<any, string | React$1.JSXElementConstructor<any>>;
22
-
23
- interface FormFieldProps {
24
- fieldId: string;
25
- disabled?: boolean;
26
- customProps?: Record<string, any>;
27
- className?: string;
28
- }
29
- declare function FormField({ fieldId, disabled, customProps, className, }: FormFieldProps): react_jsx_runtime.JSX.Element | null;
30
-
31
- interface FormState {
32
- values: Record<string, any>;
33
- errors: Record<string, ValidationError[]>;
34
- warnings: Record<string, ValidationError[]>;
35
- touched: Set<string>;
36
- isValidating: Set<string>;
37
- isDirty: boolean;
38
- isValid: boolean;
39
- isSubmitting: boolean;
40
- }
41
- interface FormContextValue {
42
- formState: FormState;
43
- formConfig: FormConfiguration;
44
- setValue: (fieldId: string, value: any) => void;
45
- setError: (fieldId: string, errors: ValidationError[]) => void;
46
- setWarning: (fieldId: string, warnings: ValidationError[]) => void;
47
- clearError: (fieldId: string) => void;
48
- clearWarning: (fieldId: string) => void;
49
- markFieldTouched: (fieldId: string) => void;
50
- setFieldValidating: (fieldId: string, isValidating: boolean) => void;
51
- validateField: (fieldId: string, value?: any) => Promise<ValidationResult>;
52
- validateAllFields: () => Promise<boolean>;
53
- reset: (values?: Record<string, any>) => void;
54
- submit: (event?: React__default.FormEvent) => Promise<boolean>;
55
- }
56
- interface FormProviderProps {
57
- children: React__default.ReactNode;
58
- formConfig: FormConfiguration;
59
- defaultValues?: Record<string, any>;
60
- onSubmit?: (data: Record<string, any>) => void | Promise<void>;
61
- onFieldChange?: (fieldId: string, value: any, formData: Record<string, any>) => void;
62
- className?: string;
8
+ interface FieldConfig {
9
+ id: string;
10
+ type: string;
11
+ props?: Record<string, any>;
12
+ validation?: ValidationConfig;
13
+ conditional?: ConditionalConfig;
63
14
  }
64
- declare function FormProvider({ children, formConfig, defaultValues, onSubmit, onFieldChange, className, }: FormProviderProps): react_jsx_runtime.JSX.Element;
65
- declare function useFormContext(): FormContextValue;
66
-
67
- interface FormRowProps {
68
- row: FormFieldRow;
69
- className?: string;
15
+ interface RowOptions {
16
+ spacing?: 'tight' | 'normal' | 'loose';
17
+ alignment?: 'start' | 'center' | 'end' | 'stretch';
70
18
  }
71
- declare function FormRow({ row, className }: FormRowProps): React$1.ReactElement<any, string | React$1.JSXElementConstructor<any>>;
72
-
73
- interface FormSubmitButtonProps {
74
- className?: string;
75
- children?: React__default.ReactNode;
76
- }
77
- declare function FormSubmitButton({ className, children }: FormSubmitButtonProps): React__default.ReactElement<any, string | React__default.JSXElementConstructor<any>>;
78
-
79
19
  /**
80
20
  * Form builder class for creating form configurations
81
- * Simplified API with matrix support
21
+ * Simplified API with matrix support and auto-build capability
82
22
  */
83
23
  declare class form {
84
24
  private config;
@@ -88,115 +28,79 @@ declare class form {
88
28
  constructor(config: ril, formId?: string);
89
29
  static create(config: ril, formId?: string): form;
90
30
  /**
91
- * Add a single field (takes full width)
92
- * @param fieldId - Unique field identifier
93
- * @param componentType - Component type (e.g., 'text', 'email')
94
- * @param props - Props to pass to the component
95
- * @param options - Additional options
96
- * @returns form instance for chaining
31
+ * Helper method to create a FormFieldConfig from a FieldConfig
32
+ */
33
+ private createFormField;
34
+ /**
35
+ * Helper method to create a row with validation
97
36
  */
98
- addField(fieldId: string, componentType: string, props?: Record<string, any>, options?: {
99
- validation?: ValidationConfig;
100
- conditional?: ConditionalConfig;
101
- }): this;
37
+ private createRow;
38
+ /**
39
+ * Add a single field using simplified FieldConfig object
40
+ */
41
+ addField(fieldConfig: FieldConfig): this;
102
42
  /**
103
43
  * Add multiple fields on the same row (max 3 fields)
104
- * @param fieldConfigs - Array of field configurations for the row
105
- * @param rowOptions - Row configuration options
106
- * @returns form instance for chaining
107
- */
108
- addRowFields(fieldConfigs: Array<{
109
- fieldId: string;
110
- componentType: string;
111
- props?: Record<string, any>;
112
- validation?: ValidationConfig;
113
- conditional?: ConditionalConfig;
114
- }>, rowOptions?: {
115
- spacing?: 'tight' | 'normal' | 'loose';
116
- alignment?: 'start' | 'center' | 'end' | 'stretch';
117
- }): this;
44
+ */
45
+ addRowFields(fieldConfigs: FieldConfig[], rowOptions?: RowOptions): this;
118
46
  /**
119
47
  * Add multiple fields, each on its own row
120
- * @param fieldConfigs - Array of field configurations
121
- * @returns form instance for chaining
122
48
  */
123
- addFields(fieldConfigs: Array<{
124
- fieldId: string;
125
- componentType: string;
126
- props?: Record<string, any>;
127
- validation?: ValidationConfig;
128
- conditional?: ConditionalConfig;
129
- }>): this;
49
+ addFields(fieldConfigs: FieldConfig[]): this;
130
50
  /**
131
51
  * Set form ID
132
- * @param id - Form identifier
133
- * @returns form instance for chaining
134
52
  */
135
53
  setId(id: string): this;
136
54
  /**
137
55
  * Update field configuration
138
- * @param fieldId - Field identifier
139
- * @param updates - Updates to apply
140
- * @returns form instance for chaining
141
56
  */
142
57
  updateField(fieldId: string, updates: Partial<Omit<FormFieldConfig, 'id'>>): this;
58
+ /**
59
+ * Helper method to find a field by ID
60
+ */
61
+ private findField;
143
62
  /**
144
63
  * Remove a field from the form
145
- * @param fieldId - Field identifier
146
- * @returns form instance for chaining
147
64
  */
148
65
  removeField(fieldId: string): this;
149
66
  /**
150
67
  * Get field configuration by ID
151
- * @param fieldId - Field identifier
152
- * @returns Field configuration or undefined
153
68
  */
154
69
  getField(fieldId: string): FormFieldConfig | undefined;
155
70
  /**
156
71
  * Get all fields as a flat array
157
- * @returns Array of field configurations
158
72
  */
159
73
  getFields(): FormFieldConfig[];
160
74
  /**
161
75
  * Get all rows
162
- * @returns Array of row configurations
163
76
  */
164
77
  getRows(): FormFieldRow[];
165
78
  /**
166
79
  * Clear all fields and rows
167
- * @returns form instance for chaining
168
80
  */
169
81
  clear(): this;
170
82
  /**
171
83
  * Clone the current form builder
172
- * @param newFormId - ID for the cloned form
173
- * @returns New form instance
174
84
  */
175
85
  clone(newFormId?: string): form;
176
86
  /**
177
87
  * Validate the form configuration
178
- * @returns Array of validation errors
179
88
  */
180
89
  validate(): string[];
181
90
  /**
182
91
  * Build the final form configuration with matrix support
183
- * @returns Complete form configuration with matrix structure
184
92
  */
185
93
  build(): FormConfiguration;
186
94
  /**
187
95
  * Export form configuration as JSON
188
- * @returns JSON representation of the form
189
96
  */
190
97
  toJSON(): any;
191
98
  /**
192
99
  * Import form configuration from JSON
193
- * @param json - JSON representation of the form
194
- * @returns form instance for chaining
195
100
  */
196
101
  fromJSON(json: any): this;
197
102
  /**
198
103
  * Get form statistics
199
- * @returns Object with form statistics
200
104
  */
201
105
  getStats(): {
202
106
  totalFields: number;
@@ -206,5 +110,87 @@ declare class form {
206
110
  minFieldsInRow: number;
207
111
  };
208
112
  }
113
+ /**
114
+ * Factory function to create a form builder directly
115
+ */
116
+ declare function createForm(config: ril, formId?: string): form;
117
+ declare module '@rilaykit/core' {
118
+ interface ril {
119
+ createForm(formId?: string): form;
120
+ }
121
+ }
122
+
123
+ interface FormProps {
124
+ formConfig: FormConfiguration | form;
125
+ defaultValues?: Record<string, any>;
126
+ onSubmit?: (data: Record<string, any>) => void | Promise<void>;
127
+ onFieldChange?: (fieldId: string, value: any, formData: Record<string, any>) => void;
128
+ className?: string;
129
+ children: React.ReactNode;
130
+ }
131
+ declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, children }: FormProps): react_jsx_runtime.JSX.Element;
132
+
133
+ interface FormBodyProps {
134
+ className?: string;
135
+ children?: React.ReactNode | RendererChildrenFunction<FormBodyRendererProps>;
136
+ renderAs?: 'default' | 'children' | boolean;
137
+ }
138
+ declare function FormBody({ className, children, renderAs }: FormBodyProps): React$1.ReactNode;
139
+
140
+ interface FormFieldProps {
141
+ fieldId: string;
142
+ disabled?: boolean;
143
+ customProps?: Record<string, any>;
144
+ className?: string;
145
+ }
146
+ declare function FormField({ fieldId, disabled, customProps, className, }: FormFieldProps): react_jsx_runtime.JSX.Element | null;
147
+
148
+ interface FormState {
149
+ values: Record<string, any>;
150
+ errors: Record<string, ValidationError[]>;
151
+ touched: Set<string>;
152
+ isValidating: Set<string>;
153
+ isDirty: boolean;
154
+ isValid: boolean;
155
+ isSubmitting: boolean;
156
+ }
157
+ interface FormContextValue {
158
+ formState: FormState;
159
+ formConfig: FormConfiguration;
160
+ setValue: (fieldId: string, value: any) => void;
161
+ setError: (fieldId: string, errors: ValidationError[]) => void;
162
+ clearError: (fieldId: string) => void;
163
+ markFieldTouched: (fieldId: string) => void;
164
+ setFieldValidating: (fieldId: string, isValidating: boolean) => void;
165
+ validateField: (fieldId: string, value?: any) => Promise<ValidationResult>;
166
+ validateAllFields: () => Promise<boolean>;
167
+ reset: (values?: Record<string, any>) => void;
168
+ submit: (event?: React__default.FormEvent) => Promise<boolean>;
169
+ }
170
+ interface FormProviderProps {
171
+ children: React__default.ReactNode;
172
+ formConfig: FormConfiguration;
173
+ defaultValues?: Record<string, any>;
174
+ onSubmit?: (data: Record<string, any>) => void | Promise<void>;
175
+ onFieldChange?: (fieldId: string, value: any, formData: Record<string, any>) => void;
176
+ className?: string;
177
+ }
178
+ declare function FormProvider({ children, formConfig, defaultValues, onSubmit, onFieldChange, className, }: FormProviderProps): react_jsx_runtime.JSX.Element;
179
+ declare function useFormContext(): FormContextValue;
180
+
181
+ interface FormRowProps {
182
+ row: FormFieldRow;
183
+ className?: string;
184
+ children?: React.ReactNode | RendererChildrenFunction<FormRowRendererProps>;
185
+ renderAs?: 'default' | 'children' | boolean;
186
+ }
187
+ declare function FormRow({ row, className, children, renderAs }: FormRowProps): React$1.ReactNode;
188
+
189
+ interface FormSubmitButtonProps {
190
+ className?: string;
191
+ children?: React__default.ReactNode | RendererChildrenFunction<FormSubmitButtonRendererProps>;
192
+ renderAs?: 'default' | 'children' | boolean;
193
+ }
194
+ declare function FormSubmitButton({ className, children, renderAs }: FormSubmitButtonProps): React__default.ReactNode;
209
195
 
210
- export { Form, FormBody, type FormBodyProps, form as FormBuilder, type FormContextValue, FormField, type FormFieldProps, type FormProps, FormProvider, type FormProviderProps, FormRow, type FormRowProps, type FormState, FormSubmitButton, type FormSubmitButtonProps, form, useFormContext };
196
+ export { type FieldConfig, Form, FormBody, type FormBodyProps, form as FormBuilder, type FormContextValue, FormField, type FormFieldProps, type FormProps, FormProvider, type FormProviderProps, FormRow, type FormRowProps, type FormState, FormSubmitButton, type FormSubmitButtonProps, createForm, form, useFormContext };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- 'use strict';var er=require('react'),jsxRuntime=require('react/jsx-runtime'),core=require('@rilaykit/core');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var er__default=/*#__PURE__*/_interopDefault(er);function j(i,r){switch(r.type){case "SET_VALUE":{let o={...i.values,[r.fieldId]:r.value};return {...i,values:o,isDirty:true}}case "SET_ERROR":return {...i,errors:{...i.errors,[r.fieldId]:r.errors},isValid:false};case "SET_WARNING":return {...i,warnings:{...i.warnings,[r.fieldId]:r.warnings}};case "CLEAR_ERROR":{let o={...i.errors};return delete o[r.fieldId],{...i,errors:o}}case "CLEAR_WARNING":{let o={...i.warnings};return delete o[r.fieldId],{...i,warnings:o}}case "MARK_TOUCHED":return {...i,touched:new Set([...i.touched,r.fieldId])};case "SET_VALIDATING":{let o=new Set(i.isValidating);return r.isValidating?o.add(r.fieldId):o.delete(r.fieldId),{...i,isValidating:o}}case "SET_SUBMITTING":return {...i,isSubmitting:r.isSubmitting};case "RESET":return {values:r.values||{},errors:{},warnings:{},touched:new Set,isValidating:new Set,isDirty:false,isValid:true,isSubmitting:false};case "UPDATE_VALIDATION_STATE":{let o=Object.keys(i.errors).some(d=>i.errors[d].length>0);return {...i,isValid:!o}}default:return i}}var U=er.createContext(null);function D({children:i,formConfig:r,defaultValues:o={},onSubmit:d,onFieldChange:e,className:s}){let f={values:o,errors:{},warnings:{},touched:new Set,isValidating:new Set,isDirty:false,isValid:true,isSubmitting:false},[a,m]=er.useReducer(j,f),t=er.useRef(new Map),F=er.useRef(d),l=er.useRef(e);F.current=d,l.current=e;let y=er.useCallback((n,c)=>{m({type:"SET_ERROR",fieldId:n,errors:c}),m({type:"UPDATE_VALIDATION_STATE"});},[]),E=er.useCallback((n,c)=>{m({type:"SET_WARNING",fieldId:n,warnings:c});},[]),v=er.useCallback(n=>{m({type:"CLEAR_ERROR",fieldId:n}),m({type:"UPDATE_VALIDATION_STATE"});},[]),h=er.useCallback(n=>{m({type:"CLEAR_WARNING",fieldId:n});},[]),P=er.useCallback(n=>{m({type:"MARK_TOUCHED",fieldId:n});},[]),S=er.useCallback((n,c)=>{m({type:"SET_VALIDATING",fieldId:n,isValidating:c});},[]),T=er.useCallback((n,c)=>{if(m({type:"SET_VALUE",fieldId:n,value:c}),a.errors[n]&&a.errors[n].length>0&&(m({type:"CLEAR_ERROR",fieldId:n}),m({type:"UPDATE_VALIDATION_STATE"})),l.current){let u={...a.values,[n]:c};l.current(n,c,u);}},[a.errors,a.values]),R=er.useMemo(()=>r,[r]),b=er.useCallback(async(n,c)=>{let u=R.allFields.find(A=>A.id===n);if(!u?.validation?.validator)return {isValid:true,errors:[]};let z=c!==void 0?c:a.values[n],B=t.current.get(n);B&&clearTimeout(B);let Z={fieldId:n,formData:a.values,fieldProps:u.props,touched:a.touched.has(n),dirty:a.isDirty},O=u.validation.debounceMs||0;return new Promise(A=>{let L=async()=>{S(n,true);try{let g=await u.validation.validator(z,Z,u.props);g.errors.length>0?y(n,g.errors):v(n),g.warnings&&g.warnings.length>0?E(n,g.warnings):h(n),A(g);}catch(g){let M={isValid:false,errors:[{code:"validation_error",message:g instanceof Error?g.message:"Validation error"}]};y(n,M.errors),A(M);}finally{S(n,false);}};if(O>0){let g=setTimeout(L,O);t.current.set(n,g);}else L();})},[R,a.values,a.touched,a.isDirty,y,E,v,h,S]),I=er.useCallback(async()=>{let n=R.allFields.map(u=>b(u.id));return (await Promise.all(n)).every(u=>u.isValid)},[R,b]),w=er.useCallback(n=>{m({type:"RESET",values:n});},[]),x=er.useCallback(async n=>{if(n?.preventDefault(),!F.current)return true;m({type:"SET_SUBMITTING",isSubmitting:true});try{return await I()?(await F.current(a.values),!0):!1}catch(c){return console.error("Error during form submission:",c),false}finally{m({type:"SET_SUBMITTING",isSubmitting:false});}},[a.values,I]),K=er.useMemo(()=>({formState:a,formConfig:R,setValue:T,setError:y,setWarning:E,clearError:v,clearWarning:h,markFieldTouched:P,setFieldValidating:S,validateField:b,validateAllFields:I,reset:w,submit:x}),[a,R,T,y,E,v,h,P,S,b,I,w,x]);return jsxRuntime.jsx(U.Provider,{value:K,children:jsxRuntime.jsx("form",{onSubmit:x,className:s,noValidate:true,children:i})})}function C(){let i=er.useContext(U);if(!i)throw new Error("useFormContext must be used within a FormProvider");return i}function rr({formConfig:i,defaultValues:r,onSubmit:o,onFieldChange:d,children:e}){return jsxRuntime.jsx(D,{formConfig:i,defaultValues:r,onSubmit:o,onFieldChange:d,className:"streamline-form",children:e})}function W({fieldId:i,disabled:r=false,customProps:o={},className:d}){let{formState:e,formConfig:s,setValue:f,markFieldTouched:a,validateField:m}=C(),t=er.useMemo(()=>s.allFields.find(w=>w.id===i),[s.allFields,i]);if(!t)throw new Error(`Field with ID "${i}" not found`);let F=er.useMemo(()=>s.config.getComponent(t.componentId),[s.config,t.componentId]);if(!F)throw new Error(`Component with ID "${t.componentId}" not found`);let l=er.useMemo(()=>({value:e.values[t.id],errors:e.errors[t.id]||[],warnings:e.warnings[t.id]||[],touched:e.touched.has(t.id),validating:e.isValidating.has(t.id)}),[e.values,e.errors,e.warnings,e.touched,e.isValidating,t.id]),y=er.useCallback(w=>{let x=l.errors.length>0;f(t.id,w),(t.validation?.validateOnChange||x&&t.validation?.validator||l.touched&&t.validation?.validator)&&m(t.id,w);},[t.id,t.validation,f,m,l.errors.length,l.touched]),E=er.useCallback(()=>{a(t.id),(t.validation?.validateOnBlur||t.validation?.validator)&&m(t.id);},[t.id,t.validation,a,m]),v=er.useMemo(()=>{if(!t.conditional)return true;try{return t.conditional.condition(e.values)}catch(w){return console.warn(`Conditional evaluation failed for field "${t.id}":`,w),true}},[t.conditional,e.values,t.id]),h=er.useMemo(()=>{if(!t.conditional||!v)return {};switch(t.conditional.action){case "disable":return {disabled:true};case "require":return {required:true};default:return {}}},[t.conditional,v]);if(!v&&t.conditional?.action==="hide")return null;let P=er.useMemo(()=>({...F.defaultProps,...t.props,...o,...h}),[F.defaultProps,t.props,o,h]),S=er.useMemo(()=>({id:t.id,props:P,value:l.value,onChange:y,onBlur:E,error:l.errors,warnings:l.warnings,touched:l.touched,disabled:r||h.disabled,isValidating:l.validating}),[t.id,P,l.value,y,E,l.errors,l.warnings,l.touched,r,h.disabled,l.validating]),T=s.renderConfig?.fieldRenderer,R=F.renderer(S),b=F.useFieldRenderer!==false,I=T&&b?T({children:R,id:t.id,error:l.errors,warnings:l.warnings,touched:l.touched,disabled:r||h.disabled,isValidating:l.validating,...P}):R;return jsxRuntime.jsx("div",{className:d,"data-field-id":t.id,"data-field-type":F.type,children:I})}var q=er__default.default.memo(W);function H({row:i,className:r}){let{formConfig:o}=C(),d=o.renderConfig?.rowRenderer;if(!d)throw new Error(`No rowRenderer configured for form "${o.id}". Please configure a rowRenderer using config.setRowRenderer() or config.setFormRenderConfig().`);let e=i.fields.map(f=>jsxRuntime.jsx(q,{fieldId:f.id},f.id)),s={row:i,children:e,className:r,spacing:i.spacing,alignment:i.alignment};return d(s)}var J=H;function sr({className:i}){let{formConfig:r}=C(),o=r.renderConfig?.bodyRenderer;if(!o)throw new Error(`No bodyRenderer configured for form "${r.id}". Please configure a bodyRenderer using config.setBodyRenderer() or config.setFormRenderConfig().`);let d=er.useMemo(()=>r.rows.map(s=>jsxRuntime.jsx(J,{row:s},s.id)),[r.rows]);return o({formConfig:r,children:d,className:i})}function ar({className:i,children:r}){let{formState:o,submit:d,formConfig:e}=C(),s=e.renderConfig?.submitButtonRenderer;if(!s)throw new Error(`No submitButtonRenderer configured for form "${e.id}". Please configure a submitButtonRenderer using config.setSubmitButtonRenderer() or config.setFormRenderConfig().`);let f={isSubmitting:o.isSubmitting,isValid:o.isValid,isDirty:o.isDirty,onSubmit:d,className:i,children:r};return s(f)}var N=class i{constructor(r,o){this.rows=[];this.rowCounter=0;this.config=r,this.formId=o||`form-${Date.now()}`;}static create(r,o){return new i(r,o)}addField(r,o,d={},e){return this.addRowFields([{fieldId:r,componentType:o,props:d,validation:e?.validation,conditional:e?.conditional}])}addRowFields(r,o){if(r.length===0)throw new Error("At least one field is required");if(r.length>3)throw new Error("Maximum 3 fields per row");let d=`row-${++this.rowCounter}`,e=[];for(let f of r){let a=this.config.getComponent(f.componentType);if(!a)throw new Error(`No component found with type "${f.componentType}"`);let m={id:f.fieldId,componentId:a.id,props:{...a.defaultProps,...f.props},validation:f.validation,conditional:f.conditional};e.push(m);}let s={id:d,fields:e,maxColumns:r.length,spacing:o?.spacing||"normal",alignment:o?.alignment||"stretch"};return this.rows.push(s),this}addFields(r){for(let o of r)this.addField(o.fieldId,o.componentType,o.props,{validation:o.validation,conditional:o.conditional});return this}setId(r){return this.formId=r,this}updateField(r,o){let d=false;for(let e of this.rows){let s=e.fields.findIndex(f=>f.id===r);s!==-1&&(e.fields[s]={...e.fields[s],...o,props:{...e.fields[s].props,...o.props}},d=true);}if(!d)throw new Error(`Field with ID "${r}" not found`);return this}removeField(r){for(let o of this.rows){let d=o.fields.filter(e=>e.id!==r);Object.assign(o,{fields:d});}return this.rows=this.rows.filter(o=>o.fields.length>0),this}getField(r){for(let o of this.rows){let d=o.fields.find(e=>e.id===r);if(d)return d}}getFields(){return this.rows.flatMap(r=>r.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.rowCounter=0,this}clone(r){let o=new i(this.config,r);return o.rows=this.rows.map(d=>({...d,fields:d.fields.map(e=>({...e}))})),o.rowCounter=this.rowCounter,o}validate(){let r=[],o=this.getFields(),d=o.map(s=>s.id),e=d.filter((s,f)=>d.indexOf(s)!==f);e.length>0&&r.push(`Duplicate field IDs: ${e.join(", ")}`);for(let s of o)this.config.hasComponent(s.componentId)||r.push(`Component "${s.componentId}" not found for field "${s.id}"`);for(let s of this.rows)s.fields.length>3&&r.push(`Row "${s.id}" has ${s.fields.length} fields, maximum is 3`),s.fields.length===0&&r.push(`Row "${s.id}" is empty`);return r}build(){let r=this.validate();if(r.length>0)throw new Error(`Form validation failed: ${r.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig()}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(r){return r.id&&(this.formId=r.id),r.rows&&(this.rows=r.rows,this.rowCounter=this.rows.length),this}getStats(){let r=this.getFields(),o=this.rows.map(d=>d.fields.length);return {totalFields:r.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?r.length/this.rows.length:0,maxFieldsInRow:o.length>0?Math.max(...o):0,minFieldsInRow:o.length>0?Math.min(...o):0}}};Object.defineProperty(exports,"createZodValidator",{enumerable:true,get:function(){return core.createZodValidator}});Object.defineProperty(exports,"ril",{enumerable:true,get:function(){return core.ril}});exports.Form=rr;exports.FormBody=sr;exports.FormBuilder=N;exports.FormField=W;exports.FormProvider=D;exports.FormRow=H;exports.FormSubmitButton=ar;exports.form=N;exports.useFormContext=C;
1
+ 'use strict';var core=require('@rilaykit/core'),or=require('react'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var or__default=/*#__PURE__*/_interopDefault(or);var v=class o{constructor(r,e){this.rows=[];this.rowCounter=0;this.config=r,this.formId=e||`form-${Date.now()}`;}static create(r,e){return new o(r,e)}createFormField(r){let e=this.config.getComponent(r.type);if(!e)throw new Error(`No component found with type "${r.type}"`);return {id:r.id,componentId:e.id,props:{...e.defaultProps,...r.props},validation:r.validation,conditional:r.conditional}}createRow(r,e){if(r.length===0)throw new Error("At least one field is required");if(r.length>3)throw new Error("Maximum 3 fields per row");let i=r.map(s=>this.createFormField(s));return {id:`row-${++this.rowCounter}`,fields:i,maxColumns:r.length,spacing:e?.spacing||"normal",alignment:e?.alignment||"stretch"}}addField(r){return this.addRowFields([r])}addRowFields(r,e){let i=this.createRow(r,e);return this.rows.push(i),this}addFields(r){for(let e of r)this.addField(e);return this}setId(r){return this.formId=r,this}updateField(r,e){let i=this.findField(r);if(!i)throw new Error(`Field with ID "${r}" not found`);return Object.assign(i,{...e,props:{...i.props,...e.props}}),this}findField(r){for(let e of this.rows){let i=e.fields.find(s=>s.id===r);if(i)return i}return null}removeField(r){return this.rows=this.rows.map(e=>({...e,fields:e.fields.filter(i=>i.id!==r)})).filter(e=>e.fields.length>0),this}getField(r){return this.findField(r)||void 0}getFields(){return this.rows.flatMap(r=>r.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.rowCounter=0,this}clone(r){let e=new o(this.config,r||`${this.formId}-clone`);return e.rows=this.rows.map(i=>({...i,fields:i.fields.map(s=>({...s}))})),e.rowCounter=this.rowCounter,e}validate(){let r=[],e=this.getFields(),i=e.map(d=>d.id),s=i.filter((d,u)=>i.indexOf(d)!==u);s.length>0&&r.push(`Duplicate field IDs: ${s.join(", ")}`);for(let d of e)this.config.hasComponent(d.componentId)||r.push(`Component "${d.componentId}" not found for field "${d.id}"`);for(let d of this.rows)d.fields.length>3&&r.push(`Row "${d.id}" has ${d.fields.length} fields, maximum is 3`),d.fields.length===0&&r.push(`Row "${d.id}" is empty`);return r}build(){let r=this.validate();if(r.length>0)throw new Error(`Form validation failed: ${r.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig()}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(r){return r.id&&(this.formId=r.id),r.rows&&(this.rows=r.rows,this.rowCounter=this.rows.length),this}getStats(){let r=this.getFields(),e=this.rows.map(i=>i.fields.length);return {totalFields:r.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?r.length/this.rows.length:0,maxFieldsInRow:e.length>0?Math.max(...e):0,minFieldsInRow:e.length>0?Math.min(...e):0}}};function Z(o,r){return v.create(o,r)}core.ril.prototype.createForm=function(o){return v.create(this,o)};function j(o,r){switch(r.type){case "SET_VALUE":{let e={...o.values,[r.fieldId]:r.value};return {...o,values:e,isDirty:true}}case "SET_ERROR":return {...o,errors:{...o.errors,[r.fieldId]:r.errors},isValid:false};case "CLEAR_ERROR":{let e={...o.errors};return delete e[r.fieldId],{...o,errors:e}}case "MARK_TOUCHED":return {...o,touched:new Set([...o.touched,r.fieldId])};case "SET_VALIDATING":{let e=new Set(o.isValidating);return r.isValidating?e.add(r.fieldId):e.delete(r.fieldId),{...o,isValidating:e}}case "SET_SUBMITTING":return {...o,isSubmitting:r.isSubmitting};case "RESET":return {values:r.values||{},errors:{},touched:new Set,isValidating:new Set,isDirty:false,isValid:true,isSubmitting:false};case "UPDATE_VALIDATION_STATE":{let e=Object.keys(o.errors).some(i=>o.errors[i].length>0);return {...o,isValid:!e}}default:return o}}var k=or.createContext(null);function B({children:o,formConfig:r,defaultValues:e={},onSubmit:i,onFieldChange:s,className:d}){let u={values:e,errors:{},touched:new Set,isValidating:new Set,isDirty:false,isValid:true,isSubmitting:false},[a,l]=or.useReducer(j,u),t=or.useRef(new Map),c=or.useRef(i),m=or.useRef(s);c.current=i,m.current=s;let R=or.useCallback((n,f)=>{l({type:"SET_ERROR",fieldId:n,errors:f}),l({type:"UPDATE_VALIDATION_STATE"});},[]),b=or.useCallback(n=>{l({type:"CLEAR_ERROR",fieldId:n}),l({type:"UPDATE_VALIDATION_STATE"});},[]),V=or.useCallback(n=>{l({type:"MARK_TOUCHED",fieldId:n});},[]),p=or.useCallback((n,f)=>{l({type:"SET_VALIDATING",fieldId:n,isValidating:f});},[]),x=or.useCallback((n,f)=>{if(l({type:"SET_VALUE",fieldId:n,value:f}),a.errors[n]&&a.errors[n].length>0&&(l({type:"CLEAR_ERROR",fieldId:n}),l({type:"UPDATE_VALIDATION_STATE"})),m.current){let g={...a.values,[n]:f};m.current(n,f,g);}},[a.errors,a.values]),w=or.useMemo(()=>r,[r]),E=or.useCallback(async(n,f)=>{let g=w.allFields.find(I=>I.id===n);if(!g?.validation?.validator)return {isValid:true,errors:[]};let K=f!==void 0?f:a.values[n],N=t.current.get(n);N&&clearTimeout(N);let W={fieldId:n,formData:a.values,fieldProps:g.props,touched:a.touched.has(n),dirty:a.isDirty},_=g.validation.debounceMs||0;return new Promise(I=>{let O=async()=>{p(n,true);try{let y=await g.validation.validator(K,W,g.props);y.errors.length>0?R(n,y.errors):b(n),I(y);}catch(y){let U={isValid:false,errors:[{code:"validation_error",message:y instanceof Error?y.message:"Validation error"}]};R(n,U.errors),I(U);}finally{p(n,false);}};if(_>0){let y=setTimeout(O,_);t.current.set(n,y);}else O();})},[w,a.values,a.touched,a.isDirty,R,b,p]),P=or.useCallback(async()=>{let n=w.allFields.map(g=>E(g.id));return (await Promise.all(n)).every(g=>g.isValid)},[w,E]),A=or.useCallback(n=>{l({type:"RESET",values:n});},[]),T=or.useCallback(async n=>{if(n?.preventDefault(),!c.current)return true;l({type:"SET_SUBMITTING",isSubmitting:true});try{return await P()?(await c.current(a.values),!0):!1}catch(f){return console.error("Error during form submission:",f),false}finally{l({type:"SET_SUBMITTING",isSubmitting:false});}},[a.values,P]),h=or.useMemo(()=>({formState:a,formConfig:w,setValue:x,setError:R,clearError:b,markFieldTouched:V,setFieldValidating:p,validateField:E,validateAllFields:P,reset:A,submit:T}),[a,w,x,R,b,V,p,E,P,A,T]);return jsxRuntime.jsx(k.Provider,{value:h,children:jsxRuntime.jsx("form",{onSubmit:T,className:d,noValidate:true,children:o})})}function C(){let o=or.useContext(k);if(!o)throw new Error("useFormContext must be used within a FormProvider");return o}function rr({formConfig:o,defaultValues:r,onSubmit:e,onFieldChange:i,children:s}){let d=o instanceof v?o.build():o;return jsxRuntime.jsx(B,{formConfig:d,defaultValues:r,onSubmit:e,onFieldChange:i,children:s})}function G({fieldId:o,disabled:r=false,customProps:e={},className:i}){let{formState:s,formConfig:d,setValue:u,markFieldTouched:a,validateField:l}=C(),t=or.useMemo(()=>d.allFields.find(h=>h.id===o),[d.allFields,o]);if(!t)throw new Error(`Field with ID "${o}" not found`);let c=or.useMemo(()=>d.config.getComponent(t.componentId),[d.config,t.componentId]);if(!c)throw new Error(`Component with ID "${t.componentId}" not found`);let m=or.useMemo(()=>({value:s.values[t.id],errors:s.errors[t.id]||[],touched:s.touched.has(t.id),validating:s.isValidating.has(t.id)}),[s.values,s.errors,s.touched,s.isValidating,t.id]),R=or.useCallback(h=>{let n=m.errors.length>0;u(t.id,h),(t.validation?.validateOnChange||n&&t.validation?.validator||m.touched&&t.validation?.validator)&&l(t.id,h);},[t.id,t.validation,u,l,m.errors.length,m.touched]),b=or.useCallback(()=>{a(t.id),(t.validation?.validateOnBlur||t.validation?.validator)&&l(t.id);},[t.id,t.validation,a,l]),V=or.useMemo(()=>{if(!t.conditional)return true;try{return t.conditional.condition(s.values)}catch(h){return console.warn(`Conditional evaluation failed for field "${t.id}":`,h),true}},[t.conditional,s.values,t.id]),p=or.useMemo(()=>{if(!t.conditional||!V)return {};switch(t.conditional.action){case "disable":return {disabled:true};case "require":return {required:true};default:return {}}},[t.conditional,V]);if(!V&&t.conditional?.action==="hide")return null;let x=or.useMemo(()=>({...c.defaultProps,...t.props,...e,...p}),[c.defaultProps,t.props,e,p]),w=or.useMemo(()=>({id:t.id,props:x,value:m.value,onChange:R,onBlur:b,error:m.errors,touched:m.touched,disabled:r||p.disabled,isValidating:m.validating}),[t.id,x,m.value,R,b,m.errors,m.touched,r,p.disabled,m.validating]),E=d.renderConfig?.fieldRenderer,P=c.renderer(w),A=c.useFieldRenderer!==false,T=E&&A?E({children:P,id:t.id,error:m.errors,touched:m.touched,disabled:r||p.disabled,isValidating:m.validating,...x}):P;return jsxRuntime.jsx("div",{className:i,"data-field-id":t.id,"data-field-type":c.type,children:T})}var q=or__default.default.memo(G);function H({row:o,className:r,children:e,renderAs:i}){let{formConfig:s}=C(),d=o.fields.map(m=>jsxRuntime.jsx(q,{fieldId:m.id},m.id));if(i==="children"||i===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');let m={row:o,children:d,className:r,spacing:o.spacing,alignment:o.alignment};return e(m)}let a=s.renderConfig?.rowRenderer;if(!a)throw new Error(`No rowRenderer configured for form "${s.id}". Please configure a rowRenderer using config.setRowRenderer() or config.setFormRenderConfig().`);let l={row:o,children:d,className:r,spacing:o.spacing,alignment:o.alignment},t=core.resolveRendererChildren(e,l),c={...l,children:t||d};return a(c)}var J=H;function ar({className:o,children:r,renderAs:e}){let{formConfig:i}=C(),s=or.useMemo(()=>i.rows.map(c=>jsxRuntime.jsx(J,{row:c},c.id)),[i.rows]);if(e==="children"||e===true){if(typeof r!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return r({formConfig:i,children:s,className:o})}let u=i.renderConfig?.bodyRenderer;if(!u)throw new Error(`No bodyRenderer configured for form "${i.id}". Please configure a bodyRenderer using config.setBodyRenderer() or config.setFormRenderConfig().`);let a={formConfig:i,children:s,className:o},l=core.resolveRendererChildren(r,a),t={...a,children:l||s};return u(t)}function cr({className:o,children:r,renderAs:e}){let{formState:i,submit:s,formConfig:d}=C(),u={isSubmitting:i.isSubmitting,isValid:i.isValid,isDirty:i.isDirty,onSubmit:s,className:o};if(e==="children"||e===true){if(typeof r!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return r(u)}let l=d.renderConfig?.submitButtonRenderer;if(!l)throw new Error(`No submitButtonRenderer configured for form "${d.id}". Please configure a submitButtonRenderer using config.setSubmitButtonRenderer() or config.setFormRenderConfig().`);let t=core.resolveRendererChildren(r,u),c={...u,children:t};return l(c)}Object.defineProperty(exports,"createZodValidator",{enumerable:true,get:function(){return core.createZodValidator}});Object.defineProperty(exports,"ril",{enumerable:true,get:function(){return core.ril}});exports.Form=rr;exports.FormBody=ar;exports.FormBuilder=v;exports.FormField=G;exports.FormProvider=B;exports.FormRow=H;exports.FormSubmitButton=cr;exports.createForm=Z;exports.form=v;exports.useFormContext=C;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import er,{createContext,useMemo,useCallback,useContext,useReducer,useRef}from'react';import {jsx}from'react/jsx-runtime';export{createZodValidator,ril}from'@rilaykit/core';function j(i,r){switch(r.type){case "SET_VALUE":{let o={...i.values,[r.fieldId]:r.value};return {...i,values:o,isDirty:true}}case "SET_ERROR":return {...i,errors:{...i.errors,[r.fieldId]:r.errors},isValid:false};case "SET_WARNING":return {...i,warnings:{...i.warnings,[r.fieldId]:r.warnings}};case "CLEAR_ERROR":{let o={...i.errors};return delete o[r.fieldId],{...i,errors:o}}case "CLEAR_WARNING":{let o={...i.warnings};return delete o[r.fieldId],{...i,warnings:o}}case "MARK_TOUCHED":return {...i,touched:new Set([...i.touched,r.fieldId])};case "SET_VALIDATING":{let o=new Set(i.isValidating);return r.isValidating?o.add(r.fieldId):o.delete(r.fieldId),{...i,isValidating:o}}case "SET_SUBMITTING":return {...i,isSubmitting:r.isSubmitting};case "RESET":return {values:r.values||{},errors:{},warnings:{},touched:new Set,isValidating:new Set,isDirty:false,isValid:true,isSubmitting:false};case "UPDATE_VALIDATION_STATE":{let o=Object.keys(i.errors).some(d=>i.errors[d].length>0);return {...i,isValid:!o}}default:return i}}var U=createContext(null);function D({children:i,formConfig:r,defaultValues:o={},onSubmit:d,onFieldChange:e,className:s}){let f={values:o,errors:{},warnings:{},touched:new Set,isValidating:new Set,isDirty:false,isValid:true,isSubmitting:false},[a,m]=useReducer(j,f),t=useRef(new Map),F=useRef(d),l=useRef(e);F.current=d,l.current=e;let y=useCallback((n,c)=>{m({type:"SET_ERROR",fieldId:n,errors:c}),m({type:"UPDATE_VALIDATION_STATE"});},[]),E=useCallback((n,c)=>{m({type:"SET_WARNING",fieldId:n,warnings:c});},[]),v=useCallback(n=>{m({type:"CLEAR_ERROR",fieldId:n}),m({type:"UPDATE_VALIDATION_STATE"});},[]),h=useCallback(n=>{m({type:"CLEAR_WARNING",fieldId:n});},[]),P=useCallback(n=>{m({type:"MARK_TOUCHED",fieldId:n});},[]),S=useCallback((n,c)=>{m({type:"SET_VALIDATING",fieldId:n,isValidating:c});},[]),T=useCallback((n,c)=>{if(m({type:"SET_VALUE",fieldId:n,value:c}),a.errors[n]&&a.errors[n].length>0&&(m({type:"CLEAR_ERROR",fieldId:n}),m({type:"UPDATE_VALIDATION_STATE"})),l.current){let u={...a.values,[n]:c};l.current(n,c,u);}},[a.errors,a.values]),R=useMemo(()=>r,[r]),b=useCallback(async(n,c)=>{let u=R.allFields.find(A=>A.id===n);if(!u?.validation?.validator)return {isValid:true,errors:[]};let z=c!==void 0?c:a.values[n],B=t.current.get(n);B&&clearTimeout(B);let Z={fieldId:n,formData:a.values,fieldProps:u.props,touched:a.touched.has(n),dirty:a.isDirty},O=u.validation.debounceMs||0;return new Promise(A=>{let L=async()=>{S(n,true);try{let g=await u.validation.validator(z,Z,u.props);g.errors.length>0?y(n,g.errors):v(n),g.warnings&&g.warnings.length>0?E(n,g.warnings):h(n),A(g);}catch(g){let M={isValid:false,errors:[{code:"validation_error",message:g instanceof Error?g.message:"Validation error"}]};y(n,M.errors),A(M);}finally{S(n,false);}};if(O>0){let g=setTimeout(L,O);t.current.set(n,g);}else L();})},[R,a.values,a.touched,a.isDirty,y,E,v,h,S]),I=useCallback(async()=>{let n=R.allFields.map(u=>b(u.id));return (await Promise.all(n)).every(u=>u.isValid)},[R,b]),w=useCallback(n=>{m({type:"RESET",values:n});},[]),x=useCallback(async n=>{if(n?.preventDefault(),!F.current)return true;m({type:"SET_SUBMITTING",isSubmitting:true});try{return await I()?(await F.current(a.values),!0):!1}catch(c){return console.error("Error during form submission:",c),false}finally{m({type:"SET_SUBMITTING",isSubmitting:false});}},[a.values,I]),K=useMemo(()=>({formState:a,formConfig:R,setValue:T,setError:y,setWarning:E,clearError:v,clearWarning:h,markFieldTouched:P,setFieldValidating:S,validateField:b,validateAllFields:I,reset:w,submit:x}),[a,R,T,y,E,v,h,P,S,b,I,w,x]);return jsx(U.Provider,{value:K,children:jsx("form",{onSubmit:x,className:s,noValidate:true,children:i})})}function C(){let i=useContext(U);if(!i)throw new Error("useFormContext must be used within a FormProvider");return i}function rr({formConfig:i,defaultValues:r,onSubmit:o,onFieldChange:d,children:e}){return jsx(D,{formConfig:i,defaultValues:r,onSubmit:o,onFieldChange:d,className:"streamline-form",children:e})}function W({fieldId:i,disabled:r=false,customProps:o={},className:d}){let{formState:e,formConfig:s,setValue:f,markFieldTouched:a,validateField:m}=C(),t=useMemo(()=>s.allFields.find(w=>w.id===i),[s.allFields,i]);if(!t)throw new Error(`Field with ID "${i}" not found`);let F=useMemo(()=>s.config.getComponent(t.componentId),[s.config,t.componentId]);if(!F)throw new Error(`Component with ID "${t.componentId}" not found`);let l=useMemo(()=>({value:e.values[t.id],errors:e.errors[t.id]||[],warnings:e.warnings[t.id]||[],touched:e.touched.has(t.id),validating:e.isValidating.has(t.id)}),[e.values,e.errors,e.warnings,e.touched,e.isValidating,t.id]),y=useCallback(w=>{let x=l.errors.length>0;f(t.id,w),(t.validation?.validateOnChange||x&&t.validation?.validator||l.touched&&t.validation?.validator)&&m(t.id,w);},[t.id,t.validation,f,m,l.errors.length,l.touched]),E=useCallback(()=>{a(t.id),(t.validation?.validateOnBlur||t.validation?.validator)&&m(t.id);},[t.id,t.validation,a,m]),v=useMemo(()=>{if(!t.conditional)return true;try{return t.conditional.condition(e.values)}catch(w){return console.warn(`Conditional evaluation failed for field "${t.id}":`,w),true}},[t.conditional,e.values,t.id]),h=useMemo(()=>{if(!t.conditional||!v)return {};switch(t.conditional.action){case "disable":return {disabled:true};case "require":return {required:true};default:return {}}},[t.conditional,v]);if(!v&&t.conditional?.action==="hide")return null;let P=useMemo(()=>({...F.defaultProps,...t.props,...o,...h}),[F.defaultProps,t.props,o,h]),S=useMemo(()=>({id:t.id,props:P,value:l.value,onChange:y,onBlur:E,error:l.errors,warnings:l.warnings,touched:l.touched,disabled:r||h.disabled,isValidating:l.validating}),[t.id,P,l.value,y,E,l.errors,l.warnings,l.touched,r,h.disabled,l.validating]),T=s.renderConfig?.fieldRenderer,R=F.renderer(S),b=F.useFieldRenderer!==false,I=T&&b?T({children:R,id:t.id,error:l.errors,warnings:l.warnings,touched:l.touched,disabled:r||h.disabled,isValidating:l.validating,...P}):R;return jsx("div",{className:d,"data-field-id":t.id,"data-field-type":F.type,children:I})}var q=er.memo(W);function H({row:i,className:r}){let{formConfig:o}=C(),d=o.renderConfig?.rowRenderer;if(!d)throw new Error(`No rowRenderer configured for form "${o.id}". Please configure a rowRenderer using config.setRowRenderer() or config.setFormRenderConfig().`);let e=i.fields.map(f=>jsx(q,{fieldId:f.id},f.id)),s={row:i,children:e,className:r,spacing:i.spacing,alignment:i.alignment};return d(s)}var J=H;function sr({className:i}){let{formConfig:r}=C(),o=r.renderConfig?.bodyRenderer;if(!o)throw new Error(`No bodyRenderer configured for form "${r.id}". Please configure a bodyRenderer using config.setBodyRenderer() or config.setFormRenderConfig().`);let d=useMemo(()=>r.rows.map(s=>jsx(J,{row:s},s.id)),[r.rows]);return o({formConfig:r,children:d,className:i})}function ar({className:i,children:r}){let{formState:o,submit:d,formConfig:e}=C(),s=e.renderConfig?.submitButtonRenderer;if(!s)throw new Error(`No submitButtonRenderer configured for form "${e.id}". Please configure a submitButtonRenderer using config.setSubmitButtonRenderer() or config.setFormRenderConfig().`);let f={isSubmitting:o.isSubmitting,isValid:o.isValid,isDirty:o.isDirty,onSubmit:d,className:i,children:r};return s(f)}var N=class i{constructor(r,o){this.rows=[];this.rowCounter=0;this.config=r,this.formId=o||`form-${Date.now()}`;}static create(r,o){return new i(r,o)}addField(r,o,d={},e){return this.addRowFields([{fieldId:r,componentType:o,props:d,validation:e?.validation,conditional:e?.conditional}])}addRowFields(r,o){if(r.length===0)throw new Error("At least one field is required");if(r.length>3)throw new Error("Maximum 3 fields per row");let d=`row-${++this.rowCounter}`,e=[];for(let f of r){let a=this.config.getComponent(f.componentType);if(!a)throw new Error(`No component found with type "${f.componentType}"`);let m={id:f.fieldId,componentId:a.id,props:{...a.defaultProps,...f.props},validation:f.validation,conditional:f.conditional};e.push(m);}let s={id:d,fields:e,maxColumns:r.length,spacing:o?.spacing||"normal",alignment:o?.alignment||"stretch"};return this.rows.push(s),this}addFields(r){for(let o of r)this.addField(o.fieldId,o.componentType,o.props,{validation:o.validation,conditional:o.conditional});return this}setId(r){return this.formId=r,this}updateField(r,o){let d=false;for(let e of this.rows){let s=e.fields.findIndex(f=>f.id===r);s!==-1&&(e.fields[s]={...e.fields[s],...o,props:{...e.fields[s].props,...o.props}},d=true);}if(!d)throw new Error(`Field with ID "${r}" not found`);return this}removeField(r){for(let o of this.rows){let d=o.fields.filter(e=>e.id!==r);Object.assign(o,{fields:d});}return this.rows=this.rows.filter(o=>o.fields.length>0),this}getField(r){for(let o of this.rows){let d=o.fields.find(e=>e.id===r);if(d)return d}}getFields(){return this.rows.flatMap(r=>r.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.rowCounter=0,this}clone(r){let o=new i(this.config,r);return o.rows=this.rows.map(d=>({...d,fields:d.fields.map(e=>({...e}))})),o.rowCounter=this.rowCounter,o}validate(){let r=[],o=this.getFields(),d=o.map(s=>s.id),e=d.filter((s,f)=>d.indexOf(s)!==f);e.length>0&&r.push(`Duplicate field IDs: ${e.join(", ")}`);for(let s of o)this.config.hasComponent(s.componentId)||r.push(`Component "${s.componentId}" not found for field "${s.id}"`);for(let s of this.rows)s.fields.length>3&&r.push(`Row "${s.id}" has ${s.fields.length} fields, maximum is 3`),s.fields.length===0&&r.push(`Row "${s.id}" is empty`);return r}build(){let r=this.validate();if(r.length>0)throw new Error(`Form validation failed: ${r.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig()}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(r){return r.id&&(this.formId=r.id),r.rows&&(this.rows=r.rows,this.rowCounter=this.rows.length),this}getStats(){let r=this.getFields(),o=this.rows.map(d=>d.fields.length);return {totalFields:r.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?r.length/this.rows.length:0,maxFieldsInRow:o.length>0?Math.max(...o):0,minFieldsInRow:o.length>0?Math.min(...o):0}}};export{rr as Form,sr as FormBody,N as FormBuilder,W as FormField,D as FormProvider,H as FormRow,ar as FormSubmitButton,N as form,C as useFormContext};
1
+ import {ril,resolveRendererChildren}from'@rilaykit/core';export{createZodValidator,ril}from'@rilaykit/core';import or,{createContext,useMemo,useCallback,useContext,useReducer,useRef}from'react';import {jsx}from'react/jsx-runtime';var v=class o{constructor(r,e){this.rows=[];this.rowCounter=0;this.config=r,this.formId=e||`form-${Date.now()}`;}static create(r,e){return new o(r,e)}createFormField(r){let e=this.config.getComponent(r.type);if(!e)throw new Error(`No component found with type "${r.type}"`);return {id:r.id,componentId:e.id,props:{...e.defaultProps,...r.props},validation:r.validation,conditional:r.conditional}}createRow(r,e){if(r.length===0)throw new Error("At least one field is required");if(r.length>3)throw new Error("Maximum 3 fields per row");let i=r.map(s=>this.createFormField(s));return {id:`row-${++this.rowCounter}`,fields:i,maxColumns:r.length,spacing:e?.spacing||"normal",alignment:e?.alignment||"stretch"}}addField(r){return this.addRowFields([r])}addRowFields(r,e){let i=this.createRow(r,e);return this.rows.push(i),this}addFields(r){for(let e of r)this.addField(e);return this}setId(r){return this.formId=r,this}updateField(r,e){let i=this.findField(r);if(!i)throw new Error(`Field with ID "${r}" not found`);return Object.assign(i,{...e,props:{...i.props,...e.props}}),this}findField(r){for(let e of this.rows){let i=e.fields.find(s=>s.id===r);if(i)return i}return null}removeField(r){return this.rows=this.rows.map(e=>({...e,fields:e.fields.filter(i=>i.id!==r)})).filter(e=>e.fields.length>0),this}getField(r){return this.findField(r)||void 0}getFields(){return this.rows.flatMap(r=>r.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.rowCounter=0,this}clone(r){let e=new o(this.config,r||`${this.formId}-clone`);return e.rows=this.rows.map(i=>({...i,fields:i.fields.map(s=>({...s}))})),e.rowCounter=this.rowCounter,e}validate(){let r=[],e=this.getFields(),i=e.map(d=>d.id),s=i.filter((d,u)=>i.indexOf(d)!==u);s.length>0&&r.push(`Duplicate field IDs: ${s.join(", ")}`);for(let d of e)this.config.hasComponent(d.componentId)||r.push(`Component "${d.componentId}" not found for field "${d.id}"`);for(let d of this.rows)d.fields.length>3&&r.push(`Row "${d.id}" has ${d.fields.length} fields, maximum is 3`),d.fields.length===0&&r.push(`Row "${d.id}" is empty`);return r}build(){let r=this.validate();if(r.length>0)throw new Error(`Form validation failed: ${r.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig()}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(r){return r.id&&(this.formId=r.id),r.rows&&(this.rows=r.rows,this.rowCounter=this.rows.length),this}getStats(){let r=this.getFields(),e=this.rows.map(i=>i.fields.length);return {totalFields:r.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?r.length/this.rows.length:0,maxFieldsInRow:e.length>0?Math.max(...e):0,minFieldsInRow:e.length>0?Math.min(...e):0}}};function Z(o,r){return v.create(o,r)}ril.prototype.createForm=function(o){return v.create(this,o)};function j(o,r){switch(r.type){case "SET_VALUE":{let e={...o.values,[r.fieldId]:r.value};return {...o,values:e,isDirty:true}}case "SET_ERROR":return {...o,errors:{...o.errors,[r.fieldId]:r.errors},isValid:false};case "CLEAR_ERROR":{let e={...o.errors};return delete e[r.fieldId],{...o,errors:e}}case "MARK_TOUCHED":return {...o,touched:new Set([...o.touched,r.fieldId])};case "SET_VALIDATING":{let e=new Set(o.isValidating);return r.isValidating?e.add(r.fieldId):e.delete(r.fieldId),{...o,isValidating:e}}case "SET_SUBMITTING":return {...o,isSubmitting:r.isSubmitting};case "RESET":return {values:r.values||{},errors:{},touched:new Set,isValidating:new Set,isDirty:false,isValid:true,isSubmitting:false};case "UPDATE_VALIDATION_STATE":{let e=Object.keys(o.errors).some(i=>o.errors[i].length>0);return {...o,isValid:!e}}default:return o}}var k=createContext(null);function B({children:o,formConfig:r,defaultValues:e={},onSubmit:i,onFieldChange:s,className:d}){let u={values:e,errors:{},touched:new Set,isValidating:new Set,isDirty:false,isValid:true,isSubmitting:false},[a,l]=useReducer(j,u),t=useRef(new Map),c=useRef(i),m=useRef(s);c.current=i,m.current=s;let R=useCallback((n,f)=>{l({type:"SET_ERROR",fieldId:n,errors:f}),l({type:"UPDATE_VALIDATION_STATE"});},[]),b=useCallback(n=>{l({type:"CLEAR_ERROR",fieldId:n}),l({type:"UPDATE_VALIDATION_STATE"});},[]),V=useCallback(n=>{l({type:"MARK_TOUCHED",fieldId:n});},[]),p=useCallback((n,f)=>{l({type:"SET_VALIDATING",fieldId:n,isValidating:f});},[]),x=useCallback((n,f)=>{if(l({type:"SET_VALUE",fieldId:n,value:f}),a.errors[n]&&a.errors[n].length>0&&(l({type:"CLEAR_ERROR",fieldId:n}),l({type:"UPDATE_VALIDATION_STATE"})),m.current){let g={...a.values,[n]:f};m.current(n,f,g);}},[a.errors,a.values]),w=useMemo(()=>r,[r]),E=useCallback(async(n,f)=>{let g=w.allFields.find(I=>I.id===n);if(!g?.validation?.validator)return {isValid:true,errors:[]};let K=f!==void 0?f:a.values[n],N=t.current.get(n);N&&clearTimeout(N);let W={fieldId:n,formData:a.values,fieldProps:g.props,touched:a.touched.has(n),dirty:a.isDirty},_=g.validation.debounceMs||0;return new Promise(I=>{let O=async()=>{p(n,true);try{let y=await g.validation.validator(K,W,g.props);y.errors.length>0?R(n,y.errors):b(n),I(y);}catch(y){let U={isValid:false,errors:[{code:"validation_error",message:y instanceof Error?y.message:"Validation error"}]};R(n,U.errors),I(U);}finally{p(n,false);}};if(_>0){let y=setTimeout(O,_);t.current.set(n,y);}else O();})},[w,a.values,a.touched,a.isDirty,R,b,p]),P=useCallback(async()=>{let n=w.allFields.map(g=>E(g.id));return (await Promise.all(n)).every(g=>g.isValid)},[w,E]),A=useCallback(n=>{l({type:"RESET",values:n});},[]),T=useCallback(async n=>{if(n?.preventDefault(),!c.current)return true;l({type:"SET_SUBMITTING",isSubmitting:true});try{return await P()?(await c.current(a.values),!0):!1}catch(f){return console.error("Error during form submission:",f),false}finally{l({type:"SET_SUBMITTING",isSubmitting:false});}},[a.values,P]),h=useMemo(()=>({formState:a,formConfig:w,setValue:x,setError:R,clearError:b,markFieldTouched:V,setFieldValidating:p,validateField:E,validateAllFields:P,reset:A,submit:T}),[a,w,x,R,b,V,p,E,P,A,T]);return jsx(k.Provider,{value:h,children:jsx("form",{onSubmit:T,className:d,noValidate:true,children:o})})}function C(){let o=useContext(k);if(!o)throw new Error("useFormContext must be used within a FormProvider");return o}function rr({formConfig:o,defaultValues:r,onSubmit:e,onFieldChange:i,children:s}){let d=o instanceof v?o.build():o;return jsx(B,{formConfig:d,defaultValues:r,onSubmit:e,onFieldChange:i,children:s})}function G({fieldId:o,disabled:r=false,customProps:e={},className:i}){let{formState:s,formConfig:d,setValue:u,markFieldTouched:a,validateField:l}=C(),t=useMemo(()=>d.allFields.find(h=>h.id===o),[d.allFields,o]);if(!t)throw new Error(`Field with ID "${o}" not found`);let c=useMemo(()=>d.config.getComponent(t.componentId),[d.config,t.componentId]);if(!c)throw new Error(`Component with ID "${t.componentId}" not found`);let m=useMemo(()=>({value:s.values[t.id],errors:s.errors[t.id]||[],touched:s.touched.has(t.id),validating:s.isValidating.has(t.id)}),[s.values,s.errors,s.touched,s.isValidating,t.id]),R=useCallback(h=>{let n=m.errors.length>0;u(t.id,h),(t.validation?.validateOnChange||n&&t.validation?.validator||m.touched&&t.validation?.validator)&&l(t.id,h);},[t.id,t.validation,u,l,m.errors.length,m.touched]),b=useCallback(()=>{a(t.id),(t.validation?.validateOnBlur||t.validation?.validator)&&l(t.id);},[t.id,t.validation,a,l]),V=useMemo(()=>{if(!t.conditional)return true;try{return t.conditional.condition(s.values)}catch(h){return console.warn(`Conditional evaluation failed for field "${t.id}":`,h),true}},[t.conditional,s.values,t.id]),p=useMemo(()=>{if(!t.conditional||!V)return {};switch(t.conditional.action){case "disable":return {disabled:true};case "require":return {required:true};default:return {}}},[t.conditional,V]);if(!V&&t.conditional?.action==="hide")return null;let x=useMemo(()=>({...c.defaultProps,...t.props,...e,...p}),[c.defaultProps,t.props,e,p]),w=useMemo(()=>({id:t.id,props:x,value:m.value,onChange:R,onBlur:b,error:m.errors,touched:m.touched,disabled:r||p.disabled,isValidating:m.validating}),[t.id,x,m.value,R,b,m.errors,m.touched,r,p.disabled,m.validating]),E=d.renderConfig?.fieldRenderer,P=c.renderer(w),A=c.useFieldRenderer!==false,T=E&&A?E({children:P,id:t.id,error:m.errors,touched:m.touched,disabled:r||p.disabled,isValidating:m.validating,...x}):P;return jsx("div",{className:i,"data-field-id":t.id,"data-field-type":c.type,children:T})}var q=or.memo(G);function H({row:o,className:r,children:e,renderAs:i}){let{formConfig:s}=C(),d=o.fields.map(m=>jsx(q,{fieldId:m.id},m.id));if(i==="children"||i===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');let m={row:o,children:d,className:r,spacing:o.spacing,alignment:o.alignment};return e(m)}let a=s.renderConfig?.rowRenderer;if(!a)throw new Error(`No rowRenderer configured for form "${s.id}". Please configure a rowRenderer using config.setRowRenderer() or config.setFormRenderConfig().`);let l={row:o,children:d,className:r,spacing:o.spacing,alignment:o.alignment},t=resolveRendererChildren(e,l),c={...l,children:t||d};return a(c)}var J=H;function ar({className:o,children:r,renderAs:e}){let{formConfig:i}=C(),s=useMemo(()=>i.rows.map(c=>jsx(J,{row:c},c.id)),[i.rows]);if(e==="children"||e===true){if(typeof r!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return r({formConfig:i,children:s,className:o})}let u=i.renderConfig?.bodyRenderer;if(!u)throw new Error(`No bodyRenderer configured for form "${i.id}". Please configure a bodyRenderer using config.setBodyRenderer() or config.setFormRenderConfig().`);let a={formConfig:i,children:s,className:o},l=resolveRendererChildren(r,a),t={...a,children:l||s};return u(t)}function cr({className:o,children:r,renderAs:e}){let{formState:i,submit:s,formConfig:d}=C(),u={isSubmitting:i.isSubmitting,isValid:i.isValid,isDirty:i.isDirty,onSubmit:s,className:o};if(e==="children"||e===true){if(typeof r!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return r(u)}let l=d.renderConfig?.submitButtonRenderer;if(!l)throw new Error(`No submitButtonRenderer configured for form "${d.id}". Please configure a submitButtonRenderer using config.setSubmitButtonRenderer() or config.setFormRenderConfig().`);let t=resolveRendererChildren(r,u),c={...u,children:t};return l(c)}export{rr as Form,ar as FormBody,v as FormBuilder,G as FormField,B as FormProvider,H as FormRow,cr as FormSubmitButton,Z as createForm,v as form,C as useFormContext};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rilaykit/forms",
3
- "version": "1.3.0",
3
+ "version": "2.0.1",
4
4
  "description": "Form building utilities and components for RilayKit",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,7 +24,7 @@
24
24
  "url": "https://github.com/andyoucreate/rilay/issues"
25
25
  },
26
26
  "dependencies": {
27
- "@rilaykit/core": "1.3.0"
27
+ "@rilaykit/core": "2.0.1"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "react": ">=18.0.0",