@rilaykit/forms 13.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 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: React$1.NamedExoticComponent<ComponentRendererBaseProps<FormBodyRendererProps>>;
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: React$1.NamedExoticComponent<FormFieldProps>;
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
- formState: FormState;
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({ formState, onSubmit, validateForm, setSubmitting, }: UseFormSubmissionProps): {
669
- submit: (event?: React$1.FormEvent) => Promise<boolean>;
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?: React$1.FormEvent) => Promise<boolean>;
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: React$1.ReactNode;
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: React$1.NamedExoticComponent<FormRowProps>;
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: React$1.NamedExoticComponent<FormSubmitButtonProps>;
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: React$1.NamedExoticComponent<ComponentRendererBaseProps<FormBodyRendererProps>>;
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: React$1.NamedExoticComponent<FormFieldProps>;
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
- formState: FormState;
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({ formState, onSubmit, validateForm, setSubmitting, }: UseFormSubmissionProps): {
669
- submit: (event?: React$1.FormEvent) => Promise<boolean>;
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?: React$1.FormEvent) => Promise<boolean>;
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: React$1.ReactNode;
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: React$1.NamedExoticComponent<FormRowProps>;
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: React$1.NamedExoticComponent<FormSubmitButtonProps>;
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]),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]);if(!a.isVisible)return null;let 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]),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]);if(!a.isVisible)return null;let 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": "13.0.0",
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": "12.1.0"
35
+ "@rilaykit/core": "13.0.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "react": ">=18.0.0",