@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 +111 -125
- package/dist/index.d.ts +111 -125
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,84 +1,24 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
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
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
65
|
-
|
|
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
|
-
*
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
*
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
105
|
-
|
|
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:
|
|
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 {
|
|
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
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
65
|
-
|
|
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
|
-
*
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
*
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
105
|
-
|
|
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:
|
|
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": "
|
|
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": "
|
|
27
|
+
"@rilaykit/core": "2.0.1"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"react": ">=18.0.0",
|