@rilaykit/core 5.2.1 → 6.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,20 +1,101 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default from 'react';
3
3
 
4
+ type ConditionOperator = 'equals' | 'notEquals' | 'greaterThan' | 'lessThan' | 'greaterThanOrEqual' | 'lessThanOrEqual' | 'contains' | 'notContains' | 'in' | 'notIn' | 'matches' | 'exists' | 'notExists';
5
+ type LogicalOperator = 'and' | 'or';
6
+ type ConditionValue = string | number | boolean | null | undefined | Array<string | number | boolean>;
7
+ interface ConditionConfig {
8
+ field: string;
9
+ operator: ConditionOperator;
10
+ value?: ConditionValue;
11
+ conditions?: ConditionConfig[];
12
+ logicalOperator?: LogicalOperator;
13
+ }
14
+ type ConditionEvaluator = (data: Record<string, any>) => boolean;
15
+ interface ConditionBuilder extends ConditionConfig {
16
+ equals(value: ConditionValue): ConditionBuilder;
17
+ notEquals(value: ConditionValue): ConditionBuilder;
18
+ greaterThan(value: number): ConditionBuilder;
19
+ lessThan(value: number): ConditionBuilder;
20
+ greaterThanOrEqual(value: number): ConditionBuilder;
21
+ lessThanOrEqual(value: number): ConditionBuilder;
22
+ contains(value: string): ConditionBuilder;
23
+ notContains(value: string): ConditionBuilder;
24
+ in(values: Array<string | number | boolean>): ConditionBuilder;
25
+ notIn(values: Array<string | number | boolean>): ConditionBuilder;
26
+ matches(pattern: string | RegExp): ConditionBuilder;
27
+ exists(): ConditionBuilder;
28
+ notExists(): ConditionBuilder;
29
+ and(condition: ConditionBuilder | ConditionConfig): ConditionBuilder;
30
+ or(condition: ConditionBuilder | ConditionConfig): ConditionBuilder;
31
+ build(): ConditionConfig;
32
+ evaluate(data: Record<string, any>): boolean;
33
+ }
34
+ declare function when(field: string): ConditionBuilder;
35
+ declare function evaluateCondition(condition: ConditionConfig, data: Record<string, any>): boolean;
36
+
37
+ /**
38
+ * Validation result for async operations
39
+ */
40
+ interface AsyncValidationResult {
41
+ isValid: boolean;
42
+ errors: string[];
43
+ warnings?: string[];
44
+ }
45
+ /**
46
+ * Interface publique pour les instances Rilay
47
+ * Expose uniquement les méthodes nécessaires à l'API publique
48
+ */
49
+ interface RilayInstance<C> {
50
+ addComponent<NewType extends string, TProps = any>(type: NewType, config: Omit<ComponentConfig<TProps>, 'id' | 'type'>): RilayInstance<C & {
51
+ [K in NewType]: TProps;
52
+ }>;
53
+ configure(config: Partial<FormRenderConfig & WorkflowRenderConfig>): RilayInstance<C>;
54
+ getComponent<T extends keyof C & string>(id: T): ComponentConfig<C[T]> | undefined;
55
+ getComponent(id: string): ComponentConfig | undefined;
56
+ getAllComponents(): ComponentConfig[];
57
+ hasComponent(id: string): boolean;
58
+ getFormRenderConfig(): FormRenderConfig;
59
+ getWorkflowRenderConfig(): WorkflowRenderConfig;
60
+ getStats(): {
61
+ total: number;
62
+ byType: Record<string, number>;
63
+ hasCustomRenderers: {
64
+ row: boolean;
65
+ body: boolean;
66
+ submitButton: boolean;
67
+ field: boolean;
68
+ stepper: boolean;
69
+ workflowNextButton: boolean;
70
+ workflowPreviousButton: boolean;
71
+ workflowSkipButton: boolean;
72
+ };
73
+ };
74
+ validate(): string[];
75
+ validateAsync(): Promise<AsyncValidationResult>;
76
+ clone(): RilayInstance<C>;
77
+ removeComponent(id: string): RilayInstance<C>;
78
+ clear(): RilayInstance<C>;
79
+ }
4
80
  /**
5
81
  * Main configuration class for Rilay form components and workflows
6
- * Manages component registration, retrieval, and configuration
82
+ * Manages component registration, retrieval, and configuration with immutable API
7
83
  */
