@rilaykit/forms 2.0.1 → 3.0.0
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 +19 -17
- package/dist/index.d.ts +19 -17
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -5,13 +5,13 @@ export { createZodValidator, ril } from '@rilaykit/core';
|
|
|
5
5
|
import * as React$1 from 'react';
|
|
6
6
|
import React__default from 'react';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
type FieldConfig<C extends Record<string, any>, T extends keyof C> = {
|
|
9
9
|
id: string;
|
|
10
|
-
type:
|
|
11
|
-
props?:
|
|
10
|
+
type: T;
|
|
11
|
+
props?: Partial<C[T]>;
|
|
12
12
|
validation?: ValidationConfig;
|
|
13
13
|
conditional?: ConditionalConfig;
|
|
14
|
-
}
|
|
14
|
+
};
|
|
15
15
|
interface RowOptions {
|
|
16
16
|
spacing?: 'tight' | 'normal' | 'loose';
|
|
17
17
|
alignment?: 'start' | 'center' | 'end' | 'stretch';
|
|
@@ -20,13 +20,13 @@ interface RowOptions {
|
|
|
20
20
|
* Form builder class for creating form configurations
|
|
21
21
|
* Simplified API with matrix support and auto-build capability
|
|
22
22
|
*/
|
|
23
|
-
declare class form {
|
|
23
|
+
declare class form<C extends Record<string, any> = Record<string, never>> {
|
|
24
24
|
private config;
|
|
25
25
|
private rows;
|
|
26
26
|
private formId;
|
|
27
27
|
private rowCounter;
|
|
28
|
-
constructor(config: ril
|
|
29
|
-
static create(config: ril
|
|
28
|
+
constructor(config: ril<C>, formId?: string);
|
|
29
|
+
static create<Cm extends Record<string, any> = Record<string, never>>(config: ril<Cm>, formId?: string): form<Cm>;
|
|
30
30
|
/**
|
|
31
31
|
* Helper method to create a FormFieldConfig from a FieldConfig
|
|
32
32
|
*/
|
|
@@ -38,15 +38,17 @@ declare class form {
|
|
|
38
38
|
/**
|
|
39
39
|
* Add a single field using simplified FieldConfig object
|
|
40
40
|
*/
|
|
41
|
-
addField(fieldConfig: FieldConfig
|
|
41
|
+
addField<T extends keyof C & string>(fieldConfig: FieldConfig<C, T> & {
|
|
42
|
+
type: keyof C;
|
|
43
|
+
}): this;
|
|
42
44
|
/**
|
|
43
45
|
* Add multiple fields on the same row (max 3 fields)
|
|
44
46
|
*/
|
|
45
|
-
addRowFields(fieldConfigs: FieldConfig[], rowOptions?: RowOptions): this;
|
|
47
|
+
addRowFields<T extends keyof C & string>(fieldConfigs: FieldConfig<C, T>[], rowOptions?: RowOptions): this;
|
|
46
48
|
/**
|
|
47
49
|
* Add multiple fields, each on its own row
|
|
48
50
|
*/
|
|
49
|
-
addFields(fieldConfigs: FieldConfig[]): this;
|
|
51
|
+
addFields<T extends keyof C & string>(fieldConfigs: FieldConfig<C, T>[]): this;
|
|
50
52
|
/**
|
|
51
53
|
* Set form ID
|
|
52
54
|
*/
|
|
@@ -82,7 +84,7 @@ declare class form {
|
|
|
82
84
|
/**
|
|
83
85
|
* Clone the current form builder
|
|
84
86
|
*/
|
|
85
|
-
clone(newFormId?: string): form
|
|
87
|
+
clone(newFormId?: string): form<C>;
|
|
86
88
|
/**
|
|
87
89
|
* Validate the form configuration
|
|
88
90
|
*/
|
|
@@ -113,10 +115,10 @@ declare class form {
|
|
|
113
115
|
/**
|
|
114
116
|
* Factory function to create a form builder directly
|
|
115
117
|
*/
|
|
116
|
-
declare function createForm(config: ril
|
|
118
|
+
declare function createForm<C extends Record<string, any>>(config: ril<C>, formId?: string): form<C>;
|
|
117
119
|
declare module '@rilaykit/core' {
|
|
118
|
-
interface ril {
|
|
119
|
-
createForm(formId?: string): form
|
|
120
|
+
interface ril<C extends Record<string, any> = Record<string, never>> {
|
|
121
|
+
createForm(formId?: string): form<C>;
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
124
|
|
|
@@ -135,7 +137,7 @@ interface FormBodyProps {
|
|
|
135
137
|
children?: React.ReactNode | RendererChildrenFunction<FormBodyRendererProps>;
|
|
136
138
|
renderAs?: 'default' | 'children' | boolean;
|
|
137
139
|
}
|
|
138
|
-
declare function FormBody({ className, children, renderAs }: FormBodyProps): React$1.ReactNode;
|
|
140
|
+
declare function FormBody({ className, children, renderAs }: FormBodyProps): string | number | boolean | React$1.ReactElement<any, string | React$1.JSXElementConstructor<any>> | Iterable<React$1.ReactNode> | null | undefined;
|
|
139
141
|
|
|
140
142
|
interface FormFieldProps {
|
|
141
143
|
fieldId: string;
|
|
@@ -184,13 +186,13 @@ interface FormRowProps {
|
|
|
184
186
|
children?: React.ReactNode | RendererChildrenFunction<FormRowRendererProps>;
|
|
185
187
|
renderAs?: 'default' | 'children' | boolean;
|
|
186
188
|
}
|
|
187
|
-
declare function FormRow({ row, className, children, renderAs }: FormRowProps): React$1.ReactNode;
|
|
189
|
+
declare function FormRow({ row, className, children, renderAs }: FormRowProps): string | number | boolean | React$1.ReactElement<any, string | React$1.JSXElementConstructor<any>> | Iterable<React$1.ReactNode> | null | undefined;
|
|
188
190
|
|
|
189
191
|
interface FormSubmitButtonProps {
|
|
190
192
|
className?: string;
|
|
191
193
|
children?: React__default.ReactNode | RendererChildrenFunction<FormSubmitButtonRendererProps>;
|
|
192
194
|
renderAs?: 'default' | 'children' | boolean;
|
|
193
195
|
}
|
|
194
|
-
declare function FormSubmitButton({ className, children, renderAs }: FormSubmitButtonProps): React__default.ReactNode;
|
|
196
|
+
declare function FormSubmitButton({ className, children, renderAs }: FormSubmitButtonProps): string | number | boolean | React__default.ReactElement<any, string | React__default.JSXElementConstructor<any>> | Iterable<React__default.ReactNode> | null | undefined;
|
|
195
197
|
|
|
196
198
|
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
|
@@ -5,13 +5,13 @@ export { createZodValidator, ril } from '@rilaykit/core';
|
|
|
5
5
|
import * as React$1 from 'react';
|
|
6
6
|
import React__default from 'react';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
type FieldConfig<C extends Record<string, any>, T extends keyof C> = {
|
|
9
9
|
id: string;
|
|
10
|
-
type:
|
|
11
|
-
props?:
|
|
10
|
+
type: T;
|
|
11
|
+
props?: Partial<C[T]>;
|
|
12
12
|
validation?: ValidationConfig;
|
|
13
13
|
conditional?: ConditionalConfig;
|
|
14
|
-
}
|
|
14
|
+
};
|
|
15
15
|
interface RowOptions {
|
|
16
16
|
spacing?: 'tight' | 'normal' | 'loose';
|
|
17
17
|
alignment?: 'start' | 'center' | 'end' | 'stretch';
|
|
@@ -20,13 +20,13 @@ interface RowOptions {
|
|
|
20
20
|
* Form builder class for creating form configurations
|
|
21
21
|
* Simplified API with matrix support and auto-build capability
|
|
22
22
|
*/
|
|
23
|
-
declare class form {
|
|
23
|
+
declare class form<C extends Record<string, any> = Record<string, never>> {
|
|
24
24
|
private config;
|
|
25
25
|
private rows;
|
|
26
26
|
private formId;
|
|
27
27
|
private rowCounter;
|
|
28
|
-
constructor(config: ril
|
|
29
|
-
static create(config: ril
|
|
28
|
+
constructor(config: ril<C>, formId?: string);
|
|
29
|
+
static create<Cm extends Record<string, any> = Record<string, never>>(config: ril<Cm>, formId?: string): form<Cm>;
|
|
30
30
|
/**
|
|
31
31
|
* Helper method to create a FormFieldConfig from a FieldConfig
|
|
32
32
|
*/
|
|
@@ -38,15 +38,17 @@ declare class form {
|
|
|
38
38
|
/**
|
|
39
39
|
* Add a single field using simplified FieldConfig object
|
|
40
40
|
*/
|
|
41
|
-
addField(fieldConfig: FieldConfig
|
|
41
|
+
addField<T extends keyof C & string>(fieldConfig: FieldConfig<C, T> & {
|
|
42
|
+
type: keyof C;
|
|
43
|
+
}): this;
|
|
42
44
|
/**
|
|
43
45
|
* Add multiple fields on the same row (max 3 fields)
|
|
44
46
|
*/
|
|
45
|
-
addRowFields(fieldConfigs: FieldConfig[], rowOptions?: RowOptions): this;
|
|
47
|
+
addRowFields<T extends keyof C & string>(fieldConfigs: FieldConfig<C, T>[], rowOptions?: RowOptions): this;
|
|
46
48
|
/**
|
|
47
49
|
* Add multiple fields, each on its own row
|
|
48
50
|
*/
|
|
49
|
-
addFields(fieldConfigs: FieldConfig[]): this;
|
|
51
|
+
addFields<T extends keyof C & string>(fieldConfigs: FieldConfig<C, T>[]): this;
|
|
50
52
|
/**
|
|
51
53
|
* Set form ID
|
|
52
54
|
*/
|
|
@@ -82,7 +84,7 @@ declare class form {
|
|
|
82
84
|
/**
|
|
83
85
|
* Clone the current form builder
|
|
84
86
|
*/
|
|
85
|
-
clone(newFormId?: string): form
|
|
87
|
+
clone(newFormId?: string): form<C>;
|
|
86
88
|
/**
|
|
87
89
|
* Validate the form configuration
|
|
88
90
|
*/
|
|
@@ -113,10 +115,10 @@ declare class form {
|
|
|
113
115
|
/**
|
|
114
116
|
* Factory function to create a form builder directly
|
|
115
117
|
*/
|
|
116
|
-
declare function createForm(config: ril
|
|
118
|
+
declare function createForm<C extends Record<string, any>>(config: ril<C>, formId?: string): form<C>;
|
|
117
119
|
declare module '@rilaykit/core' {
|
|
118
|
-
interface ril {
|
|
119
|
-
createForm(formId?: string): form
|
|
120
|
+
interface ril<C extends Record<string, any> = Record<string, never>> {
|
|
121
|
+
createForm(formId?: string): form<C>;
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
124
|
|
|
@@ -135,7 +137,7 @@ interface FormBodyProps {
|
|
|
135
137
|
children?: React.ReactNode | RendererChildrenFunction<FormBodyRendererProps>;
|
|
136
138
|
renderAs?: 'default' | 'children' | boolean;
|
|
137
139
|
}
|
|
138
|
-
declare function FormBody({ className, children, renderAs }: FormBodyProps): React$1.ReactNode;
|
|
140
|
+
declare function FormBody({ className, children, renderAs }: FormBodyProps): string | number | boolean | React$1.ReactElement<any, string | React$1.JSXElementConstructor<any>> | Iterable<React$1.ReactNode> | null | undefined;
|
|
139
141
|
|
|
140
142
|
interface FormFieldProps {
|
|
141
143
|
fieldId: string;
|
|
@@ -184,13 +186,13 @@ interface FormRowProps {
|
|
|
184
186
|
children?: React.ReactNode | RendererChildrenFunction<FormRowRendererProps>;
|
|
185
187
|
renderAs?: 'default' | 'children' | boolean;
|
|
186
188
|
}
|
|
187
|
-
declare function FormRow({ row, className, children, renderAs }: FormRowProps): React$1.ReactNode;
|
|
189
|
+
declare function FormRow({ row, className, children, renderAs }: FormRowProps): string | number | boolean | React$1.ReactElement<any, string | React$1.JSXElementConstructor<any>> | Iterable<React$1.ReactNode> | null | undefined;
|
|
188
190
|
|
|
189
191
|
interface FormSubmitButtonProps {
|
|
190
192
|
className?: string;
|
|
191
193
|
children?: React__default.ReactNode | RendererChildrenFunction<FormSubmitButtonRendererProps>;
|
|
192
194
|
renderAs?: 'default' | 'children' | boolean;
|
|
193
195
|
}
|
|
194
|
-
declare function FormSubmitButton({ className, children, renderAs }: FormSubmitButtonProps): React__default.ReactNode;
|
|
196
|
+
declare function FormSubmitButton({ className, children, renderAs }: FormSubmitButtonProps): string | number | boolean | React__default.ReactElement<any, string | React__default.JSXElementConstructor<any>> | Iterable<React__default.ReactNode> | null | undefined;
|
|
195
197
|
|
|
196
198
|
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 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;
|
|
1
|
+
'use strict';var core=require('@rilaykit/core'),oe=require('react'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var oe__default=/*#__PURE__*/_interopDefault(oe);var v=class o{constructor(e,r){this.rows=[];this.rowCounter=0;this.config=e,this.formId=r||`form-${Date.now()}`;}static create(e,r){return new o(e,r)}createFormField(e){let r=this.config.getComponent(e.type);if(!r)throw new Error(`No component found with type "${e.type}"`);return {id:e.id,componentId:r.id,props:{...r.defaultProps,...e.props},validation:e.validation,conditional:e.conditional}}createRow(e,r){if(e.length===0)throw new Error("At least one field is required");if(e.length>3)throw new Error("Maximum 3 fields per row");let i=e.map(s=>this.createFormField(s));return {id:`row-${++this.rowCounter}`,fields:i,maxColumns:e.length,spacing:r?.spacing||"normal",alignment:r?.alignment||"stretch"}}addField(e){return this.addRowFields([e])}addRowFields(e,r){let i=this.createRow(e,r);return this.rows.push(i),this}addFields(e){for(let r of e)this.addField(r);return this}setId(e){return this.formId=e,this}updateField(e,r){let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);return Object.assign(i,{...r,props:{...i.props,...r.props}}),this}findField(e){for(let r of this.rows){let i=r.fields.find(s=>s.id===e);if(i)return i}return null}removeField(e){return this.rows=this.rows.map(r=>({...r,fields:r.fields.filter(i=>i.id!==e)})).filter(r=>r.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.rowCounter=0,this}clone(e){let r=new o(this.config,e||`${this.formId}-clone`);return r.rows=this.rows.map(i=>({...i,fields:i.fields.map(s=>({...s}))})),r.rowCounter=this.rowCounter,r}validate(){let e=[],r=this.getFields(),i=r.map(d=>d.id),s=i.filter((d,u)=>i.indexOf(d)!==u);s.length>0&&e.push(`Duplicate field IDs: ${s.join(", ")}`);for(let d of r)this.config.hasComponent(d.componentId)||e.push(`Component "${d.componentId}" not found for field "${d.id}"`);for(let d of this.rows)d.fields.length>3&&e.push(`Row "${d.id}" has ${d.fields.length} fields, maximum is 3`),d.fields.length===0&&e.push(`Row "${d.id}" is empty`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig()}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows,this.rowCounter=this.rows.length),this}getStats(){let e=this.getFields(),r=this.rows.map(i=>i.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:r.length>0?Math.max(...r):0,minFieldsInRow:r.length>0?Math.min(...r):0}}};function Z(o,e){return v.create(o,e)}core.ril.prototype.createForm=function(o){return v.create(this,o)};function j(o,e){switch(e.type){case "SET_VALUE":{let r={...o.values,[e.fieldId]:e.value};return {...o,values:r,isDirty:true}}case "SET_ERROR":return {...o,errors:{...o.errors,[e.fieldId]:e.errors},isValid:false};case "CLEAR_ERROR":{let r={...o.errors};return delete r[e.fieldId],{...o,errors:r}}case "MARK_TOUCHED":return {...o,touched:new Set([...o.touched,e.fieldId])};case "SET_VALIDATING":{let r=new Set(o.isValidating);return e.isValidating?r.add(e.fieldId):r.delete(e.fieldId),{...o,isValidating:r}}case "SET_SUBMITTING":return {...o,isSubmitting:e.isSubmitting};case "RESET":return {values:e.values||{},errors:{},touched:new Set,isValidating:new Set,isDirty:false,isValid:true,isSubmitting:false};case "UPDATE_VALIDATION_STATE":{let r=Object.keys(o.errors).some(i=>o.errors[i].length>0);return {...o,isValid:!r}}default:return o}}var $=oe.createContext(null);function B({children:o,formConfig:e,defaultValues:r={},onSubmit:i,onFieldChange:s,className:d}){let u={values:r,errors:{},touched:new Set,isValidating:new Set,isDirty:false,isValid:true,isSubmitting:false},[a,l]=oe.useReducer(j,u),t=oe.useRef(new Map),c=oe.useRef(i),m=oe.useRef(s);c.current=i,m.current=s;let C=oe.useCallback((n,f)=>{l({type:"SET_ERROR",fieldId:n,errors:f}),l({type:"UPDATE_VALIDATION_STATE"});},[]),P=oe.useCallback(n=>{l({type:"CLEAR_ERROR",fieldId:n}),l({type:"UPDATE_VALIDATION_STATE"});},[]),x=oe.useCallback(n=>{l({type:"MARK_TOUCHED",fieldId:n});},[]),p=oe.useCallback((n,f)=>{l({type:"SET_VALIDATING",fieldId:n,isValidating:f});},[]),T=oe.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]),y=oe.useMemo(()=>e,[e]),b=oe.useCallback(async(n,f)=>{let g=y.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 w=await g.validation.validator(K,W,g.props);w.errors.length>0?C(n,w.errors):P(n),I(w);}catch(w){let k={isValid:false,errors:[{code:"validation_error",message:w instanceof Error?w.message:"Validation error"}]};C(n,k.errors),I(k);}finally{p(n,false);}};if(_>0){let w=setTimeout(O,_);t.current.set(n,w);}else O();})},[y,a.values,a.touched,a.isDirty,C,P,p]),E=oe.useCallback(async()=>{let n=y.allFields.map(g=>b(g.id));return (await Promise.all(n)).every(g=>g.isValid)},[y,b]),A=oe.useCallback(n=>{l({type:"RESET",values:n});},[]),V=oe.useCallback(async n=>{if(n?.preventDefault(),!c.current)return true;l({type:"SET_SUBMITTING",isSubmitting:true});try{return await E()?(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,E]),h=oe.useMemo(()=>({formState:a,formConfig:y,setValue:T,setError:C,clearError:P,markFieldTouched:x,setFieldValidating:p,validateField:b,validateAllFields:E,reset:A,submit:V}),[a,y,T,C,P,x,p,b,E,A,V]);return jsxRuntime.jsx($.Provider,{value:h,children:jsxRuntime.jsx("form",{onSubmit:V,className:d,noValidate:true,children:o})})}function R(){let o=oe.useContext($);if(!o)throw new Error("useFormContext must be used within a FormProvider");return o}function ee({formConfig:o,defaultValues:e,onSubmit:r,onFieldChange:i,children:s}){let d=o instanceof v?o.build():o;return jsxRuntime.jsx(B,{formConfig:d,defaultValues:e,onSubmit:r,onFieldChange:i,children:s})}function G({fieldId:o,disabled:e=false,customProps:r={},className:i}){let{formState:s,formConfig:d,setValue:u,markFieldTouched:a,validateField:l}=R(),t=oe.useMemo(()=>d.allFields.find(h=>h.id===o),[d.allFields,o]);if(!t)throw new Error(`Field with ID "${o}" not found`);let c=oe.useMemo(()=>d.config.getComponent(t.componentId),[d.config,t.componentId]);if(!c)throw new Error(`Component with ID "${t.componentId}" not found`);let m=oe.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]),C=oe.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]),P=oe.useCallback(()=>{a(t.id),(t.validation?.validateOnBlur||t.validation?.validator)&&l(t.id);},[t.id,t.validation,a,l]),x=oe.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=oe.useMemo(()=>{if(!t.conditional||!x)return {};switch(t.conditional.action){case "disable":return {disabled:true};case "require":return {required:true};default:return {}}},[t.conditional,x]);if(!x&&t.conditional?.action==="hide")return null;let T=oe.useMemo(()=>({...c.defaultProps??{},...t.props,...r,...p}),[c.defaultProps,t.props,r,p]),y=oe.useMemo(()=>({id:t.id,props:T,value:m.value,onChange:C,onBlur:P,error:m.errors,touched:m.touched,disabled:e||p.disabled,isValidating:m.validating}),[t.id,T,m.value,C,P,m.errors,m.touched,e,p.disabled,m.validating]),b=d.renderConfig?.fieldRenderer,E=c.renderer(y),A=c.useFieldRenderer!==false,V=b&&A?b({children:E,id:t.id,error:m.errors,touched:m.touched,disabled:e||p.disabled,isValidating:m.validating,...T}):E;return jsxRuntime.jsx("div",{className:i,"data-field-id":t.id,"data-field-type":c.type,children:V})}var q=oe__default.default.memo(G);function H({row:o,className:e,children:r,renderAs:i}){let{formConfig:s}=R(),d=o.fields.map(m=>jsxRuntime.jsx(q,{fieldId:m.id},m.id));if(i==="children"||i===true){if(typeof r!="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:e,spacing:o.spacing,alignment:o.alignment};return r(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:e,spacing:o.spacing,alignment:o.alignment},t=core.resolveRendererChildren(r,l),c={...l,children:t||d};return a(c)}var J=H;function ae({className:o,children:e,renderAs:r}){let{formConfig:i}=R(),s=oe.useMemo(()=>i.rows.map(c=>jsxRuntime.jsx(J,{row:c},c.id)),[i.rows]);if(r==="children"||r===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return e({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(e,a),t={...a,children:l||s};return u(t)}function ce({className:o,children:e,renderAs:r}){let{formState:i,submit:s,formConfig:d}=R(),u={isSubmitting:i.isSubmitting,isValid:i.isValid,isDirty:i.isDirty,onSubmit:s,className:o};if(r==="children"||r===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return e(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(e,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=ee;exports.FormBody=ae;exports.FormBuilder=v;exports.FormField=G;exports.FormProvider=B;exports.FormRow=H;exports.FormSubmitButton=ce;exports.createForm=Z;exports.form=v;exports.useFormContext=R;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
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};
|
|
1
|
+
import {ril,resolveRendererChildren}from'@rilaykit/core';export{createZodValidator,ril}from'@rilaykit/core';import oe,{createContext,useMemo,useCallback,useContext,useReducer,useRef}from'react';import {jsx}from'react/jsx-runtime';var v=class o{constructor(e,r){this.rows=[];this.rowCounter=0;this.config=e,this.formId=r||`form-${Date.now()}`;}static create(e,r){return new o(e,r)}createFormField(e){let r=this.config.getComponent(e.type);if(!r)throw new Error(`No component found with type "${e.type}"`);return {id:e.id,componentId:r.id,props:{...r.defaultProps,...e.props},validation:e.validation,conditional:e.conditional}}createRow(e,r){if(e.length===0)throw new Error("At least one field is required");if(e.length>3)throw new Error("Maximum 3 fields per row");let i=e.map(s=>this.createFormField(s));return {id:`row-${++this.rowCounter}`,fields:i,maxColumns:e.length,spacing:r?.spacing||"normal",alignment:r?.alignment||"stretch"}}addField(e){return this.addRowFields([e])}addRowFields(e,r){let i=this.createRow(e,r);return this.rows.push(i),this}addFields(e){for(let r of e)this.addField(r);return this}setId(e){return this.formId=e,this}updateField(e,r){let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);return Object.assign(i,{...r,props:{...i.props,...r.props}}),this}findField(e){for(let r of this.rows){let i=r.fields.find(s=>s.id===e);if(i)return i}return null}removeField(e){return this.rows=this.rows.map(r=>({...r,fields:r.fields.filter(i=>i.id!==e)})).filter(r=>r.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.rowCounter=0,this}clone(e){let r=new o(this.config,e||`${this.formId}-clone`);return r.rows=this.rows.map(i=>({...i,fields:i.fields.map(s=>({...s}))})),r.rowCounter=this.rowCounter,r}validate(){let e=[],r=this.getFields(),i=r.map(d=>d.id),s=i.filter((d,u)=>i.indexOf(d)!==u);s.length>0&&e.push(`Duplicate field IDs: ${s.join(", ")}`);for(let d of r)this.config.hasComponent(d.componentId)||e.push(`Component "${d.componentId}" not found for field "${d.id}"`);for(let d of this.rows)d.fields.length>3&&e.push(`Row "${d.id}" has ${d.fields.length} fields, maximum is 3`),d.fields.length===0&&e.push(`Row "${d.id}" is empty`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig()}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows,this.rowCounter=this.rows.length),this}getStats(){let e=this.getFields(),r=this.rows.map(i=>i.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:r.length>0?Math.max(...r):0,minFieldsInRow:r.length>0?Math.min(...r):0}}};function Z(o,e){return v.create(o,e)}ril.prototype.createForm=function(o){return v.create(this,o)};function j(o,e){switch(e.type){case "SET_VALUE":{let r={...o.values,[e.fieldId]:e.value};return {...o,values:r,isDirty:true}}case "SET_ERROR":return {...o,errors:{...o.errors,[e.fieldId]:e.errors},isValid:false};case "CLEAR_ERROR":{let r={...o.errors};return delete r[e.fieldId],{...o,errors:r}}case "MARK_TOUCHED":return {...o,touched:new Set([...o.touched,e.fieldId])};case "SET_VALIDATING":{let r=new Set(o.isValidating);return e.isValidating?r.add(e.fieldId):r.delete(e.fieldId),{...o,isValidating:r}}case "SET_SUBMITTING":return {...o,isSubmitting:e.isSubmitting};case "RESET":return {values:e.values||{},errors:{},touched:new Set,isValidating:new Set,isDirty:false,isValid:true,isSubmitting:false};case "UPDATE_VALIDATION_STATE":{let r=Object.keys(o.errors).some(i=>o.errors[i].length>0);return {...o,isValid:!r}}default:return o}}var $=createContext(null);function B({children:o,formConfig:e,defaultValues:r={},onSubmit:i,onFieldChange:s,className:d}){let u={values:r,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 C=useCallback((n,f)=>{l({type:"SET_ERROR",fieldId:n,errors:f}),l({type:"UPDATE_VALIDATION_STATE"});},[]),P=useCallback(n=>{l({type:"CLEAR_ERROR",fieldId:n}),l({type:"UPDATE_VALIDATION_STATE"});},[]),x=useCallback(n=>{l({type:"MARK_TOUCHED",fieldId:n});},[]),p=useCallback((n,f)=>{l({type:"SET_VALIDATING",fieldId:n,isValidating:f});},[]),T=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]),y=useMemo(()=>e,[e]),b=useCallback(async(n,f)=>{let g=y.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 w=await g.validation.validator(K,W,g.props);w.errors.length>0?C(n,w.errors):P(n),I(w);}catch(w){let k={isValid:false,errors:[{code:"validation_error",message:w instanceof Error?w.message:"Validation error"}]};C(n,k.errors),I(k);}finally{p(n,false);}};if(_>0){let w=setTimeout(O,_);t.current.set(n,w);}else O();})},[y,a.values,a.touched,a.isDirty,C,P,p]),E=useCallback(async()=>{let n=y.allFields.map(g=>b(g.id));return (await Promise.all(n)).every(g=>g.isValid)},[y,b]),A=useCallback(n=>{l({type:"RESET",values:n});},[]),V=useCallback(async n=>{if(n?.preventDefault(),!c.current)return true;l({type:"SET_SUBMITTING",isSubmitting:true});try{return await E()?(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,E]),h=useMemo(()=>({formState:a,formConfig:y,setValue:T,setError:C,clearError:P,markFieldTouched:x,setFieldValidating:p,validateField:b,validateAllFields:E,reset:A,submit:V}),[a,y,T,C,P,x,p,b,E,A,V]);return jsx($.Provider,{value:h,children:jsx("form",{onSubmit:V,className:d,noValidate:true,children:o})})}function R(){let o=useContext($);if(!o)throw new Error("useFormContext must be used within a FormProvider");return o}function ee({formConfig:o,defaultValues:e,onSubmit:r,onFieldChange:i,children:s}){let d=o instanceof v?o.build():o;return jsx(B,{formConfig:d,defaultValues:e,onSubmit:r,onFieldChange:i,children:s})}function G({fieldId:o,disabled:e=false,customProps:r={},className:i}){let{formState:s,formConfig:d,setValue:u,markFieldTouched:a,validateField:l}=R(),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]),C=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]),P=useCallback(()=>{a(t.id),(t.validation?.validateOnBlur||t.validation?.validator)&&l(t.id);},[t.id,t.validation,a,l]),x=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||!x)return {};switch(t.conditional.action){case "disable":return {disabled:true};case "require":return {required:true};default:return {}}},[t.conditional,x]);if(!x&&t.conditional?.action==="hide")return null;let T=useMemo(()=>({...c.defaultProps??{},...t.props,...r,...p}),[c.defaultProps,t.props,r,p]),y=useMemo(()=>({id:t.id,props:T,value:m.value,onChange:C,onBlur:P,error:m.errors,touched:m.touched,disabled:e||p.disabled,isValidating:m.validating}),[t.id,T,m.value,C,P,m.errors,m.touched,e,p.disabled,m.validating]),b=d.renderConfig?.fieldRenderer,E=c.renderer(y),A=c.useFieldRenderer!==false,V=b&&A?b({children:E,id:t.id,error:m.errors,touched:m.touched,disabled:e||p.disabled,isValidating:m.validating,...T}):E;return jsx("div",{className:i,"data-field-id":t.id,"data-field-type":c.type,children:V})}var q=oe.memo(G);function H({row:o,className:e,children:r,renderAs:i}){let{formConfig:s}=R(),d=o.fields.map(m=>jsx(q,{fieldId:m.id},m.id));if(i==="children"||i===true){if(typeof r!="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:e,spacing:o.spacing,alignment:o.alignment};return r(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:e,spacing:o.spacing,alignment:o.alignment},t=resolveRendererChildren(r,l),c={...l,children:t||d};return a(c)}var J=H;function ae({className:o,children:e,renderAs:r}){let{formConfig:i}=R(),s=useMemo(()=>i.rows.map(c=>jsx(J,{row:c},c.id)),[i.rows]);if(r==="children"||r===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return e({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(e,a),t={...a,children:l||s};return u(t)}function ce({className:o,children:e,renderAs:r}){let{formState:i,submit:s,formConfig:d}=R(),u={isSubmitting:i.isSubmitting,isValid:i.isValid,isDirty:i.isDirty,onSubmit:s,className:o};if(r==="children"||r===true){if(typeof e!="function")throw new Error('When renderAs="children" is used, children must be a function that returns React elements');return e(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(e,u),c={...u,children:t};return l(c)}export{ee as Form,ae as FormBody,v as FormBuilder,G as FormField,B as FormProvider,H as FormRow,ce as FormSubmitButton,Z as createForm,v as form,R as useFormContext};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rilaykit/forms",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
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": "3.0.0"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"react": ">=18.0.0",
|