@rilaykit/forms 12.0.0 → 14.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 +12 -10
- package/dist/index.d.ts +12 -10
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ril, FieldValidationConfig, ConditionalBehavior, FormFieldConfig, FormFieldRow, FormValidationConfig, FormConfiguration, ComponentRendererBaseProps, FormBodyRendererProps, ValidationError, ValidationResult, MonitoringConfig, FormPerformanceMetrics, FormRowRendererProps, FormSubmitButtonRendererProps } from '@rilaykit/core';
|
|
3
|
-
import React$1 from 'react';
|
|
3
|
+
import * as React$1 from 'react';
|
|
4
|
+
import React__default from 'react';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Configuration for a form field with type safety
|
|
@@ -537,7 +538,7 @@ interface FormProps {
|
|
|
537
538
|
}
|
|
538
539
|
declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, children }: FormProps): react_jsx_runtime.JSX.Element;
|
|
539
540
|
|
|
540
|
-
declare const FormBody:
|
|
541
|
+
declare const FormBody: React__default.NamedExoticComponent<ComponentRendererBaseProps<FormBodyRendererProps>>;
|
|
541
542
|
|
|
542
543
|
interface FormFieldProps {
|
|
543
544
|
fieldId: string;
|
|
@@ -546,7 +547,7 @@ interface FormFieldProps {
|
|
|
546
547
|
className?: string;
|
|
547
548
|
forceVisible?: boolean;
|
|
548
549
|
}
|
|
549
|
-
declare const FormField:
|
|
550
|
+
declare const FormField: React__default.NamedExoticComponent<FormFieldProps>;
|
|
550
551
|
|
|
551
552
|
interface ConditionEvaluationResult {
|
|
552
553
|
visible: boolean;
|
|
@@ -649,6 +650,7 @@ interface UseFormStateProps {
|
|
|
649
650
|
}
|
|
650
651
|
declare function useFormState({ defaultValues, onFieldChange }: UseFormStateProps): {
|
|
651
652
|
formState: FormState;
|
|
653
|
+
valuesRef: React$1.MutableRefObject<Record<string, any>>;
|
|
652
654
|
setValue: (fieldId: string, value: any) => void;
|
|
653
655
|
setFieldTouched: (fieldId: string) => void;
|
|
654
656
|
setError: (fieldId: string, errors: ValidationError[]) => void;
|
|
@@ -660,13 +662,13 @@ declare function useFormState({ defaultValues, onFieldChange }: UseFormStateProp
|
|
|
660
662
|
};
|
|
661
663
|
|
|
662
664
|
interface UseFormSubmissionProps {
|
|
663
|
-
|
|
665
|
+
valuesRef: React__default.MutableRefObject<Record<string, any>>;
|
|
664
666
|
onSubmit?: (data: Record<string, any>) => void | Promise<void>;
|
|
665
667
|
validateForm: () => Promise<ValidationResult>;
|
|
666
668
|
setSubmitting: (isSubmitting: boolean) => void;
|
|
667
669
|
}
|
|
668
|
-
declare function useFormSubmission({
|
|
669
|
-
submit: (event?:
|
|
670
|
+
declare function useFormSubmission({ valuesRef, onSubmit, validateForm, setSubmitting, }: UseFormSubmissionProps): {
|
|
671
|
+
submit: (event?: React__default.FormEvent) => Promise<boolean>;
|
|
670
672
|
};
|
|
671
673
|
|
|
672
674
|
interface UseFormValidationProps {
|
|
@@ -707,12 +709,12 @@ interface FormContextValue {
|
|
|
707
709
|
validateForm: () => Promise<ValidationResult>;
|
|
708
710
|
isFormValid: () => boolean;
|
|
709
711
|
reset: (values?: Record<string, any>) => void;
|
|
710
|
-
submit: (event?:
|
|
712
|
+
submit: (event?: React__default.FormEvent) => Promise<boolean>;
|
|
711
713
|
setError: (fieldId: string, errors: ValidationError[]) => void;
|
|
712
714
|
clearError: (fieldId: string) => void;
|
|
713
715
|
}
|
|
714
716
|
interface FormProviderProps {
|
|
715
|
-
children:
|
|
717
|
+
children: React__default.ReactNode;
|
|
716
718
|
formConfig: FormConfiguration;
|
|
717
719
|
defaultValues?: Record<string, any>;
|
|
718
720
|
onSubmit?: (data: Record<string, any>) => void | Promise<void>;
|
|
@@ -725,7 +727,7 @@ declare function useFormContext(): FormContextValue;
|
|
|
725
727
|
interface FormRowProps extends ComponentRendererBaseProps<FormRowRendererProps> {
|
|
726
728
|
row: FormFieldRow;
|
|
727
729
|
}
|
|
728
|
-
declare const FormRow:
|
|
730
|
+
declare const FormRow: React__default.NamedExoticComponent<FormRowProps>;
|
|
729
731
|
|
|
730
732
|
interface FormSubmitButtonProps extends ComponentRendererBaseProps<FormSubmitButtonRendererProps> {
|
|
731
733
|
/**
|
|
@@ -734,6 +736,6 @@ interface FormSubmitButtonProps extends ComponentRendererBaseProps<FormSubmitBut
|
|
|
734
736
|
*/
|
|
735
737
|
isSubmitting?: boolean;
|
|
736
738
|
}
|
|
737
|
-
declare const FormSubmitButton:
|
|
739
|
+
declare const FormSubmitButton: React__default.NamedExoticComponent<FormSubmitButtonProps>;
|
|
738
740
|
|
|
739
741
|
export { type ConditionEvaluationResult, type FieldConfig, Form, type FormAction, FormBody, form as FormBuilder, FormField, FormProvider, FormRow, type FormState, FormSubmitButton, type UseFormConditionsProps, type UseFormConditionsReturn, type UseFormMonitoringProps, type UseFormMonitoringReturn, type UseFormStateProps, type UseFormSubmissionProps, type UseFormValidationProps, form, useConditionEvaluation, useFormConditions, useFormContext, useFormMonitoring, useFormState, useFormSubmission, useFormValidation, useMultipleConditionEvaluation };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ril, FieldValidationConfig, ConditionalBehavior, FormFieldConfig, FormFieldRow, FormValidationConfig, FormConfiguration, ComponentRendererBaseProps, FormBodyRendererProps, ValidationError, ValidationResult, MonitoringConfig, FormPerformanceMetrics, FormRowRendererProps, FormSubmitButtonRendererProps } from '@rilaykit/core';
|
|
3
|
-
import React$1 from 'react';
|
|
3
|
+
import * as React$1 from 'react';
|
|
4
|
+
import React__default from 'react';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Configuration for a form field with type safety
|
|
@@ -537,7 +538,7 @@ interface FormProps {
|
|
|
537
538
|
}
|
|
538
539
|
declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, children }: FormProps): react_jsx_runtime.JSX.Element;
|
|
539
540
|
|
|
540
|
-
declare const FormBody:
|
|
541
|
+
declare const FormBody: React__default.NamedExoticComponent<ComponentRendererBaseProps<FormBodyRendererProps>>;
|
|
541
542
|
|
|
542
543
|
interface FormFieldProps {
|
|
543
544
|
fieldId: string;
|
|
@@ -546,7 +547,7 @@ interface FormFieldProps {
|
|
|
546
547
|
className?: string;
|
|
547
548
|
forceVisible?: boolean;
|
|
548
549
|
}
|
|
549
|
-
declare const FormField:
|
|
550
|
+
declare const FormField: React__default.NamedExoticComponent<FormFieldProps>;
|
|
550
551
|
|
|
551
552
|
interface ConditionEvaluationResult {
|
|
552
553
|
visible: boolean;
|
|
@@ -649,6 +650,7 @@ interface UseFormStateProps {
|
|
|
649
650
|
}
|
|
650
651
|
declare function useFormState({ defaultValues, onFieldChange }: UseFormStateProps): {
|
|
651
652
|
formState: FormState;
|
|
653
|
+
valuesRef: React$1.MutableRefObject<Record<string, any>>;
|
|
652
654
|
setValue: (fieldId: string, value: any) => void;
|
|
653
655
|
setFieldTouched: (fieldId: string) => void;
|
|
654
656
|
setError: (fieldId: string, errors: ValidationError[]) => void;
|
|
@@ -660,13 +662,13 @@ declare function useFormState({ defaultValues, onFieldChange }: UseFormStateProp
|
|
|
660
662
|
};
|
|
661
663
|
|
|
662
664
|
interface UseFormSubmissionProps {
|
|
663
|
-
|
|
665
|
+
valuesRef: React__default.MutableRefObject<Record<string, any>>;
|
|
664
666
|
onSubmit?: (data: Record<string, any>) => void | Promise<void>;
|
|
665
667
|
validateForm: () => Promise<ValidationResult>;
|
|
666
668
|
setSubmitting: (isSubmitting: boolean) => void;
|
|
667
669
|
}
|
|
668
|
-
declare function useFormSubmission({
|
|
669
|
-
submit: (event?:
|
|
670
|
+
declare function useFormSubmission({ valuesRef, onSubmit, validateForm, setSubmitting, }: UseFormSubmissionProps): {
|
|
671
|
+
submit: (event?: React__default.FormEvent) => Promise<boolean>;
|
|
670
672
|
};
|
|
671
673
|
|
|
672
674
|
interface UseFormValidationProps {
|
|
@@ -707,12 +709,12 @@ interface FormContextValue {
|
|
|
707
709
|
validateForm: () => Promise<ValidationResult>;
|
|
708
710
|
isFormValid: () => boolean;
|
|
709
711
|
reset: (values?: Record<string, any>) => void;
|
|
710
|
-
submit: (event?:
|
|
712
|
+
submit: (event?: React__default.FormEvent) => Promise<boolean>;
|
|
711
713
|
setError: (fieldId: string, errors: ValidationError[]) => void;
|
|
712
714
|
clearError: (fieldId: string) => void;
|
|
713
715
|
}
|
|
714
716
|
interface FormProviderProps {
|
|
715
|
-
children:
|
|
717
|
+
children: React__default.ReactNode;
|
|
716
718
|
formConfig: FormConfiguration;
|
|
717
719
|
defaultValues?: Record<string, any>;
|
|
718
720
|
onSubmit?: (data: Record<string, any>) => void | Promise<void>;
|
|
@@ -725,7 +727,7 @@ declare function useFormContext(): FormContextValue;
|
|
|
725
727
|
interface FormRowProps extends ComponentRendererBaseProps<FormRowRendererProps> {
|
|
726
728
|
row: FormFieldRow;
|
|
727
729
|
}
|
|
728
|
-
declare const FormRow:
|
|
730
|
+
declare const FormRow: React__default.NamedExoticComponent<FormRowProps>;
|
|
729
731
|
|
|
730
732
|
interface FormSubmitButtonProps extends ComponentRendererBaseProps<FormSubmitButtonRendererProps> {
|
|
731
733
|
/**
|
|
@@ -734,6 +736,6 @@ interface FormSubmitButtonProps extends ComponentRendererBaseProps<FormSubmitBut
|
|
|
734
736
|
*/
|
|
735
737
|
isSubmitting?: boolean;
|
|
736
738
|
}
|
|
737
|
-
declare const FormSubmitButton:
|
|
739
|
+
declare const FormSubmitButton: React__default.NamedExoticComponent<FormSubmitButtonProps>;
|
|
738
740
|
|
|
739
741
|
export { type ConditionEvaluationResult, type FieldConfig, Form, type FormAction, FormBody, form as FormBuilder, FormField, FormProvider, FormRow, type FormState, FormSubmitButton, type UseFormConditionsProps, type UseFormConditionsReturn, type UseFormMonitoringProps, type UseFormMonitoringReturn, type UseFormStateProps, type UseFormSubmissionProps, type UseFormValidationProps, form, useConditionEvaluation, useFormConditions, useFormContext, useFormMonitoring, useFormState, useFormSubmission, useFormValidation, useMultipleConditionEvaluation };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var xe=require('react'),core=require('@rilaykit/core'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var xe__default=/*#__PURE__*/_interopDefault(xe);var E=class o{constructor(e,r){this.rows=[];this.idGenerator=new core.IdGenerator;this.config=e,this.formId=r||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,r){return new o(e,r)}createFormField(e){let r=this.config.getComponent(e.type);if(!r)throw new Error(`No component found with type "${e.type}"`);let t;return (r.validation||e.validation)&&(t={validateOnChange:e.validation?.validateOnChange??r.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??r.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??r.validation?.debounceMs,validate:(()=>{let i=r.validation?.validate,n=e.validation?.validate;if(!i)return n;if(!n)return i;let l=Array.isArray(i)?i:[i],u=Array.isArray(n)?n:[n];return [...l,...u]})()}),{id:e.id||this.idGenerator.next("field"),componentId:r.id,props:{...r.defaultProps,...e.props},validation:t,conditions:e.conditions}}createRow(e){if(e.length===0)throw new Error("At least one field is required");if(e.length>3)throw new Error("Maximum 3 fields per row");let r=e.map(t=>this.createFormField(t));return {id:this.idGenerator.next("row"),fields:r,maxColumns:e.length}}add(...e){let r,t=false;if(e.length===1&&Array.isArray(e[0])?(r=e[0],t=true):r=e,r.length===0)throw new Error("At least one field is required");if(t&&r.length>3)throw new Error("Maximum 3 fields per row");if(r.length===1){let i=this.createRow(r);return this.rows.push(i),this}if(r.length<=3){let i=this.createRow(r);return this.rows.push(i),this}for(let i of r){let n=this.createRow([i]);this.rows.push(n);}return this}addSeparateRows(e){for(let r of e)this.add(r);return this}setId(e){return this.formId=e,this}updateField(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);return Object.assign(t,{...r,props:{...t.props,...r.props}}),this}findField(e){for(let r of this.rows){let t=r.fields.find(i=>i.id===e);if(t)return t}return null}removeField(e){return this.rows=this.rows.map(r=>({...r,fields:r.fields.filter(t=>t.id!==e)})).filter(r=>r.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.idGenerator.reset(),this}setValidation(e){return this.formValidation=e,this}addFieldValidation(e,r){console.warn("addFieldValidation is deprecated. Use updateField with validation.validate property instead.");let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let i={...t.validation,...r};return this.updateField(e,{validation:i})}addFieldConditions(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let i={...t.conditions,...r};return this.updateField(e,{conditions:i})}clone(e){let r=new o(this.config,e||`${this.formId}-clone`);return r.rows=core.deepClone(this.rows),r}validate(){let e=[],r=this.getFields(),t=r.map(i=>i.id);try{core.ensureUnique(t,"field");}catch(i){e.push(i instanceof Error?i.message:String(i));}for(let i of r)this.config.hasComponent(i.componentId)||e.push(`Component "${i.componentId}" not found for field "${i.id}"`);for(let i of this.rows)i.fields.length>3&&e.push(`Row "${i.id}" has ${i.fields.length} fields, maximum is 3`),i.fields.length===0&&e.push(`Row "${i.id}" is empty`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig(),validation:this.formValidation}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows),this}getStats(){let e=this.getFields(),r=this.rows.map(t=>t.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:r.length>0?Math.max(...r):0,minFieldsInRow:r.length>0?Math.min(...r):0}}};function Ge(o,e={},r={}){return xe.useMemo(()=>{if(!o)return {visible:r.visible??true,disabled:r.disabled??false,required:r.required??false,readonly:r.readonly??false};let t=i=>{try{return i&&typeof i=="object"&&"build"in i?core.evaluateCondition(i.build(),e):core.evaluateCondition(i,e)}catch(n){return console.warn("Error evaluating condition:",n),false}};return {visible:o.visible?t(o.visible):r.visible??true,disabled:o.disabled?t(o.disabled):r.disabled??false,required:o.required?t(o.required):r.required??false,readonly:o.readonly?t(o.readonly):r.readonly??false}},[o,e,r])}function H(o,e={}){return xe.useMemo(()=>{let r={};for(let[t,i]of Object.entries(o))if(r[t]={visible:true,disabled:false,required:false,readonly:false},i){let n=l=>{try{return l&&typeof l=="object"&&"build"in l?core.evaluateCondition(l.build(),e):core.evaluateCondition(l,e)}catch(u){return console.warn(`Error evaluating condition for field ${t}:`,u),false}};r[t]={visible:i.visible?n(i.visible):true,disabled:i.disabled?n(i.disabled):false,required:i.required?n(i.required):false,readonly:i.readonly?n(i.readonly):false};}return r},[o,e])}function W({formConfig:o,formValues:e}){let r=xe.useMemo(()=>{let f={};for(let s of o.allFields)s.conditions&&(f[s.id]=s.conditions);return f},[o.allFields]),t=xe.useMemo(()=>Object.keys(r).length>0,[r]),i=H(t?r:{},t?e:{}),n=xe.useCallback(f=>i[f],[i]),l=xe.useCallback(f=>{let s=i[f];return s?s.visible:true},[i]),u=xe.useCallback(f=>{let s=i[f];return s?s.disabled:false},[i]),F=xe.useCallback(f=>{let s=i[f];return s?s.required:false},[i]),g=xe.useCallback(f=>{let s=i[f];return s?s.readonly:false},[i]);return xe.useMemo(()=>({fieldConditions:i,hasConditionalFields:t,getFieldCondition:n,isFieldVisible:l,isFieldDisabled:u,isFieldRequired:F,isFieldReadonly:g}),[i,t,n,l,u,F,g])}function ce(o,e){switch(e.type){case "SET_VALUE":return {...o,values:{...o.values,[e.fieldId]:e.value},isDirty:true};case "SET_FIELD_ERRORS":return {...o,errors:{...o.errors,[e.fieldId]:e.errors}};case "SET_FIELD_VALIDATION_STATE":return {...o,validationState:{...o.validationState,[e.fieldId]:e.state}};case "SET_FIELD_TOUCHED":return {...o,touched:{...o.touched,[e.fieldId]:true}};case "SET_SUBMITTING":return {...o,isSubmitting:e.isSubmitting};case "RESET":return {values:e.values||{},errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false};default:return o}}function J({defaultValues:o={},onFieldChange:e}){let r={values:o,errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false},[t,i]=xe.useReducer(ce,r),n=xe.useRef(e);n.current=e;let l=xe.useCallback((d,p)=>{i({type:"SET_VALUE",fieldId:d,value:p}),n.current?.(d,p,{...t.values,[d]:p});},[t.values]),u=xe.useCallback(d=>{i({type:"SET_FIELD_TOUCHED",fieldId:d});},[]),F=xe.useCallback((d,p)=>{i({type:"SET_FIELD_ERRORS",fieldId:d,errors:p});},[]),g=xe.useCallback(d=>{i({type:"SET_FIELD_ERRORS",fieldId:d,errors:[]});},[]),f=xe.useCallback((d,p)=>{i({type:"SET_FIELD_VALIDATION_STATE",fieldId:d,state:p});},[]),s=xe.useCallback(d=>{i({type:"SET_SUBMITTING",isSubmitting:d});},[]),m=xe.useCallback(d=>{i({type:"RESET",values:d});},[]),c=xe.useCallback(()=>{let d=Object.values(t.errors).some(a=>a.length>0),p=Object.values(t.validationState).some(a=>a==="invalid");return !d&&!p},[t.errors,t.validationState]);return {formState:t,setValue:l,setFieldTouched:u,setError:F,clearError:g,setFieldValidationState:f,setSubmitting:s,reset:m,isFormValid:c}}function Q({formState:o,onSubmit:e,validateForm:r,setSubmitting:t}){let i=xe.useRef(e);return i.current=e,{submit:xe.useCallback(async l=>{l?.preventDefault();try{return t(!0),(await r()).isValid?(i.current&&await i.current(o.values),!0):!1}catch(u){return console.error("Error during form submission:",u),false}finally{t(false);}},[o.values,r,t])}}function B(){return {isValid:true,errors:[]}}function K({formConfig:o,formState:e,conditionsHelpers:r,setFieldValidationState:t,setError:i}){let n=xe.useRef(o),l=xe.useRef(r),u=xe.useRef(t),F=xe.useRef(i);n.current=o,l.current=r,u.current=t,F.current=i;let g=xe.useCallback(async(s,m)=>{let c=n.current.allFields.find(a=>a.id===s);if(!c)return B();if(!l.current.isFieldVisible(s))return F.current(s,[]),u.current(s,"valid"),B();if(!c.validation||!core.hasUnifiedValidation(c.validation))return F.current(s,[]),u.current(s,"valid"),B();let d=m!==void 0?m:e.values[s],p=core.createValidationContext({fieldId:s,formId:n.current.id,allFormData:{...e.values,[s]:d}});u.current(s,"validating");try{let a=await core.validateWithUnifiedConfig(c.validation,d,p),h=l.current.isFieldRequired(s),v=d==null||d==="";if(h&&v&&!a.errors.some(C=>C.code==="REQUIRED"||C.message.toLowerCase().includes("required"))){let C={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...a.errors]};return F.current(s,C.errors),u.current(s,"invalid"),C}return F.current(s,a.errors),u.current(s,a.isValid?"valid":"invalid"),a}catch(a){let h={isValid:false,errors:[{message:a instanceof Error?a.message:"Validation failed",code:"VALIDATION_ERROR"}]};return F.current(s,h.errors),u.current(s,"invalid"),h}},[e.values]),f=xe.useCallback(async()=>{let s=n.current.allFields.filter(a=>{let h=l.current.isFieldVisible(a.id),v=a.validation&&core.hasUnifiedValidation(a.validation);return h&&v}),m=n.current.allFields.filter(a=>!l.current.isFieldVisible(a.id));for(let a of m)F.current(a.id,[]),u.current(a.id,"valid");let c=await Promise.all(s.map(a=>g(a.id))),d=c.some(a=>!a.isValid),p=B();if(n.current.validation&&core.hasUnifiedValidation(n.current.validation)){let a=Object.keys(e.values).reduce((v,R)=>(l.current.isFieldVisible(R)&&(v[R]=e.values[R]),v),{}),h=core.createValidationContext({formId:n.current.id,allFormData:a});try{p=await core.validateFormWithUnifiedConfig(n.current.validation,a,h);}catch(v){p={isValid:false,errors:[{message:v instanceof Error?v.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!d&&p.isValid,errors:[...c.flatMap(a=>a.errors),...p.errors]}},[e.values,g]);return {validateField:g,validateForm:f}}function Re({formConfig:o,enabled:e=true}){let r=core.getGlobalMonitor(),t=xe.useRef(null),i=xe.useRef(0),n=xe.useRef(0);xe.useEffect(()=>{r&&e&&(t.current=r.getProfiler());},[r,e]);let l=xe.useCallback(m=>{if(!r||!e)return;i.current++;let c={formId:o.id,fieldCount:o.allFields.length,timestamp:Date.now(),duration:0,renderDuration:0,validationDuration:0,validationErrors:0,renderCount:m||i.current};r.track("component_render",`form_${o.id}`,{formId:o.id,fieldCount:o.allFields.length,renderCount:i.current},c,"low");},[r,e,o.id,o.allFields.length]),u=xe.useCallback((m,c)=>{if(!r||!e)return;let d=t.current?.getMetrics(`form_validation_${o.id}`),p={formId:o.id,fieldCount:c||o.allFields.length,timestamp:Date.now(),duration:d?.duration||0,renderDuration:0,validationDuration:d?.duration||0,validationErrors:m,renderCount:i.current};r.track("form_validation",`form_${o.id}`,{formId:o.id,validationErrors:m,fieldCount:c||o.allFields.length},p,m>0?"medium":"low");},[r,e,o.id,o.allFields.length]),F=xe.useCallback((m,c)=>{if(!r||!e)return;let d=t.current?.getMetrics(`form_submission_${o.id}`),p={formId:o.id,fieldCount:c||o.allFields.length,timestamp:Date.now(),duration:d?.duration||0,renderDuration:0,validationDuration:0,validationErrors:m?0:1,renderCount:i.current};r.track("form_submission",`form_${o.id}`,{formId:o.id,success:m,fieldCount:c||o.allFields.length,fieldChanges:n.current},p,m?"low":"high");},[r,e,o.id,o.allFields.length]),g=xe.useCallback((m,c)=>{!r||!e||(n.current++,r.track("component_update",`field_${m}`,{formId:o.id,fieldId:m,componentType:c,changeCount:n.current},void 0,"low"));},[r,e,o.id]),f=xe.useCallback(m=>{!t.current||!e||t.current.start(m,{formId:o.id,renderCount:i.current});},[e,o.id]),s=xe.useCallback(m=>{if(!t.current||!e)return null;let c=t.current.end(m);return c?{...c,formId:o.id,fieldCount:o.allFields.length,renderDuration:c.duration,validationDuration:0,validationErrors:0}:null},[e,o.id,o.allFields.length]);return {trackFormRender:l,trackFormValidation:u,trackFormSubmission:F,trackFieldChange:g,startPerformanceTracking:f,endPerformanceTracking:s}}var Y=xe.createContext(null);function $({children:o,formConfig:e,defaultValues:r={},onSubmit:t,onFieldChange:i,className:n}){let l=xe.useRef(e.id),{formState:u,setValue:F,setFieldTouched:g,reset:f,setError:s,clearError:m,setFieldValidationState:c,setSubmitting:d,isFormValid:p}=J({defaultValues:r,onFieldChange:i}),{fieldConditions:a,hasConditionalFields:h,getFieldCondition:v,isFieldVisible:R,isFieldDisabled:C,isFieldRequired:V,isFieldReadonly:x}=W({formConfig:e,formValues:u.values}),P=xe.useMemo(()=>({hasConditionalFields:h,getFieldCondition:v,isFieldVisible:R,isFieldDisabled:C,isFieldRequired:V,isFieldReadonly:x}),[h,v,R,C,V,x]),{validateField:D,validateForm:b}=K({formConfig:e,formState:u,conditionsHelpers:P,setFieldValidationState:c,setError:s}),{submit:I}=Q({formState:u,onSubmit:t,validateForm:b,setSubmitting:d});xe.useEffect(()=>{(l.current===null||e.id!==l.current)&&(l.current=e.id,f(r));},[e.id,f]);let N=xe.useMemo(()=>e,[e]),se=xe.useMemo(()=>({formState:u,formConfig:N,fieldConditions:a,conditionsHelpers:P,setValue:F,setFieldTouched:g,validateField:D,validateForm:b,isFormValid:p,reset:f,submit:I,setError:s,clearError:m}),[u,N,a,P,F,g,D,b,p,f,I,s,m]);return jsxRuntime.jsx(Y.Provider,{value:se,children:jsxRuntime.jsx("form",{onSubmit:I,className:n,noValidate:true,children:o})})}function y(){let o=xe.useContext(Y);if(!o)throw new Error("useFormContext must be used within a FormProvider");return o}function Se({formConfig:o,defaultValues:e,onSubmit:r,onFieldChange:t,children:i}){let n=xe.useMemo(()=>o instanceof E?o.build():o,[o]);return jsxRuntime.jsx($,{formConfig:n,defaultValues:e,onSubmit:r,onFieldChange:t,children:i})}var L=xe__default.default.memo(function({fieldId:e,disabled:r=false,customProps:t={},className:i,forceVisible:n=false}){let{formState:l,formConfig:u,setValue:F,setFieldTouched:g,validateField:f,conditionsHelpers:s}=y(),m=u.allFields.find(b=>b.id===e);if(!m)throw new Error(`Field with ID "${e}" not found`);let c=u.config.getComponent(m.componentId);if(!c)throw new Error(`Component with ID "${m.componentId}" not found`);let d=xe.useMemo(()=>({value:l.values[e],errors:l.errors[e]||[],validationState:l.validationState[e]||"idle",isTouched:l.touched[e]||false}),[l.values[e],l.errors[e],l.validationState[e],l.touched[e]]),p=d.validationState==="validating",a=xe.useMemo(()=>({isVisible:n||s.isFieldVisible(e),isFieldDisabled:r||s.isFieldDisabled(e),isFieldRequired:s.isFieldRequired(e),isFieldReadonly:s.isFieldReadonly(e)}),[n,e,r,s,l.values]);if(!a.isVisible)return null;let h=xe.useCallback(async b=>{F(e,b),(m.validation?.validateOnChange||d.isTouched)&&await f(e,b);},[e,F,f,m.validation?.validateOnChange,d.isTouched]),v=xe.useCallback(async()=>{d.isTouched||g(e),m.validation?.validateOnBlur!==false&&await f(e);},[e,d.isTouched,g,f,m.validation?.validateOnBlur]),R=xe.useMemo(()=>({...c.defaultProps??{},...m.props,...t,disabled:a.isFieldDisabled,required:a.isFieldRequired,readOnly:a.isFieldReadonly}),[c.defaultProps,m.props,t,a.isFieldDisabled,a.isFieldRequired,a.isFieldReadonly]),C=xe.useMemo(()=>({id:e,props:R,value:d.value,onChange:h,onBlur:v,disabled:a.isFieldDisabled,error:d.errors,isValidating:p,touched:d.isTouched}),[e,R,d.value,h,v,a.isFieldDisabled,d.errors,p,d.isTouched]),V=c.renderer(C),x=u.renderConfig?.fieldRenderer,P=c.useFieldRenderer!==false,D=x&&P?x({children:V,id:e,...R,error:d.errors,isValidating:p,touched:d.isTouched}):V;return jsxRuntime.jsx("div",{className:i,"data-field-id":e,"data-field-type":c.type,"data-field-visible":a.isVisible,"data-field-disabled":a.isFieldDisabled,"data-field-required":a.isFieldRequired,"data-field-readonly":a.isFieldReadonly,children:D})});var ie=xe__default.default.memo(function({row:e,className:r,...t}){let{formConfig:i}=y(),n=xe.useMemo(()=>e.fields.map(u=>jsxRuntime.jsx(L,{fieldId:u.id},u.id)),[e.fields]),l=xe.useMemo(()=>({row:e,children:n,className:r}),[e,n,r]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormRow",renderer:i.renderConfig?.rowRenderer,props:l,...t,children:n})}),oe=ie;var Be=xe__default.default.memo(function({className:e,...r}){let{formConfig:t}=y(),i=xe.useMemo(()=>t.rows.map(l=>jsxRuntime.jsx(oe,{row:l},l.id)),[t.rows]),n=xe.useMemo(()=>({formConfig:t,children:i,className:e}),[t,i,e]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormBody",renderer:t.renderConfig?.bodyRenderer,props:n,...r,children:i})});var Ue=xe__default.default.memo(function({className:e,isSubmitting:r,...t}){let{formState:i,submit:n,formConfig:l}=y(),u=xe.useMemo(()=>({isSubmitting:r??i.isSubmitting,onSubmit:n,className:e}),[r,i.isSubmitting,n,e]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormSubmitButton",renderer:l.renderConfig?.submitButtonRenderer,props:u,...t})});exports.Form=Se;exports.FormBody=Be;exports.FormBuilder=E;exports.FormField=L;exports.FormProvider=$;exports.FormRow=ie;exports.FormSubmitButton=Ue;exports.form=E;exports.useConditionEvaluation=Ge;exports.useFormConditions=W;exports.useFormContext=y;exports.useFormMonitoring=Re;exports.useFormState=J;exports.useFormSubmission=Q;exports.useFormValidation=K;exports.useMultipleConditionEvaluation=H;
|
|
1
|
+
'use strict';var Pe=require('react'),core=require('@rilaykit/core'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var Pe__default=/*#__PURE__*/_interopDefault(Pe);var E=class o{constructor(e,r){this.rows=[];this.idGenerator=new core.IdGenerator;this.config=e,this.formId=r||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,r){return new o(e,r)}createFormField(e){let r=this.config.getComponent(e.type);if(!r)throw new Error(`No component found with type "${e.type}"`);let t;return (r.validation||e.validation)&&(t={validateOnChange:e.validation?.validateOnChange??r.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??r.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??r.validation?.debounceMs,validate:(()=>{let i=r.validation?.validate,s=e.validation?.validate;if(!i)return s;if(!s)return i;let a=Array.isArray(i)?i:[i],l=Array.isArray(s)?s:[s];return [...a,...l]})()}),{id:e.id||this.idGenerator.next("field"),componentId:r.id,props:{...r.defaultProps,...e.props},validation:t,conditions:e.conditions}}createRow(e){if(e.length===0)throw new Error("At least one field is required");if(e.length>3)throw new Error("Maximum 3 fields per row");let r=e.map(t=>this.createFormField(t));return {id:this.idGenerator.next("row"),fields:r,maxColumns:e.length}}add(...e){let r,t=false;if(e.length===1&&Array.isArray(e[0])?(r=e[0],t=true):r=e,r.length===0)throw new Error("At least one field is required");if(t&&r.length>3)throw new Error("Maximum 3 fields per row");if(r.length===1){let i=this.createRow(r);return this.rows.push(i),this}if(r.length<=3){let i=this.createRow(r);return this.rows.push(i),this}for(let i of r){let s=this.createRow([i]);this.rows.push(s);}return this}addSeparateRows(e){for(let r of e)this.add(r);return this}setId(e){return this.formId=e,this}updateField(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);return Object.assign(t,{...r,props:{...t.props,...r.props}}),this}findField(e){for(let r of this.rows){let t=r.fields.find(i=>i.id===e);if(t)return t}return null}removeField(e){return this.rows=this.rows.map(r=>({...r,fields:r.fields.filter(t=>t.id!==e)})).filter(r=>r.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.idGenerator.reset(),this}setValidation(e){return this.formValidation=e,this}addFieldValidation(e,r){console.warn("addFieldValidation is deprecated. Use updateField with validation.validate property instead.");let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let i={...t.validation,...r};return this.updateField(e,{validation:i})}addFieldConditions(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let i={...t.conditions,...r};return this.updateField(e,{conditions:i})}clone(e){let r=new o(this.config,e||`${this.formId}-clone`);return r.rows=core.deepClone(this.rows),r}validate(){let e=[],r=this.getFields(),t=r.map(i=>i.id);try{core.ensureUnique(t,"field");}catch(i){e.push(i instanceof Error?i.message:String(i));}for(let i of r)this.config.hasComponent(i.componentId)||e.push(`Component "${i.componentId}" not found for field "${i.id}"`);for(let i of this.rows)i.fields.length>3&&e.push(`Row "${i.id}" has ${i.fields.length} fields, maximum is 3`),i.fields.length===0&&e.push(`Row "${i.id}" is empty`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig(),validation:this.formValidation}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows),this}getStats(){let e=this.getFields(),r=this.rows.map(t=>t.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:r.length>0?Math.max(...r):0,minFieldsInRow:r.length>0?Math.min(...r):0}}};function He(o,e={},r={}){return Pe.useMemo(()=>{if(!o)return {visible:r.visible??true,disabled:r.disabled??false,required:r.required??false,readonly:r.readonly??false};let t=i=>{try{return i&&typeof i=="object"&&"build"in i?core.evaluateCondition(i.build(),e):core.evaluateCondition(i,e)}catch(s){return console.warn("Error evaluating condition:",s),false}};return {visible:o.visible?t(o.visible):r.visible??true,disabled:o.disabled?t(o.disabled):r.disabled??false,required:o.required?t(o.required):r.required??false,readonly:o.readonly?t(o.readonly):r.readonly??false}},[o,e,r])}function J(o,e={}){return Pe.useMemo(()=>{let r={};for(let[t,i]of Object.entries(o))if(r[t]={visible:true,disabled:false,required:false,readonly:false},i){let s=a=>{try{return a&&typeof a=="object"&&"build"in a?core.evaluateCondition(a.build(),e):core.evaluateCondition(a,e)}catch(l){return console.warn(`Error evaluating condition for field ${t}:`,l),false}};r[t]={visible:i.visible?s(i.visible):true,disabled:i.disabled?s(i.disabled):false,required:i.required?s(i.required):false,readonly:i.readonly?s(i.readonly):false};}return r},[o,e])}function Q({formConfig:o,formValues:e}){let r=Pe.useMemo(()=>{let p={};for(let d of o.allFields)d.conditions&&(p[d.id]=d.conditions);return p},[o.allFields]),t=Pe.useMemo(()=>Object.keys(r).length>0,[r]),i=J(t?r:{},t?e:{}),s=Pe.useCallback(p=>i[p],[i]),a=Pe.useCallback(p=>{let d=i[p];return d?d.visible:true},[i]),l=Pe.useCallback(p=>{let d=i[p];return d?d.disabled:false},[i]),F=Pe.useCallback(p=>{let d=i[p];return d?d.required:false},[i]),g=Pe.useCallback(p=>{let d=i[p];return d?d.readonly:false},[i]);return Pe.useMemo(()=>({fieldConditions:i,hasConditionalFields:t,getFieldCondition:s,isFieldVisible:a,isFieldDisabled:l,isFieldRequired:F,isFieldReadonly:g}),[i,t,s,a,l,F,g])}function fe(o,e){switch(e.type){case "SET_VALUE":return {...o,values:{...o.values,[e.fieldId]:e.value},isDirty:true};case "SET_FIELD_ERRORS":return {...o,errors:{...o.errors,[e.fieldId]:e.errors}};case "SET_FIELD_VALIDATION_STATE":return {...o,validationState:{...o.validationState,[e.fieldId]:e.state}};case "SET_FIELD_TOUCHED":return {...o,touched:{...o.touched,[e.fieldId]:true}};case "SET_SUBMITTING":return {...o,isSubmitting:e.isSubmitting};case "RESET":return {values:e.values||{},errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false};default:return o}}function z({defaultValues:o={},onFieldChange:e}){let r={values:o,errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false},[t,i]=Pe.useReducer(fe,r),s=Pe.useRef(e);s.current=e;let a=Pe.useRef(o);a.current=t.values;let l=Pe.useCallback((c,n)=>{let v={...a.current,[c]:n};a.current=v,i({type:"SET_VALUE",fieldId:c,value:n}),s.current?.(c,n,v);},[]),F=Pe.useCallback(c=>{i({type:"SET_FIELD_TOUCHED",fieldId:c});},[]),g=Pe.useCallback((c,n)=>{i({type:"SET_FIELD_ERRORS",fieldId:c,errors:n});},[]),p=Pe.useCallback(c=>{i({type:"SET_FIELD_ERRORS",fieldId:c,errors:[]});},[]),d=Pe.useCallback((c,n)=>{i({type:"SET_FIELD_VALIDATION_STATE",fieldId:c,state:n});},[]),u=Pe.useCallback(c=>{i({type:"SET_SUBMITTING",isSubmitting:c});},[]),m=Pe.useCallback(c=>{let n=c||{};a.current=n,i({type:"RESET",values:n});},[]),f=Pe.useCallback(()=>{let c=Object.values(t.errors).some(v=>v.length>0),n=Object.values(t.validationState).some(v=>v==="invalid");return !c&&!n},[t.errors,t.validationState]);return {formState:t,valuesRef:a,setValue:l,setFieldTouched:F,setError:g,clearError:p,setFieldValidationState:d,setSubmitting:u,reset:m,isFormValid:f}}function K({valuesRef:o,onSubmit:e,validateForm:r,setSubmitting:t}){let i=Pe.useRef(e);return i.current=e,{submit:Pe.useCallback(async a=>{a?.preventDefault();try{return t(!0),(await r()).isValid?(i.current&&await i.current(o.current),!0):!1}catch(l){return console.error("Error during form submission:",l),false}finally{t(false);}},[o,r,t])}}function B(){return {isValid:true,errors:[]}}function Z({formConfig:o,formState:e,conditionsHelpers:r,setFieldValidationState:t,setError:i}){let s=Pe.useRef(o),a=Pe.useRef(r),l=Pe.useRef(t),F=Pe.useRef(i);s.current=o,a.current=r,l.current=t,F.current=i;let g=Pe.useCallback(async(d,u)=>{let m=s.current.allFields.find(n=>n.id===d);if(!m)return B();if(!a.current.isFieldVisible(d))return F.current(d,[]),l.current(d,"valid"),B();if(!m.validation||!core.hasUnifiedValidation(m.validation))return F.current(d,[]),l.current(d,"valid"),B();let f=u!==void 0?u:e.values[d],c=core.createValidationContext({fieldId:d,formId:s.current.id,allFormData:{...e.values,[d]:f}});l.current(d,"validating");try{let n=await core.validateWithUnifiedConfig(m.validation,f,c),v=a.current.isFieldRequired(d),h=f==null||f==="";if(v&&h&&!n.errors.some(C=>C.code==="REQUIRED"||C.message.toLowerCase().includes("required"))){let C={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...n.errors]};return F.current(d,C.errors),l.current(d,"invalid"),C}return F.current(d,n.errors),l.current(d,n.isValid?"valid":"invalid"),n}catch(n){let v={isValid:false,errors:[{message:n instanceof Error?n.message:"Validation failed",code:"VALIDATION_ERROR"}]};return F.current(d,v.errors),l.current(d,"invalid"),v}},[e.values]),p=Pe.useCallback(async()=>{let d=s.current.allFields.filter(n=>{let v=a.current.isFieldVisible(n.id),h=n.validation&&core.hasUnifiedValidation(n.validation);return v&&h}),u=s.current.allFields.filter(n=>!a.current.isFieldVisible(n.id));for(let n of u)F.current(n.id,[]),l.current(n.id,"valid");let m=await Promise.all(d.map(n=>g(n.id))),f=m.some(n=>!n.isValid),c=B();if(s.current.validation&&core.hasUnifiedValidation(s.current.validation)){let n=Object.keys(e.values).reduce((h,R)=>(a.current.isFieldVisible(R)&&(h[R]=e.values[R]),h),{}),v=core.createValidationContext({formId:s.current.id,allFormData:n});try{c=await core.validateFormWithUnifiedConfig(s.current.validation,n,v);}catch(h){c={isValid:false,errors:[{message:h instanceof Error?h.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!f&&c.isValid,errors:[...m.flatMap(n=>n.errors),...c.errors]}},[e.values,g]);return {validateField:g,validateForm:p}}function Ce({formConfig:o,enabled:e=true}){let r=core.getGlobalMonitor(),t=Pe.useRef(null),i=Pe.useRef(0),s=Pe.useRef(0);Pe.useEffect(()=>{r&&e&&(t.current=r.getProfiler());},[r,e]);let a=Pe.useCallback(u=>{if(!r||!e)return;i.current++;let m={formId:o.id,fieldCount:o.allFields.length,timestamp:Date.now(),duration:0,renderDuration:0,validationDuration:0,validationErrors:0,renderCount:u||i.current};r.track("component_render",`form_${o.id}`,{formId:o.id,fieldCount:o.allFields.length,renderCount:i.current},m,"low");},[r,e,o.id,o.allFields.length]),l=Pe.useCallback((u,m)=>{if(!r||!e)return;let f=t.current?.getMetrics(`form_validation_${o.id}`),c={formId:o.id,fieldCount:m||o.allFields.length,timestamp:Date.now(),duration:f?.duration||0,renderDuration:0,validationDuration:f?.duration||0,validationErrors:u,renderCount:i.current};r.track("form_validation",`form_${o.id}`,{formId:o.id,validationErrors:u,fieldCount:m||o.allFields.length},c,u>0?"medium":"low");},[r,e,o.id,o.allFields.length]),F=Pe.useCallback((u,m)=>{if(!r||!e)return;let f=t.current?.getMetrics(`form_submission_${o.id}`),c={formId:o.id,fieldCount:m||o.allFields.length,timestamp:Date.now(),duration:f?.duration||0,renderDuration:0,validationDuration:0,validationErrors:u?0:1,renderCount:i.current};r.track("form_submission",`form_${o.id}`,{formId:o.id,success:u,fieldCount:m||o.allFields.length,fieldChanges:s.current},c,u?"low":"high");},[r,e,o.id,o.allFields.length]),g=Pe.useCallback((u,m)=>{!r||!e||(s.current++,r.track("component_update",`field_${u}`,{formId:o.id,fieldId:u,componentType:m,changeCount:s.current},void 0,"low"));},[r,e,o.id]),p=Pe.useCallback(u=>{!t.current||!e||t.current.start(u,{formId:o.id,renderCount:i.current});},[e,o.id]),d=Pe.useCallback(u=>{if(!t.current||!e)return null;let m=t.current.end(u);return m?{...m,formId:o.id,fieldCount:o.allFields.length,renderDuration:m.duration,validationDuration:0,validationErrors:0}:null},[e,o.id,o.allFields.length]);return {trackFormRender:a,trackFormValidation:l,trackFormSubmission:F,trackFieldChange:g,startPerformanceTracking:p,endPerformanceTracking:d}}var re=Pe.createContext(null);function L({children:o,formConfig:e,defaultValues:r={},onSubmit:t,onFieldChange:i,className:s}){let a=Pe.useRef(e.id),{formState:l,valuesRef:F,setValue:g,setFieldTouched:p,reset:d,setError:u,clearError:m,setFieldValidationState:f,setSubmitting:c,isFormValid:n}=z({defaultValues:r,onFieldChange:i}),{fieldConditions:v,hasConditionalFields:h,getFieldCondition:R,isFieldVisible:C,isFieldDisabled:S,isFieldRequired:x,isFieldReadonly:D}=Q({formConfig:e,formValues:l.values}),P=Pe.useMemo(()=>({hasConditionalFields:h,getFieldCondition:R,isFieldVisible:C,isFieldDisabled:S,isFieldRequired:x,isFieldReadonly:D}),[h,R,C,S,x,D]),{validateField:w,validateForm:I}=Z({formConfig:e,formState:l,conditionsHelpers:P,setFieldValidationState:f,setError:u}),{submit:O}=K({valuesRef:F,onSubmit:t,validateForm:I,setSubmitting:c});Pe.useEffect(()=>{(a.current===null||e.id!==a.current)&&(a.current=e.id,d(r));},[e.id,d]);let H=Pe.useMemo(()=>e,[e]),de=Pe.useMemo(()=>({formState:l,formConfig:H,fieldConditions:v,conditionsHelpers:P,setValue:g,setFieldTouched:p,validateField:w,validateForm:I,isFormValid:n,reset:d,submit:O,setError:u,clearError:m}),[l,H,v,P,g,p,w,I,n,d,O,u,m]);return jsxRuntime.jsx(re.Provider,{value:de,children:jsxRuntime.jsx("form",{onSubmit:O,className:s,noValidate:true,children:o})})}function y(){let o=Pe.useContext(re);if(!o)throw new Error("useFormContext must be used within a FormProvider");return o}function Se({formConfig:o,defaultValues:e,onSubmit:r,onFieldChange:t,children:i}){let s=Pe.useMemo(()=>o instanceof E?o.build():o,[o]);return jsxRuntime.jsx(L,{formConfig:s,defaultValues:e,onSubmit:r,onFieldChange:t,children:i})}var N=Pe__default.default.memo(function({fieldId:e,disabled:r=false,customProps:t={},className:i,forceVisible:s=false}){let{formState:a,formConfig:l,setValue:F,setFieldTouched:g,validateField:p,conditionsHelpers:d}=y(),u=l.allFields.find(w=>w.id===e);if(!u)throw new Error(`Field with ID "${e}" not found`);let m=l.config.getComponent(u.componentId);if(!m)throw new Error(`Component with ID "${u.componentId}" not found`);let f=Pe.useMemo(()=>({value:a.values[e],errors:a.errors[e]||[],validationState:a.validationState[e]||"idle",isTouched:a.touched[e]||false}),[a.values[e],a.errors[e],a.validationState[e],a.touched[e]]),c=f.validationState==="validating",n=Pe.useMemo(()=>({isVisible:s||d.isFieldVisible(e),isFieldDisabled:r||d.isFieldDisabled(e),isFieldRequired:d.isFieldRequired(e),isFieldReadonly:d.isFieldReadonly(e)}),[s,e,r,d,a.values]),v=Pe.useCallback(async w=>{F(e,w),(u.validation?.validateOnChange||f.isTouched)&&await p(e,w);},[e,F,p,u.validation?.validateOnChange,f.isTouched]),h=Pe.useCallback(async()=>{f.isTouched||g(e),u.validation?.validateOnBlur!==false&&await p(e);},[e,f.isTouched,g,p,u.validation?.validateOnBlur]),R=Pe.useMemo(()=>({...m.defaultProps??{},...u.props,...t,disabled:n.isFieldDisabled,required:n.isFieldRequired,readOnly:n.isFieldReadonly}),[m.defaultProps,u.props,t,n.isFieldDisabled,n.isFieldRequired,n.isFieldReadonly]),C=Pe.useMemo(()=>({id:e,props:R,value:f.value,onChange:v,onBlur:h,disabled:n.isFieldDisabled,error:f.errors,isValidating:c,touched:f.isTouched}),[e,R,f.value,v,h,n.isFieldDisabled,f.errors,c,f.isTouched]);if(!n.isVisible)return null;let S=m.renderer(C),x=l.renderConfig?.fieldRenderer,D=m.useFieldRenderer!==false,P=x&&D?x({children:S,id:e,...R,error:f.errors,isValidating:c,touched:f.isTouched}):S;return jsxRuntime.jsx("div",{className:i,"data-field-id":e,"data-field-type":m.type,"data-field-visible":n.isVisible,"data-field-disabled":n.isFieldDisabled,"data-field-required":n.isFieldRequired,"data-field-readonly":n.isFieldReadonly,children:P})});var te=Pe__default.default.memo(function({row:e,className:r,...t}){let{formConfig:i,conditionsHelpers:s}=y(),a=Pe.useMemo(()=>e.fields.filter(g=>s.isFieldVisible(g.id)),[e.fields,s]),l=Pe.useMemo(()=>a.map(g=>jsxRuntime.jsx(N,{fieldId:g.id},g.id)),[a]),F=Pe.useMemo(()=>({row:e,children:l,className:r}),[e,l,r]);return a.length===0?null:jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormRow",renderer:i.renderConfig?.rowRenderer,props:F,...t,children:l})}),ne=te;var _e=Pe__default.default.memo(function({className:e,...r}){let{formConfig:t}=y(),i=Pe.useMemo(()=>t.rows.map(a=>jsxRuntime.jsx(ne,{row:a},a.id)),[t.rows]),s=Pe.useMemo(()=>({formConfig:t,children:i,className:e}),[t,i,e]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormBody",renderer:t.renderConfig?.bodyRenderer,props:s,...r,children:i})});var qe=Pe__default.default.memo(function({className:e,isSubmitting:r,...t}){let{formState:i,submit:s,formConfig:a}=y(),l=Pe.useMemo(()=>({isSubmitting:r??i.isSubmitting,onSubmit:s,className:e}),[r,i.isSubmitting,s,e]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormSubmitButton",renderer:a.renderConfig?.submitButtonRenderer,props:l,...t})});exports.Form=Se;exports.FormBody=_e;exports.FormBuilder=E;exports.FormField=N;exports.FormProvider=L;exports.FormRow=te;exports.FormSubmitButton=qe;exports.form=E;exports.useConditionEvaluation=He;exports.useFormConditions=Q;exports.useFormContext=y;exports.useFormMonitoring=Ce;exports.useFormState=z;exports.useFormSubmission=K;exports.useFormValidation=Z;exports.useMultipleConditionEvaluation=J;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import xe,{createContext,useMemo,useCallback,useContext,useReducer,useRef,useEffect}from'react';import {ComponentRendererWrapper,IdGenerator,deepClone,ensureUnique,hasUnifiedValidation,createValidationContext,validateWithUnifiedConfig,validateFormWithUnifiedConfig,getGlobalMonitor,evaluateCondition}from'@rilaykit/core';import {jsx}from'react/jsx-runtime';var E=class o{constructor(e,r){this.rows=[];this.idGenerator=new IdGenerator;this.config=e,this.formId=r||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,r){return new o(e,r)}createFormField(e){let r=this.config.getComponent(e.type);if(!r)throw new Error(`No component found with type "${e.type}"`);let t;return (r.validation||e.validation)&&(t={validateOnChange:e.validation?.validateOnChange??r.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??r.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??r.validation?.debounceMs,validate:(()=>{let i=r.validation?.validate,n=e.validation?.validate;if(!i)return n;if(!n)return i;let l=Array.isArray(i)?i:[i],u=Array.isArray(n)?n:[n];return [...l,...u]})()}),{id:e.id||this.idGenerator.next("field"),componentId:r.id,props:{...r.defaultProps,...e.props},validation:t,conditions:e.conditions}}createRow(e){if(e.length===0)throw new Error("At least one field is required");if(e.length>3)throw new Error("Maximum 3 fields per row");let r=e.map(t=>this.createFormField(t));return {id:this.idGenerator.next("row"),fields:r,maxColumns:e.length}}add(...e){let r,t=false;if(e.length===1&&Array.isArray(e[0])?(r=e[0],t=true):r=e,r.length===0)throw new Error("At least one field is required");if(t&&r.length>3)throw new Error("Maximum 3 fields per row");if(r.length===1){let i=this.createRow(r);return this.rows.push(i),this}if(r.length<=3){let i=this.createRow(r);return this.rows.push(i),this}for(let i of r){let n=this.createRow([i]);this.rows.push(n);}return this}addSeparateRows(e){for(let r of e)this.add(r);return this}setId(e){return this.formId=e,this}updateField(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);return Object.assign(t,{...r,props:{...t.props,...r.props}}),this}findField(e){for(let r of this.rows){let t=r.fields.find(i=>i.id===e);if(t)return t}return null}removeField(e){return this.rows=this.rows.map(r=>({...r,fields:r.fields.filter(t=>t.id!==e)})).filter(r=>r.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.idGenerator.reset(),this}setValidation(e){return this.formValidation=e,this}addFieldValidation(e,r){console.warn("addFieldValidation is deprecated. Use updateField with validation.validate property instead.");let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let i={...t.validation,...r};return this.updateField(e,{validation:i})}addFieldConditions(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let i={...t.conditions,...r};return this.updateField(e,{conditions:i})}clone(e){let r=new o(this.config,e||`${this.formId}-clone`);return r.rows=deepClone(this.rows),r}validate(){let e=[],r=this.getFields(),t=r.map(i=>i.id);try{ensureUnique(t,"field");}catch(i){e.push(i instanceof Error?i.message:String(i));}for(let i of r)this.config.hasComponent(i.componentId)||e.push(`Component "${i.componentId}" not found for field "${i.id}"`);for(let i of this.rows)i.fields.length>3&&e.push(`Row "${i.id}" has ${i.fields.length} fields, maximum is 3`),i.fields.length===0&&e.push(`Row "${i.id}" is empty`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig(),validation:this.formValidation}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows),this}getStats(){let e=this.getFields(),r=this.rows.map(t=>t.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:r.length>0?Math.max(...r):0,minFieldsInRow:r.length>0?Math.min(...r):0}}};function Ge(o,e={},r={}){return useMemo(()=>{if(!o)return {visible:r.visible??true,disabled:r.disabled??false,required:r.required??false,readonly:r.readonly??false};let t=i=>{try{return i&&typeof i=="object"&&"build"in i?evaluateCondition(i.build(),e):evaluateCondition(i,e)}catch(n){return console.warn("Error evaluating condition:",n),false}};return {visible:o.visible?t(o.visible):r.visible??true,disabled:o.disabled?t(o.disabled):r.disabled??false,required:o.required?t(o.required):r.required??false,readonly:o.readonly?t(o.readonly):r.readonly??false}},[o,e,r])}function H(o,e={}){return useMemo(()=>{let r={};for(let[t,i]of Object.entries(o))if(r[t]={visible:true,disabled:false,required:false,readonly:false},i){let n=l=>{try{return l&&typeof l=="object"&&"build"in l?evaluateCondition(l.build(),e):evaluateCondition(l,e)}catch(u){return console.warn(`Error evaluating condition for field ${t}:`,u),false}};r[t]={visible:i.visible?n(i.visible):true,disabled:i.disabled?n(i.disabled):false,required:i.required?n(i.required):false,readonly:i.readonly?n(i.readonly):false};}return r},[o,e])}function W({formConfig:o,formValues:e}){let r=useMemo(()=>{let f={};for(let s of o.allFields)s.conditions&&(f[s.id]=s.conditions);return f},[o.allFields]),t=useMemo(()=>Object.keys(r).length>0,[r]),i=H(t?r:{},t?e:{}),n=useCallback(f=>i[f],[i]),l=useCallback(f=>{let s=i[f];return s?s.visible:true},[i]),u=useCallback(f=>{let s=i[f];return s?s.disabled:false},[i]),F=useCallback(f=>{let s=i[f];return s?s.required:false},[i]),g=useCallback(f=>{let s=i[f];return s?s.readonly:false},[i]);return useMemo(()=>({fieldConditions:i,hasConditionalFields:t,getFieldCondition:n,isFieldVisible:l,isFieldDisabled:u,isFieldRequired:F,isFieldReadonly:g}),[i,t,n,l,u,F,g])}function ce(o,e){switch(e.type){case "SET_VALUE":return {...o,values:{...o.values,[e.fieldId]:e.value},isDirty:true};case "SET_FIELD_ERRORS":return {...o,errors:{...o.errors,[e.fieldId]:e.errors}};case "SET_FIELD_VALIDATION_STATE":return {...o,validationState:{...o.validationState,[e.fieldId]:e.state}};case "SET_FIELD_TOUCHED":return {...o,touched:{...o.touched,[e.fieldId]:true}};case "SET_SUBMITTING":return {...o,isSubmitting:e.isSubmitting};case "RESET":return {values:e.values||{},errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false};default:return o}}function J({defaultValues:o={},onFieldChange:e}){let r={values:o,errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false},[t,i]=useReducer(ce,r),n=useRef(e);n.current=e;let l=useCallback((d,p)=>{i({type:"SET_VALUE",fieldId:d,value:p}),n.current?.(d,p,{...t.values,[d]:p});},[t.values]),u=useCallback(d=>{i({type:"SET_FIELD_TOUCHED",fieldId:d});},[]),F=useCallback((d,p)=>{i({type:"SET_FIELD_ERRORS",fieldId:d,errors:p});},[]),g=useCallback(d=>{i({type:"SET_FIELD_ERRORS",fieldId:d,errors:[]});},[]),f=useCallback((d,p)=>{i({type:"SET_FIELD_VALIDATION_STATE",fieldId:d,state:p});},[]),s=useCallback(d=>{i({type:"SET_SUBMITTING",isSubmitting:d});},[]),m=useCallback(d=>{i({type:"RESET",values:d});},[]),c=useCallback(()=>{let d=Object.values(t.errors).some(a=>a.length>0),p=Object.values(t.validationState).some(a=>a==="invalid");return !d&&!p},[t.errors,t.validationState]);return {formState:t,setValue:l,setFieldTouched:u,setError:F,clearError:g,setFieldValidationState:f,setSubmitting:s,reset:m,isFormValid:c}}function Q({formState:o,onSubmit:e,validateForm:r,setSubmitting:t}){let i=useRef(e);return i.current=e,{submit:useCallback(async l=>{l?.preventDefault();try{return t(!0),(await r()).isValid?(i.current&&await i.current(o.values),!0):!1}catch(u){return console.error("Error during form submission:",u),false}finally{t(false);}},[o.values,r,t])}}function B(){return {isValid:true,errors:[]}}function K({formConfig:o,formState:e,conditionsHelpers:r,setFieldValidationState:t,setError:i}){let n=useRef(o),l=useRef(r),u=useRef(t),F=useRef(i);n.current=o,l.current=r,u.current=t,F.current=i;let g=useCallback(async(s,m)=>{let c=n.current.allFields.find(a=>a.id===s);if(!c)return B();if(!l.current.isFieldVisible(s))return F.current(s,[]),u.current(s,"valid"),B();if(!c.validation||!hasUnifiedValidation(c.validation))return F.current(s,[]),u.current(s,"valid"),B();let d=m!==void 0?m:e.values[s],p=createValidationContext({fieldId:s,formId:n.current.id,allFormData:{...e.values,[s]:d}});u.current(s,"validating");try{let a=await validateWithUnifiedConfig(c.validation,d,p),h=l.current.isFieldRequired(s),v=d==null||d==="";if(h&&v&&!a.errors.some(C=>C.code==="REQUIRED"||C.message.toLowerCase().includes("required"))){let C={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...a.errors]};return F.current(s,C.errors),u.current(s,"invalid"),C}return F.current(s,a.errors),u.current(s,a.isValid?"valid":"invalid"),a}catch(a){let h={isValid:false,errors:[{message:a instanceof Error?a.message:"Validation failed",code:"VALIDATION_ERROR"}]};return F.current(s,h.errors),u.current(s,"invalid"),h}},[e.values]),f=useCallback(async()=>{let s=n.current.allFields.filter(a=>{let h=l.current.isFieldVisible(a.id),v=a.validation&&hasUnifiedValidation(a.validation);return h&&v}),m=n.current.allFields.filter(a=>!l.current.isFieldVisible(a.id));for(let a of m)F.current(a.id,[]),u.current(a.id,"valid");let c=await Promise.all(s.map(a=>g(a.id))),d=c.some(a=>!a.isValid),p=B();if(n.current.validation&&hasUnifiedValidation(n.current.validation)){let a=Object.keys(e.values).reduce((v,R)=>(l.current.isFieldVisible(R)&&(v[R]=e.values[R]),v),{}),h=createValidationContext({formId:n.current.id,allFormData:a});try{p=await validateFormWithUnifiedConfig(n.current.validation,a,h);}catch(v){p={isValid:false,errors:[{message:v instanceof Error?v.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!d&&p.isValid,errors:[...c.flatMap(a=>a.errors),...p.errors]}},[e.values,g]);return {validateField:g,validateForm:f}}function Re({formConfig:o,enabled:e=true}){let r=getGlobalMonitor(),t=useRef(null),i=useRef(0),n=useRef(0);useEffect(()=>{r&&e&&(t.current=r.getProfiler());},[r,e]);let l=useCallback(m=>{if(!r||!e)return;i.current++;let c={formId:o.id,fieldCount:o.allFields.length,timestamp:Date.now(),duration:0,renderDuration:0,validationDuration:0,validationErrors:0,renderCount:m||i.current};r.track("component_render",`form_${o.id}`,{formId:o.id,fieldCount:o.allFields.length,renderCount:i.current},c,"low");},[r,e,o.id,o.allFields.length]),u=useCallback((m,c)=>{if(!r||!e)return;let d=t.current?.getMetrics(`form_validation_${o.id}`),p={formId:o.id,fieldCount:c||o.allFields.length,timestamp:Date.now(),duration:d?.duration||0,renderDuration:0,validationDuration:d?.duration||0,validationErrors:m,renderCount:i.current};r.track("form_validation",`form_${o.id}`,{formId:o.id,validationErrors:m,fieldCount:c||o.allFields.length},p,m>0?"medium":"low");},[r,e,o.id,o.allFields.length]),F=useCallback((m,c)=>{if(!r||!e)return;let d=t.current?.getMetrics(`form_submission_${o.id}`),p={formId:o.id,fieldCount:c||o.allFields.length,timestamp:Date.now(),duration:d?.duration||0,renderDuration:0,validationDuration:0,validationErrors:m?0:1,renderCount:i.current};r.track("form_submission",`form_${o.id}`,{formId:o.id,success:m,fieldCount:c||o.allFields.length,fieldChanges:n.current},p,m?"low":"high");},[r,e,o.id,o.allFields.length]),g=useCallback((m,c)=>{!r||!e||(n.current++,r.track("component_update",`field_${m}`,{formId:o.id,fieldId:m,componentType:c,changeCount:n.current},void 0,"low"));},[r,e,o.id]),f=useCallback(m=>{!t.current||!e||t.current.start(m,{formId:o.id,renderCount:i.current});},[e,o.id]),s=useCallback(m=>{if(!t.current||!e)return null;let c=t.current.end(m);return c?{...c,formId:o.id,fieldCount:o.allFields.length,renderDuration:c.duration,validationDuration:0,validationErrors:0}:null},[e,o.id,o.allFields.length]);return {trackFormRender:l,trackFormValidation:u,trackFormSubmission:F,trackFieldChange:g,startPerformanceTracking:f,endPerformanceTracking:s}}var Y=createContext(null);function $({children:o,formConfig:e,defaultValues:r={},onSubmit:t,onFieldChange:i,className:n}){let l=useRef(e.id),{formState:u,setValue:F,setFieldTouched:g,reset:f,setError:s,clearError:m,setFieldValidationState:c,setSubmitting:d,isFormValid:p}=J({defaultValues:r,onFieldChange:i}),{fieldConditions:a,hasConditionalFields:h,getFieldCondition:v,isFieldVisible:R,isFieldDisabled:C,isFieldRequired:V,isFieldReadonly:x}=W({formConfig:e,formValues:u.values}),P=useMemo(()=>({hasConditionalFields:h,getFieldCondition:v,isFieldVisible:R,isFieldDisabled:C,isFieldRequired:V,isFieldReadonly:x}),[h,v,R,C,V,x]),{validateField:D,validateForm:b}=K({formConfig:e,formState:u,conditionsHelpers:P,setFieldValidationState:c,setError:s}),{submit:I}=Q({formState:u,onSubmit:t,validateForm:b,setSubmitting:d});useEffect(()=>{(l.current===null||e.id!==l.current)&&(l.current=e.id,f(r));},[e.id,f]);let N=useMemo(()=>e,[e]),se=useMemo(()=>({formState:u,formConfig:N,fieldConditions:a,conditionsHelpers:P,setValue:F,setFieldTouched:g,validateField:D,validateForm:b,isFormValid:p,reset:f,submit:I,setError:s,clearError:m}),[u,N,a,P,F,g,D,b,p,f,I,s,m]);return jsx(Y.Provider,{value:se,children:jsx("form",{onSubmit:I,className:n,noValidate:true,children:o})})}function y(){let o=useContext(Y);if(!o)throw new Error("useFormContext must be used within a FormProvider");return o}function Se({formConfig:o,defaultValues:e,onSubmit:r,onFieldChange:t,children:i}){let n=useMemo(()=>o instanceof E?o.build():o,[o]);return jsx($,{formConfig:n,defaultValues:e,onSubmit:r,onFieldChange:t,children:i})}var L=xe.memo(function({fieldId:e,disabled:r=false,customProps:t={},className:i,forceVisible:n=false}){let{formState:l,formConfig:u,setValue:F,setFieldTouched:g,validateField:f,conditionsHelpers:s}=y(),m=u.allFields.find(b=>b.id===e);if(!m)throw new Error(`Field with ID "${e}" not found`);let c=u.config.getComponent(m.componentId);if(!c)throw new Error(`Component with ID "${m.componentId}" not found`);let d=useMemo(()=>({value:l.values[e],errors:l.errors[e]||[],validationState:l.validationState[e]||"idle",isTouched:l.touched[e]||false}),[l.values[e],l.errors[e],l.validationState[e],l.touched[e]]),p=d.validationState==="validating",a=useMemo(()=>({isVisible:n||s.isFieldVisible(e),isFieldDisabled:r||s.isFieldDisabled(e),isFieldRequired:s.isFieldRequired(e),isFieldReadonly:s.isFieldReadonly(e)}),[n,e,r,s,l.values]);if(!a.isVisible)return null;let h=useCallback(async b=>{F(e,b),(m.validation?.validateOnChange||d.isTouched)&&await f(e,b);},[e,F,f,m.validation?.validateOnChange,d.isTouched]),v=useCallback(async()=>{d.isTouched||g(e),m.validation?.validateOnBlur!==false&&await f(e);},[e,d.isTouched,g,f,m.validation?.validateOnBlur]),R=useMemo(()=>({...c.defaultProps??{},...m.props,...t,disabled:a.isFieldDisabled,required:a.isFieldRequired,readOnly:a.isFieldReadonly}),[c.defaultProps,m.props,t,a.isFieldDisabled,a.isFieldRequired,a.isFieldReadonly]),C=useMemo(()=>({id:e,props:R,value:d.value,onChange:h,onBlur:v,disabled:a.isFieldDisabled,error:d.errors,isValidating:p,touched:d.isTouched}),[e,R,d.value,h,v,a.isFieldDisabled,d.errors,p,d.isTouched]),V=c.renderer(C),x=u.renderConfig?.fieldRenderer,P=c.useFieldRenderer!==false,D=x&&P?x({children:V,id:e,...R,error:d.errors,isValidating:p,touched:d.isTouched}):V;return jsx("div",{className:i,"data-field-id":e,"data-field-type":c.type,"data-field-visible":a.isVisible,"data-field-disabled":a.isFieldDisabled,"data-field-required":a.isFieldRequired,"data-field-readonly":a.isFieldReadonly,children:D})});var ie=xe.memo(function({row:e,className:r,...t}){let{formConfig:i}=y(),n=useMemo(()=>e.fields.map(u=>jsx(L,{fieldId:u.id},u.id)),[e.fields]),l=useMemo(()=>({row:e,children:n,className:r}),[e,n,r]);return jsx(ComponentRendererWrapper,{name:"FormRow",renderer:i.renderConfig?.rowRenderer,props:l,...t,children:n})}),oe=ie;var Be=xe.memo(function({className:e,...r}){let{formConfig:t}=y(),i=useMemo(()=>t.rows.map(l=>jsx(oe,{row:l},l.id)),[t.rows]),n=useMemo(()=>({formConfig:t,children:i,className:e}),[t,i,e]);return jsx(ComponentRendererWrapper,{name:"FormBody",renderer:t.renderConfig?.bodyRenderer,props:n,...r,children:i})});var Ue=xe.memo(function({className:e,isSubmitting:r,...t}){let{formState:i,submit:n,formConfig:l}=y(),u=useMemo(()=>({isSubmitting:r??i.isSubmitting,onSubmit:n,className:e}),[r,i.isSubmitting,n,e]);return jsx(ComponentRendererWrapper,{name:"FormSubmitButton",renderer:l.renderConfig?.submitButtonRenderer,props:u,...t})});export{Se as Form,Be as FormBody,E as FormBuilder,L as FormField,$ as FormProvider,ie as FormRow,Ue as FormSubmitButton,E as form,Ge as useConditionEvaluation,W as useFormConditions,y as useFormContext,Re as useFormMonitoring,J as useFormState,Q as useFormSubmission,K as useFormValidation,H as useMultipleConditionEvaluation};
|
|
1
|
+
import Pe,{createContext,useMemo,useCallback,useContext,useReducer,useRef,useEffect}from'react';import {ComponentRendererWrapper,IdGenerator,deepClone,ensureUnique,hasUnifiedValidation,createValidationContext,validateWithUnifiedConfig,validateFormWithUnifiedConfig,getGlobalMonitor,evaluateCondition}from'@rilaykit/core';import {jsx}from'react/jsx-runtime';var E=class o{constructor(e,r){this.rows=[];this.idGenerator=new IdGenerator;this.config=e,this.formId=r||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,r){return new o(e,r)}createFormField(e){let r=this.config.getComponent(e.type);if(!r)throw new Error(`No component found with type "${e.type}"`);let t;return (r.validation||e.validation)&&(t={validateOnChange:e.validation?.validateOnChange??r.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??r.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??r.validation?.debounceMs,validate:(()=>{let i=r.validation?.validate,s=e.validation?.validate;if(!i)return s;if(!s)return i;let a=Array.isArray(i)?i:[i],l=Array.isArray(s)?s:[s];return [...a,...l]})()}),{id:e.id||this.idGenerator.next("field"),componentId:r.id,props:{...r.defaultProps,...e.props},validation:t,conditions:e.conditions}}createRow(e){if(e.length===0)throw new Error("At least one field is required");if(e.length>3)throw new Error("Maximum 3 fields per row");let r=e.map(t=>this.createFormField(t));return {id:this.idGenerator.next("row"),fields:r,maxColumns:e.length}}add(...e){let r,t=false;if(e.length===1&&Array.isArray(e[0])?(r=e[0],t=true):r=e,r.length===0)throw new Error("At least one field is required");if(t&&r.length>3)throw new Error("Maximum 3 fields per row");if(r.length===1){let i=this.createRow(r);return this.rows.push(i),this}if(r.length<=3){let i=this.createRow(r);return this.rows.push(i),this}for(let i of r){let s=this.createRow([i]);this.rows.push(s);}return this}addSeparateRows(e){for(let r of e)this.add(r);return this}setId(e){return this.formId=e,this}updateField(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);return Object.assign(t,{...r,props:{...t.props,...r.props}}),this}findField(e){for(let r of this.rows){let t=r.fields.find(i=>i.id===e);if(t)return t}return null}removeField(e){return this.rows=this.rows.map(r=>({...r,fields:r.fields.filter(t=>t.id!==e)})).filter(r=>r.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.idGenerator.reset(),this}setValidation(e){return this.formValidation=e,this}addFieldValidation(e,r){console.warn("addFieldValidation is deprecated. Use updateField with validation.validate property instead.");let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let i={...t.validation,...r};return this.updateField(e,{validation:i})}addFieldConditions(e,r){let t=this.findField(e);if(!t)throw new Error(`Field with ID "${e}" not found`);let i={...t.conditions,...r};return this.updateField(e,{conditions:i})}clone(e){let r=new o(this.config,e||`${this.formId}-clone`);return r.rows=deepClone(this.rows),r}validate(){let e=[],r=this.getFields(),t=r.map(i=>i.id);try{ensureUnique(t,"field");}catch(i){e.push(i instanceof Error?i.message:String(i));}for(let i of r)this.config.hasComponent(i.componentId)||e.push(`Component "${i.componentId}" not found for field "${i.id}"`);for(let i of this.rows)i.fields.length>3&&e.push(`Row "${i.id}" has ${i.fields.length} fields, maximum is 3`),i.fields.length===0&&e.push(`Row "${i.id}" is empty`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),config:this.config,renderConfig:this.config.getFormRenderConfig(),validation:this.formValidation}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows),this}getStats(){let e=this.getFields(),r=this.rows.map(t=>t.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:r.length>0?Math.max(...r):0,minFieldsInRow:r.length>0?Math.min(...r):0}}};function He(o,e={},r={}){return useMemo(()=>{if(!o)return {visible:r.visible??true,disabled:r.disabled??false,required:r.required??false,readonly:r.readonly??false};let t=i=>{try{return i&&typeof i=="object"&&"build"in i?evaluateCondition(i.build(),e):evaluateCondition(i,e)}catch(s){return console.warn("Error evaluating condition:",s),false}};return {visible:o.visible?t(o.visible):r.visible??true,disabled:o.disabled?t(o.disabled):r.disabled??false,required:o.required?t(o.required):r.required??false,readonly:o.readonly?t(o.readonly):r.readonly??false}},[o,e,r])}function J(o,e={}){return useMemo(()=>{let r={};for(let[t,i]of Object.entries(o))if(r[t]={visible:true,disabled:false,required:false,readonly:false},i){let s=a=>{try{return a&&typeof a=="object"&&"build"in a?evaluateCondition(a.build(),e):evaluateCondition(a,e)}catch(l){return console.warn(`Error evaluating condition for field ${t}:`,l),false}};r[t]={visible:i.visible?s(i.visible):true,disabled:i.disabled?s(i.disabled):false,required:i.required?s(i.required):false,readonly:i.readonly?s(i.readonly):false};}return r},[o,e])}function Q({formConfig:o,formValues:e}){let r=useMemo(()=>{let p={};for(let d of o.allFields)d.conditions&&(p[d.id]=d.conditions);return p},[o.allFields]),t=useMemo(()=>Object.keys(r).length>0,[r]),i=J(t?r:{},t?e:{}),s=useCallback(p=>i[p],[i]),a=useCallback(p=>{let d=i[p];return d?d.visible:true},[i]),l=useCallback(p=>{let d=i[p];return d?d.disabled:false},[i]),F=useCallback(p=>{let d=i[p];return d?d.required:false},[i]),g=useCallback(p=>{let d=i[p];return d?d.readonly:false},[i]);return useMemo(()=>({fieldConditions:i,hasConditionalFields:t,getFieldCondition:s,isFieldVisible:a,isFieldDisabled:l,isFieldRequired:F,isFieldReadonly:g}),[i,t,s,a,l,F,g])}function fe(o,e){switch(e.type){case "SET_VALUE":return {...o,values:{...o.values,[e.fieldId]:e.value},isDirty:true};case "SET_FIELD_ERRORS":return {...o,errors:{...o.errors,[e.fieldId]:e.errors}};case "SET_FIELD_VALIDATION_STATE":return {...o,validationState:{...o.validationState,[e.fieldId]:e.state}};case "SET_FIELD_TOUCHED":return {...o,touched:{...o.touched,[e.fieldId]:true}};case "SET_SUBMITTING":return {...o,isSubmitting:e.isSubmitting};case "RESET":return {values:e.values||{},errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false};default:return o}}function z({defaultValues:o={},onFieldChange:e}){let r={values:o,errors:{},validationState:{},touched:{},isDirty:false,isSubmitting:false},[t,i]=useReducer(fe,r),s=useRef(e);s.current=e;let a=useRef(o);a.current=t.values;let l=useCallback((c,n)=>{let v={...a.current,[c]:n};a.current=v,i({type:"SET_VALUE",fieldId:c,value:n}),s.current?.(c,n,v);},[]),F=useCallback(c=>{i({type:"SET_FIELD_TOUCHED",fieldId:c});},[]),g=useCallback((c,n)=>{i({type:"SET_FIELD_ERRORS",fieldId:c,errors:n});},[]),p=useCallback(c=>{i({type:"SET_FIELD_ERRORS",fieldId:c,errors:[]});},[]),d=useCallback((c,n)=>{i({type:"SET_FIELD_VALIDATION_STATE",fieldId:c,state:n});},[]),u=useCallback(c=>{i({type:"SET_SUBMITTING",isSubmitting:c});},[]),m=useCallback(c=>{let n=c||{};a.current=n,i({type:"RESET",values:n});},[]),f=useCallback(()=>{let c=Object.values(t.errors).some(v=>v.length>0),n=Object.values(t.validationState).some(v=>v==="invalid");return !c&&!n},[t.errors,t.validationState]);return {formState:t,valuesRef:a,setValue:l,setFieldTouched:F,setError:g,clearError:p,setFieldValidationState:d,setSubmitting:u,reset:m,isFormValid:f}}function K({valuesRef:o,onSubmit:e,validateForm:r,setSubmitting:t}){let i=useRef(e);return i.current=e,{submit:useCallback(async a=>{a?.preventDefault();try{return t(!0),(await r()).isValid?(i.current&&await i.current(o.current),!0):!1}catch(l){return console.error("Error during form submission:",l),false}finally{t(false);}},[o,r,t])}}function B(){return {isValid:true,errors:[]}}function Z({formConfig:o,formState:e,conditionsHelpers:r,setFieldValidationState:t,setError:i}){let s=useRef(o),a=useRef(r),l=useRef(t),F=useRef(i);s.current=o,a.current=r,l.current=t,F.current=i;let g=useCallback(async(d,u)=>{let m=s.current.allFields.find(n=>n.id===d);if(!m)return B();if(!a.current.isFieldVisible(d))return F.current(d,[]),l.current(d,"valid"),B();if(!m.validation||!hasUnifiedValidation(m.validation))return F.current(d,[]),l.current(d,"valid"),B();let f=u!==void 0?u:e.values[d],c=createValidationContext({fieldId:d,formId:s.current.id,allFormData:{...e.values,[d]:f}});l.current(d,"validating");try{let n=await validateWithUnifiedConfig(m.validation,f,c),v=a.current.isFieldRequired(d),h=f==null||f==="";if(v&&h&&!n.errors.some(C=>C.code==="REQUIRED"||C.message.toLowerCase().includes("required"))){let C={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...n.errors]};return F.current(d,C.errors),l.current(d,"invalid"),C}return F.current(d,n.errors),l.current(d,n.isValid?"valid":"invalid"),n}catch(n){let v={isValid:false,errors:[{message:n instanceof Error?n.message:"Validation failed",code:"VALIDATION_ERROR"}]};return F.current(d,v.errors),l.current(d,"invalid"),v}},[e.values]),p=useCallback(async()=>{let d=s.current.allFields.filter(n=>{let v=a.current.isFieldVisible(n.id),h=n.validation&&hasUnifiedValidation(n.validation);return v&&h}),u=s.current.allFields.filter(n=>!a.current.isFieldVisible(n.id));for(let n of u)F.current(n.id,[]),l.current(n.id,"valid");let m=await Promise.all(d.map(n=>g(n.id))),f=m.some(n=>!n.isValid),c=B();if(s.current.validation&&hasUnifiedValidation(s.current.validation)){let n=Object.keys(e.values).reduce((h,R)=>(a.current.isFieldVisible(R)&&(h[R]=e.values[R]),h),{}),v=createValidationContext({formId:s.current.id,allFormData:n});try{c=await validateFormWithUnifiedConfig(s.current.validation,n,v);}catch(h){c={isValid:false,errors:[{message:h instanceof Error?h.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!f&&c.isValid,errors:[...m.flatMap(n=>n.errors),...c.errors]}},[e.values,g]);return {validateField:g,validateForm:p}}function Ce({formConfig:o,enabled:e=true}){let r=getGlobalMonitor(),t=useRef(null),i=useRef(0),s=useRef(0);useEffect(()=>{r&&e&&(t.current=r.getProfiler());},[r,e]);let a=useCallback(u=>{if(!r||!e)return;i.current++;let m={formId:o.id,fieldCount:o.allFields.length,timestamp:Date.now(),duration:0,renderDuration:0,validationDuration:0,validationErrors:0,renderCount:u||i.current};r.track("component_render",`form_${o.id}`,{formId:o.id,fieldCount:o.allFields.length,renderCount:i.current},m,"low");},[r,e,o.id,o.allFields.length]),l=useCallback((u,m)=>{if(!r||!e)return;let f=t.current?.getMetrics(`form_validation_${o.id}`),c={formId:o.id,fieldCount:m||o.allFields.length,timestamp:Date.now(),duration:f?.duration||0,renderDuration:0,validationDuration:f?.duration||0,validationErrors:u,renderCount:i.current};r.track("form_validation",`form_${o.id}`,{formId:o.id,validationErrors:u,fieldCount:m||o.allFields.length},c,u>0?"medium":"low");},[r,e,o.id,o.allFields.length]),F=useCallback((u,m)=>{if(!r||!e)return;let f=t.current?.getMetrics(`form_submission_${o.id}`),c={formId:o.id,fieldCount:m||o.allFields.length,timestamp:Date.now(),duration:f?.duration||0,renderDuration:0,validationDuration:0,validationErrors:u?0:1,renderCount:i.current};r.track("form_submission",`form_${o.id}`,{formId:o.id,success:u,fieldCount:m||o.allFields.length,fieldChanges:s.current},c,u?"low":"high");},[r,e,o.id,o.allFields.length]),g=useCallback((u,m)=>{!r||!e||(s.current++,r.track("component_update",`field_${u}`,{formId:o.id,fieldId:u,componentType:m,changeCount:s.current},void 0,"low"));},[r,e,o.id]),p=useCallback(u=>{!t.current||!e||t.current.start(u,{formId:o.id,renderCount:i.current});},[e,o.id]),d=useCallback(u=>{if(!t.current||!e)return null;let m=t.current.end(u);return m?{...m,formId:o.id,fieldCount:o.allFields.length,renderDuration:m.duration,validationDuration:0,validationErrors:0}:null},[e,o.id,o.allFields.length]);return {trackFormRender:a,trackFormValidation:l,trackFormSubmission:F,trackFieldChange:g,startPerformanceTracking:p,endPerformanceTracking:d}}var re=createContext(null);function L({children:o,formConfig:e,defaultValues:r={},onSubmit:t,onFieldChange:i,className:s}){let a=useRef(e.id),{formState:l,valuesRef:F,setValue:g,setFieldTouched:p,reset:d,setError:u,clearError:m,setFieldValidationState:f,setSubmitting:c,isFormValid:n}=z({defaultValues:r,onFieldChange:i}),{fieldConditions:v,hasConditionalFields:h,getFieldCondition:R,isFieldVisible:C,isFieldDisabled:S,isFieldRequired:x,isFieldReadonly:D}=Q({formConfig:e,formValues:l.values}),P=useMemo(()=>({hasConditionalFields:h,getFieldCondition:R,isFieldVisible:C,isFieldDisabled:S,isFieldRequired:x,isFieldReadonly:D}),[h,R,C,S,x,D]),{validateField:w,validateForm:I}=Z({formConfig:e,formState:l,conditionsHelpers:P,setFieldValidationState:f,setError:u}),{submit:O}=K({valuesRef:F,onSubmit:t,validateForm:I,setSubmitting:c});useEffect(()=>{(a.current===null||e.id!==a.current)&&(a.current=e.id,d(r));},[e.id,d]);let H=useMemo(()=>e,[e]),de=useMemo(()=>({formState:l,formConfig:H,fieldConditions:v,conditionsHelpers:P,setValue:g,setFieldTouched:p,validateField:w,validateForm:I,isFormValid:n,reset:d,submit:O,setError:u,clearError:m}),[l,H,v,P,g,p,w,I,n,d,O,u,m]);return jsx(re.Provider,{value:de,children:jsx("form",{onSubmit:O,className:s,noValidate:true,children:o})})}function y(){let o=useContext(re);if(!o)throw new Error("useFormContext must be used within a FormProvider");return o}function Se({formConfig:o,defaultValues:e,onSubmit:r,onFieldChange:t,children:i}){let s=useMemo(()=>o instanceof E?o.build():o,[o]);return jsx(L,{formConfig:s,defaultValues:e,onSubmit:r,onFieldChange:t,children:i})}var N=Pe.memo(function({fieldId:e,disabled:r=false,customProps:t={},className:i,forceVisible:s=false}){let{formState:a,formConfig:l,setValue:F,setFieldTouched:g,validateField:p,conditionsHelpers:d}=y(),u=l.allFields.find(w=>w.id===e);if(!u)throw new Error(`Field with ID "${e}" not found`);let m=l.config.getComponent(u.componentId);if(!m)throw new Error(`Component with ID "${u.componentId}" not found`);let f=useMemo(()=>({value:a.values[e],errors:a.errors[e]||[],validationState:a.validationState[e]||"idle",isTouched:a.touched[e]||false}),[a.values[e],a.errors[e],a.validationState[e],a.touched[e]]),c=f.validationState==="validating",n=useMemo(()=>({isVisible:s||d.isFieldVisible(e),isFieldDisabled:r||d.isFieldDisabled(e),isFieldRequired:d.isFieldRequired(e),isFieldReadonly:d.isFieldReadonly(e)}),[s,e,r,d,a.values]),v=useCallback(async w=>{F(e,w),(u.validation?.validateOnChange||f.isTouched)&&await p(e,w);},[e,F,p,u.validation?.validateOnChange,f.isTouched]),h=useCallback(async()=>{f.isTouched||g(e),u.validation?.validateOnBlur!==false&&await p(e);},[e,f.isTouched,g,p,u.validation?.validateOnBlur]),R=useMemo(()=>({...m.defaultProps??{},...u.props,...t,disabled:n.isFieldDisabled,required:n.isFieldRequired,readOnly:n.isFieldReadonly}),[m.defaultProps,u.props,t,n.isFieldDisabled,n.isFieldRequired,n.isFieldReadonly]),C=useMemo(()=>({id:e,props:R,value:f.value,onChange:v,onBlur:h,disabled:n.isFieldDisabled,error:f.errors,isValidating:c,touched:f.isTouched}),[e,R,f.value,v,h,n.isFieldDisabled,f.errors,c,f.isTouched]);if(!n.isVisible)return null;let S=m.renderer(C),x=l.renderConfig?.fieldRenderer,D=m.useFieldRenderer!==false,P=x&&D?x({children:S,id:e,...R,error:f.errors,isValidating:c,touched:f.isTouched}):S;return jsx("div",{className:i,"data-field-id":e,"data-field-type":m.type,"data-field-visible":n.isVisible,"data-field-disabled":n.isFieldDisabled,"data-field-required":n.isFieldRequired,"data-field-readonly":n.isFieldReadonly,children:P})});var te=Pe.memo(function({row:e,className:r,...t}){let{formConfig:i,conditionsHelpers:s}=y(),a=useMemo(()=>e.fields.filter(g=>s.isFieldVisible(g.id)),[e.fields,s]),l=useMemo(()=>a.map(g=>jsx(N,{fieldId:g.id},g.id)),[a]),F=useMemo(()=>({row:e,children:l,className:r}),[e,l,r]);return a.length===0?null:jsx(ComponentRendererWrapper,{name:"FormRow",renderer:i.renderConfig?.rowRenderer,props:F,...t,children:l})}),ne=te;var _e=Pe.memo(function({className:e,...r}){let{formConfig:t}=y(),i=useMemo(()=>t.rows.map(a=>jsx(ne,{row:a},a.id)),[t.rows]),s=useMemo(()=>({formConfig:t,children:i,className:e}),[t,i,e]);return jsx(ComponentRendererWrapper,{name:"FormBody",renderer:t.renderConfig?.bodyRenderer,props:s,...r,children:i})});var qe=Pe.memo(function({className:e,isSubmitting:r,...t}){let{formState:i,submit:s,formConfig:a}=y(),l=useMemo(()=>({isSubmitting:r??i.isSubmitting,onSubmit:s,className:e}),[r,i.isSubmitting,s,e]);return jsx(ComponentRendererWrapper,{name:"FormSubmitButton",renderer:a.renderConfig?.submitButtonRenderer,props:l,...t})});export{Se as Form,_e as FormBody,E as FormBuilder,N as FormField,L as FormProvider,te as FormRow,qe as FormSubmitButton,E as form,He as useConditionEvaluation,Q as useFormConditions,y as useFormContext,Ce as useFormMonitoring,z as useFormState,K as useFormSubmission,Z as useFormValidation,J as useMultipleConditionEvaluation};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rilaykit/forms",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "14.0.0",
|
|
4
4
|
"description": "Form building utilities and components for RilayKit",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"url": "https://github.com/andyoucreate/rilay/issues"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@rilaykit/core": "
|
|
35
|
+
"@rilaykit/core": "13.0.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"react": ">=18.0.0",
|