8
- declare class ril<C> {
84
+ declare class ril<C> implements RilayInstance<C> {
9
85
  private components;
10
86
  private formRenderConfig;
11
87
  private workflowRenderConfig;
88
+ /**
89
+ * Static factory method to create a new ril instance
90
+ */
12
91
  static create<CT>(): ril<CT>;
13
92
  /**
14
- * Add a component to the configuration
93
+ * Add a component to the configuration (immutable)
94
+ * Returns a new instance with the added component
95
+ *
15
96
  * @param type - The component type (e.g., 'text', 'email', 'heading'), used as a unique identifier.
16
97
  * @param config - Component configuration without id and type
17
- * @returns The ril instance for chaining
98
+ * @returns A new ril instance with the added component
18
99
  *
19
100
  * @example
20
101
  * ```typescript
@@ -34,58 +115,33 @@ declare class ril<C> {
34
115
  [K in NewType]: TProps;
35
116
  }>;
36
117
  /**
37
- * Universal configuration method for all renderer types
118
+ * Universal configuration method with deep merge support (immutable)
38
119
  *
39
120
  * This method provides a unified API to configure both form and workflow renderers
40
- * in a single call, automatically categorizing and applying the appropriate configurations.
121
+ * in a single call, automatically categorizing and applying the appropriate configurations
122
+ * using recursive deep merge.
41
123
  *
42
124
  * @param config - Configuration object containing renderer settings
43
- * @param config.rowRenderer - Custom renderer for form rows (form-specific)
44
- * @param config.bodyRenderer - Custom renderer for form body container (form-specific)
45
- * @param config.submitButtonRenderer - Custom renderer for form submit buttons (form-specific)
46
- * @param config.fieldRenderer - Custom renderer for individual form fields (form-specific)
47
- * @param config.stepperRenderer - Custom renderer for workflow step navigation (workflow-specific)
48
- * @param config.nextButtonRenderer - Custom renderer for workflow next buttons (workflow-specific)
49
- * @param config.previousButtonRenderer - Custom renderer for workflow previous buttons (workflow-specific)
50
- * @param config.skipButtonRenderer - Custom renderer for workflow skip buttons (workflow-specific)
51
- *
52
- * @returns The ril instance for method chaining
125
+ * @returns A new ril instance with the updated configuration
53
126
  *
54
127
  * @example
55
128
  * ```typescript
56
- * // Configure form renderers only
129
+ * // Configure with nested settings
57
130
  * const config = ril.create()
58
131
  * .configure({
59
132
  * rowRenderer: CustomRowRenderer,
60
- * submitButtonRenderer: CustomSubmitButton
61
- * });
62
- *
63
- * // Configure workflow renderers only
64
- * const config = ril.create()
65
- * .configure({
66
- * stepperRenderer: CustomStepper,
67
- * nextButtonRenderer: CustomNextButton
68
- * });
69
- *
70
- * // Configure both form and workflow renderers
71
- * const config = ril.create()
72
- * .configure({
73
- * // Form renderers
74
- * rowRenderer: CustomRowRenderer,
75
- * fieldRenderer: CustomFieldRenderer,
76
- * // Workflow renderers
77
- * stepperRenderer: CustomStepper,
78
- * nextButtonRenderer: CustomNextButton
133
+ * submitButtonRenderer: CustomSubmitButton,
134
+ * // Deep nested configuration example
135
+ * formStyles: {
136
+ * layout: {
137
+ * spacing: 'large',
138
+ * alignment: 'center'
139
+ * }
140
+ * }
79
141
  * });
80
142
  * ```
81
- *
82
- * @remarks
83
- * - Renderers are automatically categorized into form or workflow configurations
84
- * - Existing configurations are merged, not replaced entirely
85
- * - Invalid renderer keys are silently ignored
86
- * - This method replaces individual setter methods for better DX
87
143
  */
88
- configure(config: Partial<FormRenderConfig & WorkflowRenderConfig>): this;
144
+ configure(config: Partial<FormRenderConfig & WorkflowRenderConfig>): ril<C>;
89
145
  /**
90
146
  * Configuration getters
91
147
  */
@@ -97,8 +153,25 @@ declare class ril<C> {
97
153
  getComponent<T extends keyof C & string>(id: T): ComponentConfig<C[T]> | undefined;
98
154
  getAllComponents(): ComponentConfig[];
99
155
  hasComponent(id: string): boolean;
100
- removeComponent(id: string): boolean;
101
- clear(): void;
156
+ /**
157
+ * Remove a component from the configuration (immutable)
158
+ * Returns a new instance without the specified component
159
+ *
160
+ * @param id - The component ID to remove
161
+ * @returns A new ril instance without the component
162
+ */
163
+ removeComponent(id: string): ril<C>;
164
+ /**
165
+ * Clear all components from the configuration (immutable)
166
+ * Returns a new instance with no components
167
+ *
168
+ * @returns A new empty ril instance
169
+ */
170
+ clear(): ril<C>;
171
+ /**
172
+ * Create a deep copy of the current ril instance
173
+ */
174
+ clone(): ril<C>;
102
175
  /**
103
176
  * Enhanced statistics with more detailed information
104
177
  */
@@ -117,9 +190,14 @@ declare class ril<C> {
117
190
  };
118
191
  };
119
192
  /**
120
- * Enhanced validation using shared utilities
193
+ * Synchronous validation using shared utilities
121
194
  */
122
195
  validate(): string[];
196
+ /**
197
+ * Asynchronous validation with structured error handling
198
+ * Ideal for CI/CD pipelines and advanced validation scenarios
199
+ */
200
+ validateAsync(): Promise<AsyncValidationResult>;
123
201
  }
124
202
 
125
203
  interface RilayLicenseConfig {
@@ -207,11 +285,22 @@ interface ComponentConfig<TProps = any> {
207
285
  readonly useFieldRenderer?: boolean;
208
286
  readonly validation?: FieldValidationConfig;
209
287
  }
288
+ interface ConditionalBehavior {
289
+ readonly visible?: ConditionConfig;
290
+ readonly disabled?: ConditionConfig;
291
+ readonly required?: ConditionConfig;
292
+ readonly readonly?: ConditionConfig;
293
+ }
294
+ interface StepConditionalBehavior {
295
+ readonly visible?: ConditionConfig;
296
+ readonly skippable?: ConditionConfig;
297
+ }
210
298
  interface FormFieldConfig {
211
299
  readonly id: string;
212
300
  readonly componentId: string;
213
301
  readonly props: Record<string, any>;
214
302
  readonly validation?: FieldValidationConfig;
303
+ readonly conditions?: ConditionalBehavior;
215
304
  }
216
305
  interface FormFieldRow {
217
306
  readonly id: string;
@@ -311,6 +400,7 @@ interface StepConfig {
311
400
  readonly formConfig: FormConfiguration;
312
401
  readonly allowSkip?: boolean;
313
402
  readonly renderer?: CustomStepRenderer;
403
+ readonly conditions?: StepConditionalBehavior;
314
404
  readonly onAfterValidation?: (stepData: Record<string, any>, helper: StepDataHelper, context: WorkflowContext) => void | Promise<void>;
315
405
  }
316
406
  type CustomStepRenderer = (props: StepConfig) => React__default.ReactElement;
@@ -671,13 +761,13 @@ declare function matchField(targetFieldId: string, message?: string): FieldValid
671
761
  *
672
762
  * @example
673
763
  * ```typescript
674
- * const conditionalValidator = when(
764
+ * const conditionalValidator = validateWhen(
675
765
  * (value, context) => context.allFormData?.userType === 'premium',
676
766
  * required('Premium users must provide this field')
677
767
  * );
678
768
  * ```
679
769
  */
680
- declare function when<T>(condition: (value: T, context: ValidationContext) => boolean, validator: FieldValidator<T>): FieldValidator<T>;
770
+ declare function validateWhen<T>(condition: (value: T, context: ValidationContext) => boolean, validator: FieldValidator<T>): FieldValidator<T>;
681
771
  /**
682
772
  * Creates an async custom validator from a validation function
683
773
  *
@@ -701,129 +791,4 @@ declare function when<T>(condition: (value: T, context: ValidationContext) => bo
701
791
  */
702
792
  declare function async<T>(validateFn: (value: T, context: ValidationContext) => Promise<boolean>, message: string, code?: string): FieldValidator<T>;
703
793
 
704
- /**
705
- * @fileoverview Validation adapters for popular validation libraries
706
- *
707
- * This module provides adapters that integrate popular validation libraries
708
- * like Zod with Rilay's validation system. Adapters convert external schemas
709
- * into Rilay validators while maintaining type safety and error handling.
710
- */
711
-
712
- /**
713
- * Generic schema interface that Zod and similar libraries implement
714
- */
715
- interface ZodLikeSchema<T = any> {
716
- parse(value: unknown): T;
717
- safeParse(value: unknown): {
718
- success: true;
719
- data: T;
720
- } | {
721
- success: false;
722
- error: {
723
- errors: Array<{
724
- message: string;
725
- path: (string | number)[];
726
- }>;
727
- };
728
- };
729
- }
730
- /**
731
- * Zod validation adapter that converts Zod schemas into Rilay validators
732
- *
733
- * This adapter provides seamless integration with Zod schemas, automatically
734
- * converting Zod validation errors into Rilay ValidationError objects while
735
- * preserving error messages and field paths.
736
- *
737
- * @example
738
- * ```typescript
739
- * import { z } from 'zod';
740
- * import { createZodAdapter } from '@rilaykit/core';
741
- *
742
- * const zodAdapter = createZodAdapter();
743
- * const emailValidator = zodAdapter.createFieldValidator(
744
- * z.string().email('Invalid email format')
745
- * );
746
- * ```
747
- */
748
- declare class ZodValidationAdapter implements ValidationAdapter<ZodLikeSchema> {
749
- readonly name = "ZodValidationAdapter";
750
- readonly version = "1.0.0";
751
- /**
752
- * Creates a field validator from a Zod schema
753
- *
754
- * @param schema - The Zod schema to convert
755
- * @returns A FieldValidator function compatible with Rilay
756
- *
757
- * @example
758
- * ```typescript
759
- * const emailSchema = z.string().email();
760
- * const validator = adapter.createFieldValidator(emailSchema);
761
- * ```
762
- */
763
- createFieldValidator<T>(schema: ZodLikeSchema<T>): FieldValidator<T>;
764
- /**
765
- * Creates a form validator from a Zod object schema
766
- *
767
- * @param schema - The Zod object schema to convert
768
- * @returns A FormValidator function compatible with Rilay
769
- *
770
- * @example
771
- * ```typescript
772
- * const formSchema = z.object({
773
- * email: z.string().email(),
774
- * password: z.string().min(8)
775
- * });
776
- * const validator = adapter.createFormValidator(formSchema);
777
- * ```
778
- */
779
- createFormValidator<T>(schema: ZodLikeSchema<T>): FormValidator<T>;
780
- }
781
- /**
782
- * Creates a new Zod validation adapter instance
783
- *
784
- * @returns A configured ZodValidationAdapter instance
785
- *
786
- * @example
787
- * ```typescript
788
- * const adapter = createZodAdapter();
789
- * ```
790
- */
791
- declare function createZodAdapter(): ZodValidationAdapter;
792
- /**
793
- * Helper function to create a field validator directly from a Zod schema
794
- *
795
- * This is a convenience function that creates an adapter and field validator
796
- * in a single call, useful for simple use cases.
797
- *
798
- * @param schema - The Zod schema to convert
799
- * @returns A FieldValidator function
800
- *
801
- * @example
802
- * ```typescript
803
- * import { z } from 'zod';
804
- * import { zodFieldValidator } from '@rilaykit/core';
805
- *
806
- * const emailValidator = zodFieldValidator(z.string().email());
807
- * ```
808
- */
809
- declare function zodFieldValidator<T>(schema: ZodLikeSchema<T>): FieldValidator<T>;
810
- /**
811
- * Helper function to create a form validator directly from a Zod schema
812
- *
813
- * @param schema - The Zod object schema to convert
814
- * @returns A FormValidator function
815
- *
816
- * @example
817
- * ```typescript
818
- * import { z } from 'zod';
819
- * import { zodFormValidator } from '@rilaykit/core';
820
- *
821
- * const formValidator = zodFormValidator(z.object({
822
- * email: z.string().email(),
823
- * password: z.string().min(8)
824
- * }));
825
- * ```
826
- */
827
- declare function zodFormValidator<T>(schema: ZodLikeSchema<T>): FormValidator<T>;
828
-
829
- export { type ComponentConfig, type ComponentRenderProps, type ComponentRenderer, type ComponentRendererBaseProps, ComponentRendererWrapper, type ComponentRendererWrapperProps, type CustomStepRenderer, type FieldRenderer, type FieldRendererProps, type FieldValidationConfig, type FieldValidator, type FormBodyRenderer, type FormBodyRendererProps, type FormComponentRendererProps, type FormConfiguration, type FormFieldConfig, type FormFieldRow, type FormRenderConfig, type FormRowRenderer, type FormRowRendererProps, type FormSubmitButtonRenderer, type FormSubmitButtonRendererProps, type FormValidationConfig, type FormValidator, IdGenerator, type RendererChildrenFunction, type RilayLicenseConfig, type StepConfig, type StepDataHelper, type ValidationAdapter, type ValidationContext, type ValidationError, type ValidationResult, type ValidationSchema, type WorkflowAnalytics, type WorkflowComponentRendererBaseProps, type WorkflowConfig, type WorkflowContext, type WorkflowNextButtonRenderer, type WorkflowNextButtonRendererProps, type WorkflowPlugin, type WorkflowPreviousButtonRenderer, type WorkflowPreviousButtonRendererProps, type WorkflowRenderConfig, type WorkflowSkipButtonRenderer, type WorkflowSkipButtonRendererProps, type WorkflowStepperRenderer, type WorkflowStepperRendererProps, async, combineValidationResults, configureObject, createValidationContext, createValidationResult, createZodAdapter, custom, deepClone, email, ensureUnique, matchField, max, maxLength, mergeInto, min, minLength, normalizeToArray, number, pattern, required, resolveRendererChildren, ril, runValidators, runValidatorsAsync, url, validateRequired, when, zodFieldValidator, zodFormValidator };
794
+ export { type ComponentConfig, type ComponentRenderProps, type ComponentRenderer, type ComponentRendererBaseProps, ComponentRendererWrapper, type ComponentRendererWrapperProps, type ConditionBuilder as Condition, type ConditionBuilder, type ConditionConfig, type ConditionEvaluator, type ConditionOperator, type ConditionValue, type ConditionalBehavior, type CustomStepRenderer, type FieldRenderer, type FieldRendererProps, type FieldValidationConfig, type FieldValidator, type FormBodyRenderer, type FormBodyRendererProps, type FormComponentRendererProps, type FormConfiguration, type FormFieldConfig, type FormFieldRow, type FormRenderConfig, type FormRowRenderer, type FormRowRendererProps, type FormSubmitButtonRenderer, type FormSubmitButtonRendererProps, type FormValidationConfig, type FormValidator, IdGenerator, type LogicalOperator, type RendererChildrenFunction, type RilayLicenseConfig, type StepConditionalBehavior, type StepConfig, type StepDataHelper, type ValidationAdapter, type ValidationContext, type ValidationError, type ValidationResult, type ValidationSchema, type WorkflowAnalytics, type WorkflowComponentRendererBaseProps, type WorkflowConfig, type WorkflowContext, type WorkflowNextButtonRenderer, type WorkflowNextButtonRendererProps, type WorkflowPlugin, type WorkflowPreviousButtonRenderer, type WorkflowPreviousButtonRendererProps, type WorkflowRenderConfig, type WorkflowSkipButtonRenderer, type WorkflowSkipButtonRendererProps, type WorkflowStepperRenderer, type WorkflowStepperRendererProps, async, combineValidationResults, configureObject, createValidationContext, createValidationResult, custom, deepClone, email, ensureUnique, evaluateCondition, matchField, max, maxLength, mergeInto, min, minLength, normalizeToArray, number, pattern, required, resolveRendererChildren, ril, runValidators, runValidatorsAsync, url, validateRequired, validateWhen, when };
package/dist/index.d.ts CHANGED
@@ -1,20 +1,101 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default from 'react';
3
3
 
4
+ type ConditionOperator = 'equals' | 'notEquals' | 'greaterThan' | 'lessThan' | 'greaterThanOrEqual' | 'lessThanOrEqual' | 'contains' | 'notContains' | 'in' | 'notIn' | 'matches' | 'exists' | 'notExists';
5
+ type LogicalOperator = 'and' | 'or';
6
+ type ConditionValue = string | number | boolean | null | undefined | Array<string | number | boolean>;
7
+ interface ConditionConfig {
8
+ field: string;
9
+ operator: ConditionOperator;
10
+ value?: ConditionValue;
11
+ conditions?: ConditionConfig[];
12
+ logicalOperator?: LogicalOperator;
13
+ }
14
+ type ConditionEvaluator = (data: Record<string, any>) => boolean;
15
+ interface ConditionBuilder extends ConditionConfig {
16
+ equals(value: ConditionValue): ConditionBuilder;
17
+ notEquals(value: ConditionValue): ConditionBuilder;
18
+ greaterThan(value: number): ConditionBuilder;
19
+ lessThan(value: number): ConditionBuilder;
20
+ greaterThanOrEqual(value: number): ConditionBuilder;
21
+ lessThanOrEqual(value: number): ConditionBuilder;
22
+ contains(value: string): ConditionBuilder;
23
+ notContains(value: string): ConditionBuilder;
24
+ in(values: Array<string | number | boolean>): ConditionBuilder;
25
+ notIn(values: Array<string | number | boolean>): ConditionBuilder;
26
+ matches(pattern: string | RegExp): ConditionBuilder;
27
+ exists(): ConditionBuilder;
28
+ notExists(): ConditionBuilder;
29
+ and(condition: ConditionBuilder | ConditionConfig): ConditionBuilder;
30
+ or(condition: ConditionBuilder | ConditionConfig): ConditionBuilder;
31
+ build(): ConditionConfig;
32
+ evaluate(data: Record<string, any>): boolean;
33
+ }
34
+ declare function when(field: string): ConditionBuilder;
35
+ declare function evaluateCondition(condition: ConditionConfig, data: Record<string, any>): boolean;
36
+
37
+ /**
38
+ * Validation result for async operations
39
+ */
40
+ interface AsyncValidationResult {
41
+ isValid: boolean;
42
+ errors: string[];
43
+ warnings?: string[];
44
+ }
45
+ /**
46
+ * Interface publique pour les instances Rilay
47
+ * Expose uniquement les méthodes nécessaires à l'API publique
48
+ */
49
+ interface RilayInstance<C> {
50
+ addComponent<NewType extends string, TProps = any>(type: NewType, config: Omit<ComponentConfig<TProps>, 'id' | 'type'>): RilayInstance<C & {
51
+ [K in NewType]: TProps;
52
+ }>;
53
+ configure(config: Partial<FormRenderConfig & WorkflowRenderConfig>): RilayInstance<C>;
54
+ getComponent<T extends keyof C & string>(id: T): ComponentConfig<C[T]> | undefined;
55
+ getComponent(id: string): ComponentConfig | undefined;
56
+ getAllComponents(): ComponentConfig[];
57
+ hasComponent(id: string): boolean;
58
+ getFormRenderConfig(): FormRenderConfig;
59
+ getWorkflowRenderConfig(): WorkflowRenderConfig;
60
+ getStats(): {
61
+ total: number;
62
+ byType: Record<string, number>;
63
+ hasCustomRenderers: {
64
+ row: boolean;
65
+ body: boolean;
66
+ submitButton: boolean;
67
+ field: boolean;
68
+ stepper: boolean;
69
+ workflowNextButton: boolean;
70
+ workflowPreviousButton: boolean;
71
+ workflowSkipButton: boolean;
72
+ };
73
+ };
74
+ validate(): string[];
75
+ validateAsync(): Promise<AsyncValidationResult>;
76
+ clone(): RilayInstance<C>;
77
+ removeComponent(id: string): RilayInstance<C>;
78
+ clear(): RilayInstance<C>;
79
+ }
4
80
  /**
5
81
  * Main configuration class for Rilay form components and workflows
6
- * Manages component registration, retrieval, and configuration
82
+ * Manages component registration, retrieval, and configuration with immutable API
7
83
  */
8
- declare class ril<C> {
84
+ declare class ril<C> implements RilayInstance<C> {
9
85
  private components;
10
86
  private formRenderConfig;
11
87
  private workflowRenderConfig;
88
+ /**
89
+ * Static factory method to create a new ril instance
90
+ */
12
91
  static create<CT>(): ril<CT>;
13
92
  /**
14
- * Add a component to the configuration
93
+ * Add a component to the configuration (immutable)
94
+ * Returns a new instance with the added component
95
+ *
15
96
  * @param type - The component type (e.g., 'text', 'email', 'heading'), used as a unique identifier.
16
97
  * @param config - Component configuration without id and type
17
- * @returns The ril instance for chaining
98
+ * @returns A new ril instance with the added component
18
99
  *
19
100
  * @example
20
101
  * ```typescript
@@ -34,58 +115,33 @@ declare class ril<C> {
34
115
  [K in NewType]: TProps;
35
116
  }>;
36
117
  /**
37
- * Universal configuration method for all renderer types
118
+ * Universal configuration method with deep merge support (immutable)
38
119
  *
39
120
  * This method provides a unified API to configure both form and workflow renderers
40
- * in a single call, automatically categorizing and applying the appropriate configurations.
121
+ * in a single call, automatically categorizing and applying the appropriate configurations
122
+ * using recursive deep merge.
41
123
  *
42
124
  * @param config - Configuration object containing renderer settings
43
- * @param config.rowRenderer - Custom renderer for form rows (form-specific)
44
- * @param config.bodyRenderer - Custom renderer for form body container (form-specific)
45
- * @param config.submitButtonRenderer - Custom renderer for form submit buttons (form-specific)
46
- * @param config.fieldRenderer - Custom renderer for individual form fields (form-specific)
47
- * @param config.stepperRenderer - Custom renderer for workflow step navigation (workflow-specific)
48
- * @param config.nextButtonRenderer - Custom renderer for workflow next buttons (workflow-specific)
49
- * @param config.previousButtonRenderer - Custom renderer for workflow previous buttons (workflow-specific)
50
- * @param config.skipButtonRenderer - Custom renderer for workflow skip buttons (workflow-specific)
51
- *
52
- * @returns The ril instance for method chaining
125
+ * @returns A new ril instance with the updated configuration
53
126
  *
54
127
  * @example
55
128
  * ```typescript
56
- * // Configure form renderers only
129
+ * // Configure with nested settings
57
130
  * const config = ril.create()
58
131
  * .configure({
59
132
  * rowRenderer: CustomRowRenderer,
60
- * submitButtonRenderer: CustomSubmitButton
61
- * });
62
- *
63
- * // Configure workflow renderers only
64
- * const config = ril.create()
65
- * .configure({
66
- * stepperRenderer: CustomStepper,
67
- * nextButtonRenderer: CustomNextButton
68
- * });
69
- *
70
- * // Configure both form and workflow renderers
71
- * const config = ril.create()
72
- * .configure({
73
- * // Form renderers
74
- * rowRenderer: CustomRowRenderer,
75
- * fieldRenderer: CustomFieldRenderer,
76
- * // Workflow renderers
77
- * stepperRenderer: CustomStepper,
78
- * nextButtonRenderer: CustomNextButton
133
+ * submitButtonRenderer: CustomSubmitButton,
134
+ * // Deep nested configuration example
135
+ * formStyles: {
136
+ * layout: {
137
+ * spacing: 'large',
138
+ * alignment: 'center'
139
+ * }
140
+ * }
79
141
  * });
80
142
  * ```
81
- *
82
- * @remarks
83
- * - Renderers are automatically categorized into form or workflow configurations
84
- * - Existing configurations are merged, not replaced entirely
85
- * - Invalid renderer keys are silently ignored
86
- * - This method replaces individual setter methods for better DX
87
143
  */
88
- configure(config: Partial<FormRenderConfig & WorkflowRenderConfig>): this;
144
+ configure(config: Partial<FormRenderConfig & WorkflowRenderConfig>): ril<C>;
89
145
  /**
90
146
  * Configuration getters
91
147
  */
@@ -97,8 +153,25 @@ declare class ril<C> {
97
153
  getComponent<T extends keyof C & string>(id: T): ComponentConfig<C[T]> | undefined;
98
154
  getAllComponents(): ComponentConfig[];
99
155
  hasComponent(id: string): boolean;
100
- removeComponent(id: string): boolean;
101
- clear(): void;
156
+ /**
157
+ * Remove a component from the configuration (immutable)
158
+ * Returns a new instance without the specified component
159
+ *
160
+ * @param id - The component ID to remove
161
+ * @returns A new ril instance without the component
162
+ */
163
+ removeComponent(id: string): ril<C>;
164
+ /**
165
+ * Clear all components from the configuration (immutable)
166
+ * Returns a new instance with no components
167
+ *
168
+ * @returns A new empty ril instance
169
+ */
170
+ clear(): ril<C>;
171
+ /**
172
+ * Create a deep copy of the current ril instance
173
+ */
174
+ clone(): ril<C>;
102
175
  /**
103
176
  * Enhanced statistics with more detailed information
104
177
  */
@@ -117,9 +190,14 @@ declare class ril<C> {
117
190
  };
118
191
  };
119
192
  /**
120
- * Enhanced validation using shared utilities
193
+ * Synchronous validation using shared utilities
121
194
  */
122
195
  validate(): string[];
196
+ /**
197
+ * Asynchronous validation with structured error handling
198
+ * Ideal for CI/CD pipelines and advanced validation scenarios
199
+ */
200
+ validateAsync(): Promise<AsyncValidationResult>;
123
201
  }
124
202
 
125
203
  interface RilayLicenseConfig {
@@ -207,11 +285,22 @@ interface ComponentConfig<TProps = any> {
207
285
  readonly useFieldRenderer?: boolean;
208
286
  readonly validation?: FieldValidationConfig;
209
287
  }
288
+ interface ConditionalBehavior {
289
+ readonly visible?: ConditionConfig;
290
+ readonly disabled?: ConditionConfig;
291
+ readonly required?: ConditionConfig;
292
+ readonly readonly?: ConditionConfig;
293
+ }
294
+ interface StepConditionalBehavior {
295
+ readonly visible?: ConditionConfig;
296
+ readonly skippable?: ConditionConfig;
297
+ }
210
298
  interface FormFieldConfig {
211
299
  readonly id: string;
212
300
  readonly componentId: string;
213
301
  readonly props: Record<string, any>;
214
302
  readonly validation?: FieldValidationConfig;
303
+ readonly conditions?: ConditionalBehavior;
215
304
  }
216
305
  interface FormFieldRow {
217
306
  readonly id: string;
@@ -311,6 +400,7 @@ interface StepConfig {
311
400
  readonly formConfig: FormConfiguration;
312
401
  readonly allowSkip?: boolean;
313
402
  readonly renderer?: CustomStepRenderer;
403
+ readonly conditions?: StepConditionalBehavior;
314
404
  readonly onAfterValidation?: (stepData: Record<string, any>, helper: StepDataHelper, context: WorkflowContext) => void | Promise<void>;
315
405
  }
316
406
  type CustomStepRenderer = (props: StepConfig) => React__default.ReactElement;
@@ -671,13 +761,13 @@ declare function matchField(targetFieldId: string, message?: string): FieldValid
671
761
  *
672
762
  * @example
673
763
  * ```typescript
674
- * const conditionalValidator = when(
764
+ * const conditionalValidator = validateWhen(
675
765
  * (value, context) => context.allFormData?.userType === 'premium',
676
766
  * required('Premium users must provide this field')
677
767
  * );
678
768
  * ```
679
769
  */
680
- declare function when<T>(condition: (value: T, context: ValidationContext) => boolean, validator: FieldValidator<T>): FieldValidator<T>;
770
+ declare function validateWhen<T>(condition: (value: T, context: ValidationContext) => boolean, validator: FieldValidator<T>): FieldValidator<T>;
681
771
  /**
682
772
  * Creates an async custom validator from a validation function
683
773
  *
@@ -701,129 +791,4 @@ declare function when<T>(condition: (value: T, context: ValidationContext) => bo
701
791
  */
702
792
  declare function async<T>(validateFn: (value: T, context: ValidationContext) => Promise<boolean>, message: string, code?: string): FieldValidator<T>;
703
793
 
704
- /**
705
- * @fileoverview Validation adapters for popular validation libraries
706
- *
707
- * This module provides adapters that integrate popular validation libraries
708
- * like Zod with Rilay's validation system. Adapters convert external schemas
709
- * into Rilay validators while maintaining type safety and error handling.
710
- */
711
-
712
- /**
713
- * Generic schema interface that Zod and similar libraries implement
714
- */
715
- interface ZodLikeSchema<T = any> {
716
- parse(value: unknown): T;
717
- safeParse(value: unknown): {
718
- success: true;
719
- data: T;
720
- } | {
721
- success: false;
722
- error: {
723
- errors: Array<{
724
- message: string;
725
- path: (string | number)[];
726
- }>;
727
- };
728
- };
729
- }
730
- /**
731
- * Zod validation adapter that converts Zod schemas into Rilay validators
732
- *
733
- * This adapter provides seamless integration with Zod schemas, automatically
734
- * converting Zod validation errors into Rilay ValidationError objects while
735
- * preserving error messages and field paths.
736
- *
737
- * @example
738
- * ```typescript
739
- * import { z } from 'zod';
740
- * import { createZodAdapter } from '@rilaykit/core';
741
- *
742
- * const zodAdapter = createZodAdapter();
743
- * const emailValidator = zodAdapter.createFieldValidator(
744
- * z.string().email('Invalid email format')
745
- * );
746
- * ```
747
- */
748
- declare class ZodValidationAdapter implements ValidationAdapter<ZodLikeSchema> {
749
- readonly name = "ZodValidationAdapter";
750
- readonly version = "1.0.0";
751
- /**
752
- * Creates a field validator from a Zod schema
753
- *
754
- * @param schema - The Zod schema to convert
755
- * @returns A FieldValidator function compatible with Rilay
756
- *
757
- * @example
758
- * ```typescript
759
- * const emailSchema = z.string().email();
760
- * const validator = adapter.createFieldValidator(emailSchema);
761
- * ```
762
- */
763
- createFieldValidator<T>(schema: ZodLikeSchema<T>): FieldValidator<T>;
764
- /**
765
- * Creates a form validator from a Zod object schema
766
- *
767
- * @param schema - The Zod object schema to convert
768
- * @returns A FormValidator function compatible with Rilay
769
- *
770
- * @example
771
- * ```typescript
772
- * const formSchema = z.object({
773
- * email: z.string().email(),
774
- * password: z.string().min(8)
775
- * });
776
- * const validator = adapter.createFormValidator(formSchema);
777
- * ```
778
- */
779
- createFormValidator<T>(schema: ZodLikeSchema<T>): FormValidator<T>;
780
- }
781
- /**
782
- * Creates a new Zod validation adapter instance
783
- *
784
- * @returns A configured ZodValidationAdapter instance
785
- *
786
- * @example
787
- * ```typescript
788
- * const adapter = createZodAdapter();
789
- * ```
790
- */
791
- declare function createZodAdapter(): ZodValidationAdapter;
792
- /**
793
- * Helper function to create a field validator directly from a Zod schema
794
- *
795
- * This is a convenience function that creates an adapter and field validator
796
- * in a single call, useful for simple use cases.
797
- *
798
- * @param schema - The Zod schema to convert
799
- * @returns A FieldValidator function
800
- *
801
- * @example
802
- * ```typescript
803
- * import { z } from 'zod';
804
- * import { zodFieldValidator } from '@rilaykit/core';
805
- *
806
- * const emailValidator = zodFieldValidator(z.string().email());
807
- * ```
808
- */
809
- declare function zodFieldValidator<T>(schema: ZodLikeSchema<T>): FieldValidator<T>;
810
- /**
811
- * Helper function to create a form validator directly from a Zod schema
812
- *
813
- * @param schema - The Zod object schema to convert
814
- * @returns A FormValidator function
815
- *
816
- * @example
817
- * ```typescript
818
- * import { z } from 'zod';
819
- * import { zodFormValidator } from '@rilaykit/core';
820
- *
821
- * const formValidator = zodFormValidator(z.object({
822
- * email: z.string().email(),
823
- * password: z.string().min(8)
824
- * }));
825
- * ```
826
- */
827
- declare function zodFormValidator<T>(schema: ZodLikeSchema<T>): FormValidator<T>;
828
-
829
- export { type ComponentConfig, type ComponentRenderProps, type ComponentRenderer, type ComponentRendererBaseProps, ComponentRendererWrapper, type ComponentRendererWrapperProps, type CustomStepRenderer, type FieldRenderer, type FieldRendererProps, type FieldValidationConfig, type FieldValidator, type FormBodyRenderer, type FormBodyRendererProps, type FormComponentRendererProps, type FormConfiguration, type FormFieldConfig, type FormFieldRow, type FormRenderConfig, type FormRowRenderer, type FormRowRendererProps, type FormSubmitButtonRenderer, type FormSubmitButtonRendererProps, type FormValidationConfig, type FormValidator, IdGenerator, type RendererChildrenFunction, type RilayLicenseConfig, type StepConfig, type StepDataHelper, type ValidationAdapter, type ValidationContext, type ValidationError, type ValidationResult, type ValidationSchema, type WorkflowAnalytics, type WorkflowComponentRendererBaseProps, type WorkflowConfig, type WorkflowContext, type WorkflowNextButtonRenderer, type WorkflowNextButtonRendererProps, type WorkflowPlugin, type WorkflowPreviousButtonRenderer, type WorkflowPreviousButtonRendererProps, type WorkflowRenderConfig, type WorkflowSkipButtonRenderer, type WorkflowSkipButtonRendererProps, type WorkflowStepperRenderer, type WorkflowStepperRendererProps, async, combineValidationResults, configureObject, createValidationContext, createValidationResult, createZodAdapter, custom, deepClone, email, ensureUnique, matchField, max, maxLength, mergeInto, min, minLength, normalizeToArray, number, pattern, required, resolveRendererChildren, ril, runValidators, runValidatorsAsync, url, validateRequired, when, zodFieldValidator, zodFormValidator };
794
+ export { type ComponentConfig, type ComponentRenderProps, type ComponentRenderer, type ComponentRendererBaseProps, ComponentRendererWrapper, type ComponentRendererWrapperProps, type ConditionBuilder as Condition, type ConditionBuilder, type ConditionConfig, type ConditionEvaluator, type ConditionOperator, type ConditionValue, type ConditionalBehavior, type CustomStepRenderer, type FieldRenderer, type FieldRendererProps, type FieldValidationConfig, type FieldValidator, type FormBodyRenderer, type FormBodyRendererProps, type FormComponentRendererProps, type FormConfiguration, type FormFieldConfig, type FormFieldRow, type FormRenderConfig, type FormRowRenderer, type FormRowRendererProps, type FormSubmitButtonRenderer, type FormSubmitButtonRendererProps, type FormValidationConfig, type FormValidator, IdGenerator, type LogicalOperator, type RendererChildrenFunction, type RilayLicenseConfig, type StepConditionalBehavior, type StepConfig, type StepDataHelper, type ValidationAdapter, type ValidationContext, type ValidationError, type ValidationResult, type ValidationSchema, type WorkflowAnalytics, type WorkflowComponentRendererBaseProps, type WorkflowConfig, type WorkflowContext, type WorkflowNextButtonRenderer, type WorkflowNextButtonRendererProps, type WorkflowPlugin, type WorkflowPreviousButtonRenderer, type WorkflowPreviousButtonRendererProps, type WorkflowRenderConfig, type WorkflowSkipButtonRenderer, type WorkflowSkipButtonRendererProps, type WorkflowStepperRenderer, type WorkflowStepperRendererProps, async, combineValidationResults, configureObject, createValidationContext, createValidationResult, custom, deepClone, email, ensureUnique, evaluateCondition, matchField, max, maxLength, mergeInto, min, minLength, normalizeToArray, number, pattern, required, resolveRendererChildren, ril, runValidators, runValidatorsAsync, url, validateRequired, validateWhen, when };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- 'use strict';function R(e,r){return typeof e=="function"?e(r):e}function v({children:e,renderAs:r,renderer:t,name:n,props:o}){if(r==="children"||r===true){if(typeof e!="function")throw new Error(`When renderAs="children" is used, children must be a function that returns React elements for ${n}`);return e(o)}if(!t)throw new Error(`No renderer provided for ${n}`);if(typeof t!="function")throw new Error(`Renderer must be a function for ${n}`);let l={...o,children:R(e,o)};return t(l)}function W(e,r){return {...e,...r}}function C(e,r){let t=e.filter((n,o)=>e.indexOf(n)!==o);if(t.length>0)throw new Error(`Duplicate ${r} IDs: ${t.join(", ")}`)}function z(e,r,t){if(e.filter(o=>r.some(i=>!o[i])).length>0)throw new Error(`Missing required fields in ${t}: ${r.join(", ")}`)}var V=class{constructor(){this.counters=new Map;}next(r){let t=this.counters.get(r)||0;return this.counters.set(r,t+1),`${r}-${t+1}`}reset(r){r?this.counters.delete(r):this.counters.clear();}};function U(e){return Array.isArray(e)?e:[e]}function T(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(Array.isArray(e))return e.map(t=>T(t));let r={};for(let t in e)Object.prototype.hasOwnProperty.call(e,t)&&(r[t]=T(e[t]));return r}function u(e,r,t){let n={...e};for(let o in r)t&&!t.includes(o)||r[o]!==void 0&&(n[o]=r[o]);return n}var f=class e{constructor(){this.components=new Map;this.formRenderConfig={};this.workflowRenderConfig={};}static create(){return new e}addComponent(r,t){let n={id:r,type:r,...t};return this.components.set(r,n),this}configure(r){let t=["rowRenderer","bodyRenderer","submitButtonRenderer","fieldRenderer"],n=["stepperRenderer","nextButtonRenderer","previousButtonRenderer","skipButtonRenderer"],o={},i={};for(let[l,g]of Object.entries(r))t.includes(l)?o[l]=g:n.includes(l)&&(i[l]=g);return this.formRenderConfig=u(this.formRenderConfig,o),this.workflowRenderConfig=u(this.workflowRenderConfig,i),this}getFormRenderConfig(){return {...this.formRenderConfig}}getWorkflowRenderConfig(){return {...this.workflowRenderConfig}}getComponent(r){return this.components.get(r)}getAllComponents(){return Array.from(this.components.values())}hasComponent(r){return this.components.has(r)}removeComponent(r){return this.components.delete(r)}clear(){this.components.clear();}getStats(){let r=Array.from(this.components.values());return {total:r.length,byType:r.reduce((t,n)=>(t[n.type]=(t[n.type]||0)+1,t),{}),hasCustomRenderers:{row:!!this.formRenderConfig.rowRenderer,body:!!this.formRenderConfig.bodyRenderer,submitButton:!!this.formRenderConfig.submitButtonRenderer,field:!!this.formRenderConfig.fieldRenderer,stepper:!!this.workflowRenderConfig.stepperRenderer,workflowNextButton:!!this.workflowRenderConfig.nextButtonRenderer,workflowPreviousButton:!!this.workflowRenderConfig.previousButtonRenderer,workflowSkipButton:!!this.workflowRenderConfig.skipButtonRenderer}}}validate(){let r=[],t=Array.from(this.components.values()),n=t.map(i=>i.id);try{C(n,"component");}catch(i){r.push(i instanceof Error?i.message:String(i));}let o=t.filter(i=>!i.renderer);return o.length>0&&r.push(`Components without renderer: ${o.map(i=>i.id).join(", ")}`),r}};function d(e,r=[]){return {isValid:e,errors:[...r]}}function a(){return d(true,[])}function s(e,r,t){return d(false,[{message:e,code:r,path:t}])}function c(e){let r=[],t=true;for(let n of e)n.isValid||(t=false),r.push(...n.errors);return d(t,r)}function h(e,r,t){let n=e.map(o=>{let i=o(r,t);if(i instanceof Promise)throw new Error("Use runValidatorsAsync for async validators");return i});return c(n)}async function y(e,r,t){let n=await Promise.all(e.map(o=>o(r,t)));return c(n)}function w(e={}){return {fieldId:e.fieldId,formId:e.formId,stepId:e.stepId,workflowId:e.workflowId,allFormData:e.allFormData||{},stepData:e.stepData||{},workflowData:e.workflowData||{}}}function x(e="This field is required"){return r=>r==null||r===""||Array.isArray(r)&&r.length===0?s(e,"REQUIRED"):a()}function F(e,r){return t=>!t||t.length<e?s(r||`Must be at least ${e} characters long`,"MIN_LENGTH",`length.${e}`):a()}function A(e,r){return t=>t&&t.length>e?s(r||`Must be no more than ${e} characters long`,"MAX_LENGTH",`length.${e}`):a()}function b(e,r){return t=>t&&!e.test(t)?s(r||"Invalid format","PATTERN_MISMATCH",`pattern.${e.source}`):a()}function k(e="Please enter a valid email address"){let r=/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;return t=>t&&!r.test(t)?s(e,"INVALID_EMAIL"):a()}function N(e="Please enter a valid URL"){let r=/^https?:\/\/(?:[-\w.])+(?:\:[0-9]+)?(?:\/(?:[\w/_.])*(?:\?(?:[\w&=%.])*)?(?:\#(?:[\w.])*)?)?$/;return t=>t&&!r.test(t)?s(e,"INVALID_URL"):a()}function E(e="Must be a valid number"){return r=>{let t=typeof r=="string"?Number.parseFloat(r):r;return Number.isNaN(t)||!Number.isFinite(t)?s(e,"INVALID_NUMBER"):a()}}function I(e,r){return t=>{let n=typeof t=="string"?Number.parseFloat(t):t;return !Number.isNaN(n)&&n<e?s(r||`Must be at least ${e}`,"MIN_VALUE",`min.${e}`):a()}}function P(e,r){return t=>{let n=typeof t=="string"?Number.parseFloat(t):t;return !Number.isNaN(n)&&n>e?s(r||`Must be no more than ${e}`,"MAX_VALUE",`max.${e}`):a()}}function L(e,r,t){return (n,o)=>e(n,o)?a():s(r,t||"CUSTOM_VALIDATION_FAILED")}function B(e,r){return (t,n)=>{let o=n.allFormData?.[e];return t!==o?s(r||"Fields must match","FIELD_MISMATCH",`match.${e}`):a()}}function D(e,r){return (t,n)=>e(t,n)?r(t,n):a()}function $(e,r,t){return async(n,o)=>{try{return await e(n,o)?a():s(r,t||"ASYNC_VALIDATION_FAILED")}catch(i){return s(i instanceof Error?i.message:"Async validation error","ASYNC_ERROR")}}}var p=class{constructor(){this.name="ZodValidationAdapter";this.version="1.0.0";}createFieldValidator(r){return (t,n)=>{try{let o=r.safeParse(t);return o.success?a():{isValid:!1,errors:o.error.errors.map(l=>({message:l.message,code:"VALIDATION_ERROR",path:l.path.join(".")}))}}catch(o){return s(o instanceof Error?o.message:"Validation failed","VALIDATION_ERROR")}}}createFormValidator(r){return (t,n)=>{try{let o=r.safeParse(t);return o.success?a():{isValid:!1,errors:o.error.errors.map(l=>({message:l.message,code:"VALIDATION_ERROR",path:l.path.join(".")}))}}catch(o){return s(o instanceof Error?o.message:"Form validation failed","VALIDATION_ERROR")}}}};function m(){return new p}function _(e){return m().createFieldValidator(e)}function O(e){return m().createFormValidator(e)}exports.ComponentRendererWrapper=v;exports.IdGenerator=V;exports.async=$;exports.combineValidationResults=c;exports.configureObject=u;exports.createValidationContext=w;exports.createValidationResult=d;exports.createZodAdapter=m;exports.custom=L;exports.deepClone=T;exports.email=k;exports.ensureUnique=C;exports.matchField=B;exports.max=P;exports.maxLength=A;exports.mergeInto=W;exports.min=I;exports.minLength=F;exports.normalizeToArray=U;exports.number=E;exports.pattern=b;exports.required=x;exports.resolveRendererChildren=R;exports.ril=f;exports.runValidators=h;exports.runValidatorsAsync=y;exports.url=N;exports.validateRequired=z;exports.when=D;exports.zodFieldValidator=_;exports.zodFormValidator=O;
1
+ 'use strict';function T(n,e){return typeof n=="function"?n(e):n}function z({children:n,renderAs:e,renderer:r,name:t,props:o}){if(e==="children"||e===true){if(typeof n!="function")throw new Error(`When renderAs="children" is used, children must be a function that returns React elements for ${t}`);return n(o)}if(!r)throw new Error(`No renderer provided for ${t}`);if(typeof r!="function")throw new Error(`Renderer must be a function for ${t}`);let d={...o,children:T(n,o)};return r(d)}function j(n,e){return {...n,...e}}function V(n,e){let r=n.filter((t,o)=>n.indexOf(t)!==o);if(r.length>0)throw new Error(`Duplicate ${e} IDs: ${r.join(", ")}`)}function H(n,e,r){if(n.filter(o=>e.some(i=>!o[i])).length>0)throw new Error(`Missing required fields in ${r}: ${e.join(", ")}`)}var b=class{constructor(){this.counters=new Map;}next(e){let r=this.counters.get(e)||0;return this.counters.set(e,r+1),`${e}-${r+1}`}reset(e){e?this.counters.delete(e):this.counters.clear();}};function X(n){return Array.isArray(n)?n:[n]}function x(n){if(n===null||typeof n!="object")return n;if(n instanceof Date)return new Date(n.getTime());if(Array.isArray(n))return n.map(r=>x(r));let e={};for(let r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=x(n[r]));return e}function Y(n,e,r){let t={...n};for(let o in e)r&&!r.includes(o)||e[o]!==void 0&&(t[o]=e[o]);return t}var C=class extends Error{constructor(r,t,o){super(r);this.code=t;this.meta=o;this.name="RilayError";}},g=class extends C{constructor(e,r){super(e,"VALIDATION_ERROR",r),this.name="ValidationError";}};function p(n,e){let r={...n};for(let t in e){let o=e[t],i=r[t];o&&typeof o=="object"&&!Array.isArray(o)&&i&&typeof i=="object"&&!Array.isArray(i)?r[t]=p(i,o):r[t]=o;}return r}var h=class n{constructor(){this.components=new Map;this.formRenderConfig={};this.workflowRenderConfig={};}static create(){return new n}addComponent(e,r){let t={id:e,type:e,...r},o=new n;return o.components=new Map(this.components),o.formRenderConfig={...this.formRenderConfig},o.workflowRenderConfig={...this.workflowRenderConfig},o.components.set(e,t),o}configure(e){let r=["rowRenderer","bodyRenderer","submitButtonRenderer","fieldRenderer"],t=["stepperRenderer","nextButtonRenderer","previousButtonRenderer","skipButtonRenderer"],o={},i={};for(let[f,c]of Object.entries(e))r.includes(f)?o[f]=c:t.includes(f)&&(i[f]=c);let d=new n;return d.components=new Map(this.components),d.formRenderConfig=p(this.formRenderConfig,o),d.workflowRenderConfig=p(this.workflowRenderConfig,i),d}getFormRenderConfig(){return {...this.formRenderConfig}}getWorkflowRenderConfig(){return {...this.workflowRenderConfig}}getComponent(e){return this.components.get(e)}getAllComponents(){return Array.from(this.components.values())}hasComponent(e){return this.components.has(e)}removeComponent(e){let r=new n;return r.components=new Map(this.components),r.formRenderConfig={...this.formRenderConfig},r.workflowRenderConfig={...this.workflowRenderConfig},r.components.delete(e),r}clear(){let e=new n;return e.formRenderConfig={...this.formRenderConfig},e.workflowRenderConfig={...this.workflowRenderConfig},e}clone(){let e=new n;return e.components=new Map(this.components),e.formRenderConfig=p({},this.formRenderConfig),e.workflowRenderConfig=p({},this.workflowRenderConfig),e}getStats(){let e=Array.from(this.components.values());return {total:e.length,byType:e.reduce((r,t)=>(r[t.type]=(r[t.type]||0)+1,r),{}),hasCustomRenderers:{row:!!this.formRenderConfig.rowRenderer,body:!!this.formRenderConfig.bodyRenderer,submitButton:!!this.formRenderConfig.submitButtonRenderer,field:!!this.formRenderConfig.fieldRenderer,stepper:!!this.workflowRenderConfig.stepperRenderer,workflowNextButton:!!this.workflowRenderConfig.nextButtonRenderer,workflowPreviousButton:!!this.workflowRenderConfig.previousButtonRenderer,workflowSkipButton:!!this.workflowRenderConfig.skipButtonRenderer}}}validate(){let e=[],r=Array.from(this.components.values()),t=r.map(u=>u.id);try{V(t,"component");}catch(u){e.push(u instanceof Error?u.message:String(u));}let o=r.filter(u=>!u.renderer);o.length>0&&e.push(`Components without renderer: ${o.map(u=>u.id).join(", ")}`);let i=Object.keys(this.formRenderConfig),d=Object.keys(this.workflowRenderConfig),f=["rowRenderer","bodyRenderer","submitButtonRenderer","fieldRenderer"],c=["stepperRenderer","nextButtonRenderer","previousButtonRenderer","skipButtonRenderer"],l=i.filter(u=>!f.includes(u)),w=d.filter(u=>!c.includes(u));return l.length>0&&e.push(`Invalid form renderer keys: ${l.join(", ")}`),w.length>0&&e.push(`Invalid workflow renderer keys: ${w.join(", ")}`),e}async validateAsync(){let e=[],r=[],t=Array.from(this.components.values());try{let o=this.validate();e.push(...o);let i=t.map(async l=>l.renderer&&typeof l.renderer!="function"&&typeof l.renderer!="object"?`Component "${l.id}" has invalid renderer type: ${typeof l.renderer}`:((l.id.includes(" ")||l.id.includes("-"))&&r.push(`Component "${l.id}" uses non-standard naming (contains spaces or dashes)`),null)),f=(await Promise.all(i)).filter(l=>l!==null);e.push(...f),t.length>50&&r.push("Large number of components detected. Consider splitting configuration.");let c={isValid:e.length===0,errors:e,warnings:r.length>0?r:void 0};if(!c.isValid)throw new g("Ril configuration validation failed",{errors:e,warnings:r,componentCount:t.length});return c}catch(o){throw o instanceof g?o:new g("Unexpected error during async validation",{originalError:o instanceof Error?o.message:String(o)})}}};function m(n,e=[]){return {isValid:n,errors:[...e]}}function s(){return m(true,[])}function a(n,e,r){return m(false,[{message:n,code:e,path:r}])}function R(n){let e=[],r=true;for(let t of n)t.isValid||(r=false),e.push(...t.errors);return m(r,e)}function k(n,e,r){let t=n.map(o=>{let i=o(e,r);if(i instanceof Promise)throw new Error("Use runValidatorsAsync for async validators");return i});return R(t)}async function A(n,e,r){let t=await Promise.all(n.map(o=>o(e,r)));return R(t)}function B(n={}){return {fieldId:n.fieldId,formId:n.formId,stepId:n.stepId,workflowId:n.workflowId,allFormData:n.allFormData||{},stepData:n.stepData||{},workflowData:n.workflowData||{}}}function E(n="This field is required"){return e=>e==null||e===""||Array.isArray(e)&&e.length===0?a(n,"REQUIRED"):s()}function F(n,e){return r=>!r||r.length<n?a(e||`Must be at least ${n} characters long`,"MIN_LENGTH",`length.${n}`):s()}function I(n,e){return r=>r&&r.length>n?a(e||`Must be no more than ${n} characters long`,"MAX_LENGTH",`length.${n}`):s()}function O(n,e){return r=>r&&!n.test(r)?a(e||"Invalid format","PATTERN_MISMATCH",`pattern.${n.source}`):s()}function N(n="Please enter a valid email address"){let e=/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;return r=>r&&!e.test(r)?a(n,"INVALID_EMAIL"):s()}function P(n="Please enter a valid URL"){let e=/^https?:\/\/(?:[-\w.])+(?:\:[0-9]+)?(?:\/(?:[\w/_.])*(?:\?(?:[\w&=%.])*)?(?:\#(?:[\w.])*)?)?$/;return r=>r&&!e.test(r)?a(n,"INVALID_URL"):s()}function $(n="Must be a valid number"){return e=>{let r=typeof e=="string"?Number.parseFloat(e):e;return Number.isNaN(r)||!Number.isFinite(r)?a(n,"INVALID_NUMBER"):s()}}function q(n,e){return r=>{let t=typeof r=="string"?Number.parseFloat(r):r;return !Number.isNaN(t)&&t<n?a(e||`Must be at least ${n}`,"MIN_VALUE",`min.${n}`):s()}}function L(n,e){return r=>{let t=typeof r=="string"?Number.parseFloat(r):r;return !Number.isNaN(t)&&t>n?a(e||`Must be no more than ${n}`,"MAX_VALUE",`max.${n}`):s()}}function D(n,e,r){return (t,o)=>n(t,o)?s():a(e,r||"CUSTOM_VALIDATION_FAILED")}function M(n,e){return (r,t)=>{let o=t.allFormData?.[n];return r!==o?a(e||"Fields must match","FIELD_MISMATCH",`match.${n}`):s()}}function W(n,e){return (r,t)=>n(r,t)?e(r,t):s()}function S(n,e,r){return async(t,o)=>{try{return await n(t,o)?s():a(e,r||"ASYNC_VALIDATION_FAILED")}catch(i){return a(i instanceof Error?i.message:"Async validation error","ASYNC_ERROR")}}}var y=class{constructor(e){this.field=e,this.operator="exists",this.conditions=[];}equals(e){return this.operator="equals",this.value=e,this}notEquals(e){return this.operator="notEquals",this.value=e,this}greaterThan(e){return this.operator="greaterThan",this.value=e,this}lessThan(e){return this.operator="lessThan",this.value=e,this}greaterThanOrEqual(e){return this.operator="greaterThanOrEqual",this.value=e,this}lessThanOrEqual(e){return this.operator="lessThanOrEqual",this.value=e,this}contains(e){return this.operator="contains",this.value=e,this}notContains(e){return this.operator="notContains",this.value=e,this}in(e){return this.operator="in",this.value=e,this}notIn(e){return this.operator="notIn",this.value=e,this}matches(e){return this.operator="matches",this.value=e instanceof RegExp?e.source:e,this}exists(){return this.operator="exists",this.value=void 0,this}notExists(){return this.operator="notExists",this.value=void 0,this}and(e){let r="build"in e?e.build():e,t={field:this.field,operator:this.operator,value:this.value,conditions:this.conditions,logicalOperator:this.logicalOperator};return this.field="",this.operator="exists",this.value=void 0,this.conditions=[t,r],this.logicalOperator="and",this}or(e){let r="build"in e?e.build():e,t={field:this.field,operator:this.operator,value:this.value,conditions:this.conditions,logicalOperator:this.logicalOperator};return this.field="",this.operator="exists",this.value=void 0,this.conditions=[t,r],this.logicalOperator="or",this}build(){return {field:this.field,operator:this.operator,value:this.value,conditions:this.conditions,logicalOperator:this.logicalOperator}}evaluate(e){return v(this,e)}};function se(n){return new y(n)}function v(n,e){if(n.conditions&&n.conditions.length>0){let t=n.conditions.map(o=>v(o,e));return n.logicalOperator==="or"?t.some(o=>o):t.every(o=>o)}let r=U(e,n.field);switch(n.operator){case "equals":return r===n.value;case "notEquals":return r!==n.value;case "greaterThan":return typeof r=="number"&&typeof n.value=="number"&&r>n.value;case "lessThan":return typeof r=="number"&&typeof n.value=="number"&&r<n.value;case "greaterThanOrEqual":return typeof r=="number"&&typeof n.value=="number"&&r>=n.value;case "lessThanOrEqual":return typeof r=="number"&&typeof n.value=="number"&&r<=n.value;case "contains":return typeof r=="string"&&typeof n.value=="string"&&r.includes(n.value);case "notContains":return typeof r=="string"&&typeof n.value=="string"&&!r.includes(n.value);case "in":return Array.isArray(n.value)&&n.value.includes(r);case "notIn":return Array.isArray(n.value)&&!n.value.includes(r);case "matches":return typeof r!="string"||typeof n.value!="string"?false:new RegExp(n.value).test(r);case "exists":return r!=null;case "notExists":return r==null;default:return false}}function U(n,e){let r=e.split("."),t=n;for(let o of r)if(t&&typeof t=="object"&&o in t)t=t[o];else return;return t}exports.ComponentRendererWrapper=z;exports.IdGenerator=b;exports.async=S;exports.combineValidationResults=R;exports.configureObject=Y;exports.createValidationContext=B;exports.createValidationResult=m;exports.custom=D;exports.deepClone=x;exports.email=N;exports.ensureUnique=V;exports.evaluateCondition=v;exports.matchField=M;exports.max=L;exports.maxLength=I;exports.mergeInto=j;exports.min=q;exports.minLength=F;exports.normalizeToArray=X;exports.number=$;exports.pattern=O;exports.required=E;exports.resolveRendererChildren=T;exports.ril=h;exports.runValidators=k;exports.runValidatorsAsync=A;exports.url=P;exports.validateRequired=H;exports.validateWhen=W;exports.when=se;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- function R(e,r){return typeof e=="function"?e(r):e}function v({children:e,renderAs:r,renderer:t,name:n,props:o}){if(r==="children"||r===true){if(typeof e!="function")throw new Error(`When renderAs="children" is used, children must be a function that returns React elements for ${n}`);return e(o)}if(!t)throw new Error(`No renderer provided for ${n}`);if(typeof t!="function")throw new Error(`Renderer must be a function for ${n}`);let l={...o,children:R(e,o)};return t(l)}function W(e,r){return {...e,...r}}function C(e,r){let t=e.filter((n,o)=>e.indexOf(n)!==o);if(t.length>0)throw new Error(`Duplicate ${r} IDs: ${t.join(", ")}`)}function z(e,r,t){if(e.filter(o=>r.some(i=>!o[i])).length>0)throw new Error(`Missing required fields in ${t}: ${r.join(", ")}`)}var V=class{constructor(){this.counters=new Map;}next(r){let t=this.counters.get(r)||0;return this.counters.set(r,t+1),`${r}-${t+1}`}reset(r){r?this.counters.delete(r):this.counters.clear();}};function U(e){return Array.isArray(e)?e:[e]}function T(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(Array.isArray(e))return e.map(t=>T(t));let r={};for(let t in e)Object.prototype.hasOwnProperty.call(e,t)&&(r[t]=T(e[t]));return r}function u(e,r,t){let n={...e};for(let o in r)t&&!t.includes(o)||r[o]!==void 0&&(n[o]=r[o]);return n}var f=class e{constructor(){this.components=new Map;this.formRenderConfig={};this.workflowRenderConfig={};}static create(){return new e}addComponent(r,t){let n={id:r,type:r,...t};return this.components.set(r,n),this}configure(r){let t=["rowRenderer","bodyRenderer","submitButtonRenderer","fieldRenderer"],n=["stepperRenderer","nextButtonRenderer","previousButtonRenderer","skipButtonRenderer"],o={},i={};for(let[l,g]of Object.entries(r))t.includes(l)?o[l]=g:n.includes(l)&&(i[l]=g);return this.formRenderConfig=u(this.formRenderConfig,o),this.workflowRenderConfig=u(this.workflowRenderConfig,i),this}getFormRenderConfig(){return {...this.formRenderConfig}}getWorkflowRenderConfig(){return {...this.workflowRenderConfig}}getComponent(r){return this.components.get(r)}getAllComponents(){return Array.from(this.components.values())}hasComponent(r){return this.components.has(r)}removeComponent(r){return this.components.delete(r)}clear(){this.components.clear();}getStats(){let r=Array.from(this.components.values());return {total:r.length,byType:r.reduce((t,n)=>(t[n.type]=(t[n.type]||0)+1,t),{}),hasCustomRenderers:{row:!!this.formRenderConfig.rowRenderer,body:!!this.formRenderConfig.bodyRenderer,submitButton:!!this.formRenderConfig.submitButtonRenderer,field:!!this.formRenderConfig.fieldRenderer,stepper:!!this.workflowRenderConfig.stepperRenderer,workflowNextButton:!!this.workflowRenderConfig.nextButtonRenderer,workflowPreviousButton:!!this.workflowRenderConfig.previousButtonRenderer,workflowSkipButton:!!this.workflowRenderConfig.skipButtonRenderer}}}validate(){let r=[],t=Array.from(this.components.values()),n=t.map(i=>i.id);try{C(n,"component");}catch(i){r.push(i instanceof Error?i.message:String(i));}let o=t.filter(i=>!i.renderer);return o.length>0&&r.push(`Components without renderer: ${o.map(i=>i.id).join(", ")}`),r}};function d(e,r=[]){return {isValid:e,errors:[...r]}}function a(){return d(true,[])}function s(e,r,t){return d(false,[{message:e,code:r,path:t}])}function c(e){let r=[],t=true;for(let n of e)n.isValid||(t=false),r.push(...n.errors);return d(t,r)}function h(e,r,t){let n=e.map(o=>{let i=o(r,t);if(i instanceof Promise)throw new Error("Use runValidatorsAsync for async validators");return i});return c(n)}async function y(e,r,t){let n=await Promise.all(e.map(o=>o(r,t)));return c(n)}function w(e={}){return {fieldId:e.fieldId,formId:e.formId,stepId:e.stepId,workflowId:e.workflowId,allFormData:e.allFormData||{},stepData:e.stepData||{},workflowData:e.workflowData||{}}}function x(e="This field is required"){return r=>r==null||r===""||Array.isArray(r)&&r.length===0?s(e,"REQUIRED"):a()}function F(e,r){return t=>!t||t.length<e?s(r||`Must be at least ${e} characters long`,"MIN_LENGTH",`length.${e}`):a()}function A(e,r){return t=>t&&t.length>e?s(r||`Must be no more than ${e} characters long`,"MAX_LENGTH",`length.${e}`):a()}function b(e,r){return t=>t&&!e.test(t)?s(r||"Invalid format","PATTERN_MISMATCH",`pattern.${e.source}`):a()}function k(e="Please enter a valid email address"){let r=/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;return t=>t&&!r.test(t)?s(e,"INVALID_EMAIL"):a()}function N(e="Please enter a valid URL"){let r=/^https?:\/\/(?:[-\w.])+(?:\:[0-9]+)?(?:\/(?:[\w/_.])*(?:\?(?:[\w&=%.])*)?(?:\#(?:[\w.])*)?)?$/;return t=>t&&!r.test(t)?s(e,"INVALID_URL"):a()}function E(e="Must be a valid number"){return r=>{let t=typeof r=="string"?Number.parseFloat(r):r;return Number.isNaN(t)||!Number.isFinite(t)?s(e,"INVALID_NUMBER"):a()}}function I(e,r){return t=>{let n=typeof t=="string"?Number.parseFloat(t):t;return !Number.isNaN(n)&&n<e?s(r||`Must be at least ${e}`,"MIN_VALUE",`min.${e}`):a()}}function P(e,r){return t=>{let n=typeof t=="string"?Number.parseFloat(t):t;return !Number.isNaN(n)&&n>e?s(r||`Must be no more than ${e}`,"MAX_VALUE",`max.${e}`):a()}}function L(e,r,t){return (n,o)=>e(n,o)?a():s(r,t||"CUSTOM_VALIDATION_FAILED")}function B(e,r){return (t,n)=>{let o=n.allFormData?.[e];return t!==o?s(r||"Fields must match","FIELD_MISMATCH",`match.${e}`):a()}}function D(e,r){return (t,n)=>e(t,n)?r(t,n):a()}function $(e,r,t){return async(n,o)=>{try{return await e(n,o)?a():s(r,t||"ASYNC_VALIDATION_FAILED")}catch(i){return s(i instanceof Error?i.message:"Async validation error","ASYNC_ERROR")}}}var p=class{constructor(){this.name="ZodValidationAdapter";this.version="1.0.0";}createFieldValidator(r){return (t,n)=>{try{let o=r.safeParse(t);return o.success?a():{isValid:!1,errors:o.error.errors.map(l=>({message:l.message,code:"VALIDATION_ERROR",path:l.path.join(".")}))}}catch(o){return s(o instanceof Error?o.message:"Validation failed","VALIDATION_ERROR")}}}createFormValidator(r){return (t,n)=>{try{let o=r.safeParse(t);return o.success?a():{isValid:!1,errors:o.error.errors.map(l=>({message:l.message,code:"VALIDATION_ERROR",path:l.path.join(".")}))}}catch(o){return s(o instanceof Error?o.message:"Form validation failed","VALIDATION_ERROR")}}}};function m(){return new p}function _(e){return m().createFieldValidator(e)}function O(e){return m().createFormValidator(e)}export{v as ComponentRendererWrapper,V as IdGenerator,$ as async,c as combineValidationResults,u as configureObject,w as createValidationContext,d as createValidationResult,m as createZodAdapter,L as custom,T as deepClone,k as email,C as ensureUnique,B as matchField,P as max,A as maxLength,W as mergeInto,I as min,F as minLength,U as normalizeToArray,E as number,b as pattern,x as required,R as resolveRendererChildren,f as ril,h as runValidators,y as runValidatorsAsync,N as url,z as validateRequired,D as when,_ as zodFieldValidator,O as zodFormValidator};
1
+ function T(n,e){return typeof n=="function"?n(e):n}function z({children:n,renderAs:e,renderer:r,name:t,props:o}){if(e==="children"||e===true){if(typeof n!="function")throw new Error(`When renderAs="children" is used, children must be a function that returns React elements for ${t}`);return n(o)}if(!r)throw new Error(`No renderer provided for ${t}`);if(typeof r!="function")throw new Error(`Renderer must be a function for ${t}`);let d={...o,children:T(n,o)};return r(d)}function j(n,e){return {...n,...e}}function V(n,e){let r=n.filter((t,o)=>n.indexOf(t)!==o);if(r.length>0)throw new Error(`Duplicate ${e} IDs: ${r.join(", ")}`)}function H(n,e,r){if(n.filter(o=>e.some(i=>!o[i])).length>0)throw new Error(`Missing required fields in ${r}: ${e.join(", ")}`)}var b=class{constructor(){this.counters=new Map;}next(e){let r=this.counters.get(e)||0;return this.counters.set(e,r+1),`${e}-${r+1}`}reset(e){e?this.counters.delete(e):this.counters.clear();}};function X(n){return Array.isArray(n)?n:[n]}function x(n){if(n===null||typeof n!="object")return n;if(n instanceof Date)return new Date(n.getTime());if(Array.isArray(n))return n.map(r=>x(r));let e={};for(let r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=x(n[r]));return e}function Y(n,e,r){let t={...n};for(let o in e)r&&!r.includes(o)||e[o]!==void 0&&(t[o]=e[o]);return t}var C=class extends Error{constructor(r,t,o){super(r);this.code=t;this.meta=o;this.name="RilayError";}},g=class extends C{constructor(e,r){super(e,"VALIDATION_ERROR",r),this.name="ValidationError";}};function p(n,e){let r={...n};for(let t in e){let o=e[t],i=r[t];o&&typeof o=="object"&&!Array.isArray(o)&&i&&typeof i=="object"&&!Array.isArray(i)?r[t]=p(i,o):r[t]=o;}return r}var h=class n{constructor(){this.components=new Map;this.formRenderConfig={};this.workflowRenderConfig={};}static create(){return new n}addComponent(e,r){let t={id:e,type:e,...r},o=new n;return o.components=new Map(this.components),o.formRenderConfig={...this.formRenderConfig},o.workflowRenderConfig={...this.workflowRenderConfig},o.components.set(e,t),o}configure(e){let r=["rowRenderer","bodyRenderer","submitButtonRenderer","fieldRenderer"],t=["stepperRenderer","nextButtonRenderer","previousButtonRenderer","skipButtonRenderer"],o={},i={};for(let[f,c]of Object.entries(e))r.includes(f)?o[f]=c:t.includes(f)&&(i[f]=c);let d=new n;return d.components=new Map(this.components),d.formRenderConfig=p(this.formRenderConfig,o),d.workflowRenderConfig=p(this.workflowRenderConfig,i),d}getFormRenderConfig(){return {...this.formRenderConfig}}getWorkflowRenderConfig(){return {...this.workflowRenderConfig}}getComponent(e){return this.components.get(e)}getAllComponents(){return Array.from(this.components.values())}hasComponent(e){return this.components.has(e)}removeComponent(e){let r=new n;return r.components=new Map(this.components),r.formRenderConfig={...this.formRenderConfig},r.workflowRenderConfig={...this.workflowRenderConfig},r.components.delete(e),r}clear(){let e=new n;return e.formRenderConfig={...this.formRenderConfig},e.workflowRenderConfig={...this.workflowRenderConfig},e}clone(){let e=new n;return e.components=new Map(this.components),e.formRenderConfig=p({},this.formRenderConfig),e.workflowRenderConfig=p({},this.workflowRenderConfig),e}getStats(){let e=Array.from(this.components.values());return {total:e.length,byType:e.reduce((r,t)=>(r[t.type]=(r[t.type]||0)+1,r),{}),hasCustomRenderers:{row:!!this.formRenderConfig.rowRenderer,body:!!this.formRenderConfig.bodyRenderer,submitButton:!!this.formRenderConfig.submitButtonRenderer,field:!!this.formRenderConfig.fieldRenderer,stepper:!!this.workflowRenderConfig.stepperRenderer,workflowNextButton:!!this.workflowRenderConfig.nextButtonRenderer,workflowPreviousButton:!!this.workflowRenderConfig.previousButtonRenderer,workflowSkipButton:!!this.workflowRenderConfig.skipButtonRenderer}}}validate(){let e=[],r=Array.from(this.components.values()),t=r.map(u=>u.id);try{V(t,"component");}catch(u){e.push(u instanceof Error?u.message:String(u));}let o=r.filter(u=>!u.renderer);o.length>0&&e.push(`Components without renderer: ${o.map(u=>u.id).join(", ")}`);let i=Object.keys(this.formRenderConfig),d=Object.keys(this.workflowRenderConfig),f=["rowRenderer","bodyRenderer","submitButtonRenderer","fieldRenderer"],c=["stepperRenderer","nextButtonRenderer","previousButtonRenderer","skipButtonRenderer"],l=i.filter(u=>!f.includes(u)),w=d.filter(u=>!c.includes(u));return l.length>0&&e.push(`Invalid form renderer keys: ${l.join(", ")}`),w.length>0&&e.push(`Invalid workflow renderer keys: ${w.join(", ")}`),e}async validateAsync(){let e=[],r=[],t=Array.from(this.components.values());try{let o=this.validate();e.push(...o);let i=t.map(async l=>l.renderer&&typeof l.renderer!="function"&&typeof l.renderer!="object"?`Component "${l.id}" has invalid renderer type: ${typeof l.renderer}`:((l.id.includes(" ")||l.id.includes("-"))&&r.push(`Component "${l.id}" uses non-standard naming (contains spaces or dashes)`),null)),f=(await Promise.all(i)).filter(l=>l!==null);e.push(...f),t.length>50&&r.push("Large number of components detected. Consider splitting configuration.");let c={isValid:e.length===0,errors:e,warnings:r.length>0?r:void 0};if(!c.isValid)throw new g("Ril configuration validation failed",{errors:e,warnings:r,componentCount:t.length});return c}catch(o){throw o instanceof g?o:new g("Unexpected error during async validation",{originalError:o instanceof Error?o.message:String(o)})}}};function m(n,e=[]){return {isValid:n,errors:[...e]}}function s(){return m(true,[])}function a(n,e,r){return m(false,[{message:n,code:e,path:r}])}function R(n){let e=[],r=true;for(let t of n)t.isValid||(r=false),e.push(...t.errors);return m(r,e)}function k(n,e,r){let t=n.map(o=>{let i=o(e,r);if(i instanceof Promise)throw new Error("Use runValidatorsAsync for async validators");return i});return R(t)}async function A(n,e,r){let t=await Promise.all(n.map(o=>o(e,r)));return R(t)}function B(n={}){return {fieldId:n.fieldId,formId:n.formId,stepId:n.stepId,workflowId:n.workflowId,allFormData:n.allFormData||{},stepData:n.stepData||{},workflowData:n.workflowData||{}}}function E(n="This field is required"){return e=>e==null||e===""||Array.isArray(e)&&e.length===0?a(n,"REQUIRED"):s()}function F(n,e){return r=>!r||r.length<n?a(e||`Must be at least ${n} characters long`,"MIN_LENGTH",`length.${n}`):s()}function I(n,e){return r=>r&&r.length>n?a(e||`Must be no more than ${n} characters long`,"MAX_LENGTH",`length.${n}`):s()}function O(n,e){return r=>r&&!n.test(r)?a(e||"Invalid format","PATTERN_MISMATCH",`pattern.${n.source}`):s()}function N(n="Please enter a valid email address"){let e=/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;return r=>r&&!e.test(r)?a(n,"INVALID_EMAIL"):s()}function P(n="Please enter a valid URL"){let e=/^https?:\/\/(?:[-\w.])+(?:\:[0-9]+)?(?:\/(?:[\w/_.])*(?:\?(?:[\w&=%.])*)?(?:\#(?:[\w.])*)?)?$/;return r=>r&&!e.test(r)?a(n,"INVALID_URL"):s()}function $(n="Must be a valid number"){return e=>{let r=typeof e=="string"?Number.parseFloat(e):e;return Number.isNaN(r)||!Number.isFinite(r)?a(n,"INVALID_NUMBER"):s()}}function q(n,e){return r=>{let t=typeof r=="string"?Number.parseFloat(r):r;return !Number.isNaN(t)&&t<n?a(e||`Must be at least ${n}`,"MIN_VALUE",`min.${n}`):s()}}function L(n,e){return r=>{let t=typeof r=="string"?Number.parseFloat(r):r;return !Number.isNaN(t)&&t>n?a(e||`Must be no more than ${n}`,"MAX_VALUE",`max.${n}`):s()}}function D(n,e,r){return (t,o)=>n(t,o)?s():a(e,r||"CUSTOM_VALIDATION_FAILED")}function M(n,e){return (r,t)=>{let o=t.allFormData?.[n];return r!==o?a(e||"Fields must match","FIELD_MISMATCH",`match.${n}`):s()}}function W(n,e){return (r,t)=>n(r,t)?e(r,t):s()}function S(n,e,r){return async(t,o)=>{try{return await n(t,o)?s():a(e,r||"ASYNC_VALIDATION_FAILED")}catch(i){return a(i instanceof Error?i.message:"Async validation error","ASYNC_ERROR")}}}var y=class{constructor(e){this.field=e,this.operator="exists",this.conditions=[];}equals(e){return this.operator="equals",this.value=e,this}notEquals(e){return this.operator="notEquals",this.value=e,this}greaterThan(e){return this.operator="greaterThan",this.value=e,this}lessThan(e){return this.operator="lessThan",this.value=e,this}greaterThanOrEqual(e){return this.operator="greaterThanOrEqual",this.value=e,this}lessThanOrEqual(e){return this.operator="lessThanOrEqual",this.value=e,this}contains(e){return this.operator="contains",this.value=e,this}notContains(e){return this.operator="notContains",this.value=e,this}in(e){return this.operator="in",this.value=e,this}notIn(e){return this.operator="notIn",this.value=e,this}matches(e){return this.operator="matches",this.value=e instanceof RegExp?e.source:e,this}exists(){return this.operator="exists",this.value=void 0,this}notExists(){return this.operator="notExists",this.value=void 0,this}and(e){let r="build"in e?e.build():e,t={field:this.field,operator:this.operator,value:this.value,conditions:this.conditions,logicalOperator:this.logicalOperator};return this.field="",this.operator="exists",this.value=void 0,this.conditions=[t,r],this.logicalOperator="and",this}or(e){let r="build"in e?e.build():e,t={field:this.field,operator:this.operator,value:this.value,conditions:this.conditions,logicalOperator:this.logicalOperator};return this.field="",this.operator="exists",this.value=void 0,this.conditions=[t,r],this.logicalOperator="or",this}build(){return {field:this.field,operator:this.operator,value:this.value,conditions:this.conditions,logicalOperator:this.logicalOperator}}evaluate(e){return v(this,e)}};function se(n){return new y(n)}function v(n,e){if(n.conditions&&n.conditions.length>0){let t=n.conditions.map(o=>v(o,e));return n.logicalOperator==="or"?t.some(o=>o):t.every(o=>o)}let r=U(e,n.field);switch(n.operator){case "equals":return r===n.value;case "notEquals":return r!==n.value;case "greaterThan":return typeof r=="number"&&typeof n.value=="number"&&r>n.value;case "lessThan":return typeof r=="number"&&typeof n.value=="number"&&r<n.value;case "greaterThanOrEqual":return typeof r=="number"&&typeof n.value=="number"&&r>=n.value;case "lessThanOrEqual":return typeof r=="number"&&typeof n.value=="number"&&r<=n.value;case "contains":return typeof r=="string"&&typeof n.value=="string"&&r.includes(n.value);case "notContains":return typeof r=="string"&&typeof n.value=="string"&&!r.includes(n.value);case "in":return Array.isArray(n.value)&&n.value.includes(r);case "notIn":return Array.isArray(n.value)&&!n.value.includes(r);case "matches":return typeof r!="string"||typeof n.value!="string"?false:new RegExp(n.value).test(r);case "exists":return r!=null;case "notExists":return r==null;default:return false}}function U(n,e){let r=e.split("."),t=n;for(let o of r)if(t&&typeof t=="object"&&o in t)t=t[o];else return;return t}export{z as ComponentRendererWrapper,b as IdGenerator,S as async,R as combineValidationResults,Y as configureObject,B as createValidationContext,m as createValidationResult,D as custom,x as deepClone,N as email,V as ensureUnique,v as evaluateCondition,M as matchField,L as max,I as maxLength,j as mergeInto,q as min,F as minLength,X as normalizeToArray,$ as number,O as pattern,E as required,T as resolveRendererChildren,h as ril,k as runValidators,A as runValidatorsAsync,P as url,H as validateRequired,W as validateWhen,se as when};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rilaykit/core",
3
- "version": "5.2.1",
3
+ "version": "6.0.0",
4
4
  "description": "Core types, configurations, and utilities for the RilayKit form library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -33,9 +33,6 @@
33
33
  "react": "^19.1.0",
34
34
  "typescript": "^5.3.0"
35
35
  },
36
- "dependencies": {
37
- "zod": "^3.22.4"
38
- },
39
36
  "publishConfig": {
40
37
  "access": "public"
41
38
  },