@rilaykit/forms 0.1.1 → 0.1.3

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/README.md ADDED
@@ -0,0 +1,239 @@
1
+ # @rilaykit/forms
2
+
3
+ The form builder and React rendering layer for [RilayKit](https://rilay.dev) — build type-safe, headless forms from declarative schemas.
4
+
5
+ `@rilaykit/forms` provides a fluent builder API to define form configurations and headless React components to render them. State management is powered by Zustand with granular selectors for optimal re-render performance.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ # pnpm (recommended)
11
+ pnpm add @rilaykit/core @rilaykit/forms
12
+
13
+ # npm
14
+ npm install @rilaykit/core @rilaykit/forms
15
+
16
+ # yarn
17
+ yarn add @rilaykit/core @rilaykit/forms
18
+
19
+ # bun
20
+ bun add @rilaykit/core @rilaykit/forms
21
+ ```
22
+
23
+ > `@rilaykit/core` is a required peer dependency.
24
+
25
+ ### Requirements
26
+
27
+ - React >= 18
28
+ - React DOM >= 18
29
+
30
+ ## Quick Start
31
+
32
+ ### 1. Create Your Registry
33
+
34
+ ```tsx
35
+ import { ril } from '@rilaykit/core';
36
+ import { Input } from './components/Input';
37
+
38
+ const rilay = ril.create()
39
+ .addComponent('input', { renderer: Input });
40
+ ```
41
+
42
+ ### 2. Build a Form
43
+
44
+ ```tsx
45
+ import { required, email } from '@rilaykit/core';
46
+
47
+ const loginForm = rilay
48
+ .form('login')
49
+ .add({
50
+ id: 'email',
51
+ type: 'input',
52
+ props: { label: 'Email', type: 'email' },
53
+ validation: { validate: [required(), email()] },
54
+ })
55
+ .add({
56
+ id: 'password',
57
+ type: 'input',
58
+ props: { label: 'Password', type: 'password' },
59
+ validation: { validate: [required()] },
60
+ });
61
+ ```
62
+
63
+ ### 3. Render It
64
+
65
+ ```tsx
66
+ import { Form, FormField } from '@rilaykit/forms';
67
+
68
+ function LoginForm() {
69
+ const handleSubmit = (data: { email: string; password: string }) => {
70
+ console.log('Login:', data);
71
+ };
72
+
73
+ return (
74
+ <Form formConfig={loginForm} onSubmit={handleSubmit}>
75
+ <FormField fieldId="email" />
76
+ <FormField fieldId="password" />
77
+ <button type="submit">Sign In</button>
78
+ </Form>
79
+ );
80
+ }
81
+ ```
82
+
83
+ ## Features
84
+
85
+ ### Fluent Form Builder
86
+
87
+ Construct forms with a chainable, type-safe API. Each field type and its props are validated at compile time.
88
+
89
+ ```tsx
90
+ const contactForm = rilay
91
+ .form('contact')
92
+ .add(
93
+ { id: 'firstName', type: 'input', props: { label: 'First Name' } },
94
+ { id: 'lastName', type: 'input', props: { label: 'Last Name' } },
95
+ )
96
+ .add({
97
+ id: 'message',
98
+ type: 'textarea',
99
+ props: { label: 'Message', rows: 5 },
100
+ validation: { validate: [required()] },
101
+ });
102
+
103
+ // Serialize, clone, inspect
104
+ const json = contactForm.toJSON();
105
+ const variant = contactForm.clone('contact-v2');
106
+ const stats = contactForm.getStats();
107
+ ```
108
+
109
+ ### Headless React Components
110
+
111
+ Zero HTML, zero CSS. You provide the renderers, RilayKit handles state, validation, and orchestration.
112
+
113
+ | Component | Description |
114
+ |-----------|-------------|
115
+ | `<Form>` | Main wrapper — manages context, state, and submission |
116
+ | `<FormProvider>` | Context provider (used separately from Form when needed) |
117
+ | `<FormBody>` | Renders the full form body from configuration |
118
+ | `<FormField>` | Renders a single field by ID |
119
+ | `<FormRow>` | Renders a row of fields |
120
+ | `<FormSubmitButton>` | Submit button with loading/disabled state |
121
+
122
+ ### Zustand-Powered Store
123
+
124
+ Each form instance gets its own Zustand store with granular selectors — only the fields that change trigger re-renders.
125
+
126
+ ```tsx
127
+ import {
128
+ useFieldValue,
129
+ useFieldErrors,
130
+ useFieldTouched,
131
+ useFieldState,
132
+ useFormValues,
133
+ useFormValid,
134
+ useFormDirty,
135
+ useFormSubmitting,
136
+ useFieldActions,
137
+ useFormActions,
138
+ } from '@rilaykit/forms';
139
+
140
+ function CustomField({ fieldId }: { fieldId: string }) {
141
+ const value = useFieldValue(fieldId);
142
+ const errors = useFieldErrors(fieldId);
143
+ const { setValue, setTouched } = useFieldActions(fieldId);
144
+ // ...
145
+ }
146
+ ```
147
+
148
+ ### Conditional Fields
149
+
150
+ Combined with `@rilaykit/core`'s condition system, fields show/hide reactively based on other field values.
151
+
152
+ ```tsx
153
+ import { when } from '@rilaykit/core';
154
+
155
+ rilay.form('account')
156
+ .add({
157
+ id: 'accountType',
158
+ type: 'select',
159
+ props: { options: [{ value: 'business', label: 'Business' }] },
160
+ })
161
+ .add({
162
+ id: 'companyName',
163
+ type: 'input',
164
+ props: { label: 'Company Name' },
165
+ conditions: { visible: when('accountType').equals('business') },
166
+ });
167
+ ```
168
+
169
+ ### Validation
170
+
171
+ Supports built-in validators, Standard Schema libraries (Zod, Valibot, Yup...), and custom validators — all in the same field.
172
+
173
+ ```tsx
174
+ import { z } from 'zod';
175
+ import { required } from '@rilaykit/core';
176
+
177
+ validation: {
178
+ validate: [required(), z.string().email()],
179
+ validateOnBlur: true,
180
+ }
181
+ ```
182
+
183
+ ## API Overview
184
+
185
+ ### Builder
186
+
187
+ | Method | Description |
188
+ |--------|-------------|
189
+ | `form.create(ril, id?)` | Create a new form builder |
190
+ | `.add(...fields)` | Add fields (1-3 per row) |
191
+ | `.addSeparateRows(fields)` | Each field on its own row |
192
+ | `.updateField(id, updates)` | Update a field definition |
193
+ | `.removeField(id)` | Remove a field |
194
+ | `.setValidation(config)` | Set form-level validation |
195
+ | `.addFieldConditions(id, conditions)` | Add conditional logic |
196
+ | `.build()` | Produce the final `FormConfiguration` |
197
+ | `.toJSON()` / `.fromJSON(json)` | Serialize / deserialize |
198
+ | `.clone(newId?)` | Clone the form configuration |
199
+
200
+ ### Hooks
201
+
202
+ | Hook | Description |
203
+ |------|-------------|
204
+ | `useFieldValue(id)` | Current field value |
205
+ | `useFieldErrors(id)` | Field validation errors |
206
+ | `useFieldTouched(id)` | Whether field has been touched |
207
+ | `useFieldState(id)` | Combined field state |
208
+ | `useFieldActions(id)` | `setValue`, `setTouched`, etc. |
209
+ | `useFieldConditions(id)` | Evaluated condition results |
210
+ | `useFormValues()` | All form values |
211
+ | `useFormValid()` | Whether form is valid |
212
+ | `useFormDirty()` | Whether form has unsaved changes |
213
+ | `useFormSubmitting()` | Whether form is submitting |
214
+ | `useFormActions()` | `submit`, `reset`, `validate`, etc. |
215
+
216
+ ## Architecture
217
+
218
+ ```
219
+ @rilaykit/core (registry, types, validation, conditions)
220
+
221
+ @rilaykit/forms ← you are here
222
+
223
+ @rilaykit/workflow (multi-step workflows)
224
+ ```
225
+
226
+ ## Documentation
227
+
228
+ Full documentation at [rilay.dev](https://rilay.dev):
229
+
230
+ - [Building Forms](https://rilay.dev/forms/building-forms)
231
+ - [Rendering Forms](https://rilay.dev/forms/rendering-forms)
232
+ - [Form Validation](https://rilay.dev/forms/validation)
233
+ - [Advanced Forms](https://rilay.dev/forms/advanced-forms)
234
+ - [Form Hooks](https://rilay.dev/forms/hooks)
235
+ - [API Reference](https://rilay.dev/api)
236
+
237
+ ## License
238
+
239
+ MIT — see [LICENSE](./LICENSE) for details.
package/dist/index.d.mts CHANGED
@@ -1,9 +1,66 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ril, FieldValidationConfig, ConditionalBehavior, FormFieldConfig, FormFieldRow, FormValidationConfig, FormConfiguration, ComponentRendererBaseProps, FormBodyRendererProps, FieldConditions, FormState, ValidationError, ValidationState, FieldState, ValidationResult, MonitoringConfig, FormPerformanceMetrics, FormRowRendererProps, FormSubmitButtonRendererProps } from '@rilaykit/core';
2
+ import { ril, FieldValidationConfig, RepeatableFieldConfig, ConditionalBehavior, FormFieldConfig, FormRowEntry, FormValidationConfig, SubmitOptions, FormConfiguration, ComponentRendererBaseProps, FormBodyRendererProps, FieldConditions, FormState, ValidationError, ValidationState, FieldState, ValidationResult, RepeatableFieldItem, MonitoringConfig, FormPerformanceMetrics, FormRowRendererProps, FormFieldRow, FormSubmitButtonRendererProps } from '@rilaykit/core';
3
3
  import * as React$1 from 'react';
4
4
  import React__default from 'react';
5
5
  import * as zustand from 'zustand';
6
6
 
7
+ /**
8
+ * Fluent builder for configuring repeatable field groups
9
+ *
10
+ * Used via callback in `form.addRepeatable()`:
11
+ * ```typescript
12
+ * form.create(ril, "order")
13
+ * .addRepeatable("items", r => r
14
+ * .add(
15
+ * { id: "name", type: "text", props: { label: "Item" } },
16
+ * { id: "qty", type: "number", props: { label: "Qty" } }
17
+ * )
18
+ * .min(1)
19
+ * .max(10)
20
+ * .defaultValue({ name: "", qty: 1 })
21
+ * )
22
+ * .build()
23
+ * ```
24
+ */
25
+ declare class RepeatableBuilder<C extends Record<string, any>> {
26
+ private innerForm;
27
+ private _min?;
28
+ private _max?;
29
+ private _defaultValue?;
30
+ private _validation?;
31
+ constructor(config: ril<C>);
32
+ /**
33
+ * Add fields to the repeatable template
34
+ * Same API as form.add() — variadic ≤3 puts them on the same row
35
+ */
36
+ add<T extends keyof C & string>(...fields: FieldConfig<C, T>[]): this;
37
+ add<T extends keyof C & string>(fields: FieldConfig<C, T>[]): this;
38
+ /**
39
+ * Add fields each on their own row
40
+ */
41
+ addSeparateRows<T extends keyof C & string>(fields: FieldConfig<C, T>[]): this;
42
+ /**
43
+ * Set minimum number of items (defaults to 0)
44
+ */
45
+ min(value: number): this;
46
+ /**
47
+ * Set maximum number of items (unlimited if not set)
48
+ */
49
+ max(value: number): this;
50
+ /**
51
+ * Set default values for new items
52
+ */
53
+ defaultValue(value: Record<string, unknown>): this;
54
+ /**
55
+ * Set group-level validation (applied to the entire array)
56
+ */
57
+ validation(config: FieldValidationConfig): this;
58
+ /** @internal — called by form.addRepeatable */
59
+ _build(id: string): RepeatableFieldConfig;
60
+ /** @internal — check if the inner builder has repeatables (nesting forbidden) */
61
+ _hasRepeatables(): boolean;
62
+ }
63
+
7
64
  /**
8
65
  * Configuration for a form field with type safety
9
66
  *
@@ -88,6 +145,8 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
88
145
  private idGenerator;
89
146
  /** Form-level validation configuration */
90
147
  private formValidation?;
148
+ /** Default submit options for this form */
149
+ private _submitOptions?;
91
150
  /**
92
151
  * Creates a new form builder instance
93
152
  *
@@ -206,6 +265,30 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
206
265
  * ```
207
266
  */
208
267
  addSeparateRows<T extends keyof C & string>(fieldConfigs: FieldConfig<C, T>[]): this;
268
+ /**
269
+ * Adds a repeatable field group to the form
270
+ *
271
+ * Repeatable fields allow users to add/remove instances of a group of fields
272
+ * at runtime (e.g., "Add another item", "Add another contact").
273
+ *
274
+ * @param id - Unique identifier for the repeatable group (cannot contain [ or ])
275
+ * @param configure - Callback receiving a RepeatableBuilder for fluent configuration
276
+ * @returns The form builder instance for method chaining
277
+ *
278
+ * @example
279
+ * ```typescript
280
+ * builder.addRepeatable("items", r => r
281
+ * .add(
282
+ * { id: "name", type: "text", props: { label: "Item" } },
283
+ * { id: "qty", type: "number", props: { label: "Qty" } }
284
+ * )
285
+ * .min(1)
286
+ * .max(10)
287
+ * .defaultValue({ name: "", qty: 1 })
288
+ * );
289
+ * ```
290
+ */
291
+ addRepeatable(id: string, configure: (builder: RepeatableBuilder<C>) => RepeatableBuilder<C>): this;
209
292
  /**
210
293
  * Sets the form identifier
211
294
  *
@@ -308,7 +391,7 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
308
391
  * console.log(`Form has ${rows.length} rows`);
309
392
  * ```
310
393
  */
311
- getRows(): FormFieldRow[];
394
+ getRows(): FormRowEntry[];
312
395
  /**
313
396
  * Clears all fields and rows from the form
314
397
  *
@@ -349,6 +432,24 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
349
432
  * ```
350
433
  */
351
434
  setValidation(validationConfig: FormValidationConfig): this;
435
+ /**
436
+ * Sets default submit options for this form
437
+ *
438
+ * These options can be overridden at submit-time by passing options to `submit()`.
439
+ *
440
+ * @param options - Submit options to use as defaults
441
+ * @returns The form builder instance for method chaining
442
+ *
443
+ * @example
444
+ * ```typescript
445
+ * // Always skip invalid fields on submit
446
+ * builder.setSubmitOptions({ skipInvalid: true });
447
+ *
448
+ * // Force submit by default (bypass validation)
449
+ * builder.setSubmitOptions({ force: true });
450
+ * ```
451
+ */
452
+ setSubmitOptions(options: SubmitOptions): this;
352
453
  /**
353
454
  * Adds validators to the form-level validation
354
455
  *
@@ -516,16 +617,20 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
516
617
  * - Useful for form complexity analysis
517
618
  */
518
619
  getStats(): {
519
- /** Total number of fields across all rows */
620
+ /** Total number of static fields across all rows */
520
621
  totalFields: number;
521
622
  /** Total number of rows in the form */
522
623
  totalRows: number;
523
- /** Average number of fields per row */
624
+ /** Average number of fields per row (field rows only) */
524
625
  averageFieldsPerRow: number;
525
626
  /** Maximum number of fields in any single row */
526
627
  maxFieldsInRow: number;
527
628
  /** Minimum number of fields in any single row */
528
629
  minFieldsInRow: number;
630
+ /** Total number of repeatable groups */
631
+ totalRepeatables: number;
632
+ /** Total number of fields across all repeatable templates */
633
+ totalRepeatableFields: number;
529
634
  };
530
635
  }
531
636
 
@@ -537,12 +642,14 @@ interface FormProps {
537
642
  className?: string;
538
643
  children: React.ReactNode;
539
644
  }
540
- declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, children }: FormProps): react_jsx_runtime.JSX.Element;
645
+ declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, className, children, }: FormProps): react_jsx_runtime.JSX.Element;
541
646
 
542
647
  declare const FormBody: React__default.NamedExoticComponent<ComponentRendererBaseProps<FormBodyRendererProps>>;
543
648
 
544
649
  interface FormFieldProps {
545
650
  fieldId: string;
651
+ /** Pre-resolved field config (used by RepeatableItem to skip allFields lookup) */
652
+ fieldConfig?: FormFieldConfig;
546
653
  disabled?: boolean;
547
654
  customProps?: Record<string, unknown>;
548
655
  className?: string;
@@ -626,6 +733,8 @@ declare function useFieldConditionsWithRefresh(fieldId: string, conditions?: Con
626
733
  interface UseFormConditionsProps {
627
734
  formConfig: FormConfiguration;
628
735
  formValues: Record<string, any>;
736
+ /** Active repeatable item keys, keyed by repeatable ID */
737
+ repeatableOrder?: Record<string, string[]>;
629
738
  }
630
739
  interface UseFormConditionsReturn {
631
740
  fieldConditions: Record<string, ConditionEvaluationResult>;
@@ -662,11 +771,14 @@ interface UseFormConditionsReturn {
662
771
  * }
663
772
  * ```
664
773
  */
665
- declare function useFormConditions({ formConfig, formValues, }: UseFormConditionsProps): UseFormConditionsReturn;
774
+ declare function useFormConditions({ formConfig, formValues, repeatableOrder, }: UseFormConditionsProps): UseFormConditionsReturn;
666
775
 
667
776
  interface FormStoreState extends FormState {
668
777
  _defaultValues: Record<string, unknown>;
669
778
  _fieldConditions: Record<string, FieldConditions>;
779
+ _repeatableConfigs: Record<string, RepeatableFieldConfig>;
780
+ _repeatableOrder: Record<string, string[]>;
781
+ _repeatableNextKey: Record<string, number>;
670
782
  _setValue: (fieldId: string, value: unknown) => void;
671
783
  _setTouched: (fieldId: string) => void;
672
784
  _setErrors: (fieldId: string, errors: ValidationError[]) => void;
@@ -676,6 +788,11 @@ interface FormStoreState extends FormState {
676
788
  _reset: (values?: Record<string, unknown>) => void;
677
789
  _setFieldConditions: (fieldId: string, conditions: FieldConditions) => void;
678
790
  _updateIsValid: () => void;
791
+ _setRepeatableConfig: (id: string, config: RepeatableFieldConfig) => void;
792
+ _appendRepeatableItem: (repeatableId: string, defaultValue?: Record<string, unknown>) => string | null;
793
+ _removeRepeatableItem: (repeatableId: string, key: string) => boolean;
794
+ _moveRepeatableItem: (repeatableId: string, fromIndex: number, toIndex: number) => void;
795
+ _insertRepeatableItem: (repeatableId: string, index: number, defaultValue?: Record<string, unknown>) => string | null;
679
796
  }
680
797
  type FormStore = ReturnType<typeof createFormStore>;
681
798
  declare function createFormStore(initialValues?: Record<string, unknown>): Omit<zustand.StoreApi<FormStoreState>, "subscribe"> & {
@@ -749,6 +866,10 @@ declare function useFormSubmitState(): {
749
866
  isValid: boolean;
750
867
  isDirty: boolean;
751
868
  };
869
+ /**
870
+ * Select ordered keys for a repeatable field — re-renders when the order changes
871
+ */
872
+ declare function useRepeatableKeys(repeatableId: string): string[];
752
873
  interface UseFieldActionsResult {
753
874
  setValue: (value: unknown) => void;
754
875
  setTouched: () => void;
@@ -783,9 +904,10 @@ interface UseFormSubmissionWithStoreProps {
783
904
  store: FormStore;
784
905
  onSubmit?: (data: Record<string, unknown>) => void | Promise<void>;
785
906
  validateForm: () => Promise<ValidationResult>;
907
+ defaultSubmitOptions?: SubmitOptions;
786
908
  }
787
- declare function useFormSubmissionWithStore({ store, onSubmit, validateForm, }: UseFormSubmissionWithStoreProps): {
788
- submit: (event?: React__default.FormEvent) => Promise<boolean>;
909
+ declare function useFormSubmissionWithStore({ store, onSubmit, validateForm, defaultSubmitOptions, }: UseFormSubmissionWithStoreProps): {
910
+ submit: (eventOrOptions?: React__default.FormEvent | SubmitOptions) => Promise<boolean>;
789
911
  };
790
912
 
791
913
  interface UseFormValidationWithStoreProps {
@@ -798,6 +920,45 @@ declare function useFormValidationWithStore({ formConfig, store, conditionsHelpe
798
920
  validateForm: () => Promise<ValidationResult>;
799
921
  };
800
922
 
923
+ interface UseRepeatableFieldReturn {
924
+ items: RepeatableFieldItem[];
925
+ append: (defaultValue?: Record<string, unknown>) => void;
926
+ remove: (key: string) => void;
927
+ move: (fromIndex: number, toIndex: number) => void;
928
+ canAdd: boolean;
929
+ canRemove: boolean;
930
+ count: number;
931
+ }
932
+ /**
933
+ * Hook to manage a repeatable field group
934
+ *
935
+ * Provides the list of items and actions to add, remove, and reorder them.
936
+ * Each item contains scoped field configs ready for rendering.
937
+ *
938
+ * @param repeatableId - The ID of the repeatable group (as defined in addRepeatable)
939
+ * @returns Items, actions, and constraints
940
+ *
941
+ * @example
942
+ * ```tsx
943
+ * const { items, append, remove, canAdd, canRemove } = useRepeatableField("items");
944
+ *
945
+ * return (
946
+ * <div>
947
+ * {items.map(item => (
948
+ * <div key={item.key}>
949
+ * {item.allFields.map(field => (
950
+ * <FormField key={field.id} fieldId={field.id} fieldConfig={field} />
951
+ * ))}
952
+ * {canRemove && <button onClick={() => remove(item.key)}>Remove</button>}
953
+ * </div>
954
+ * ))}
955
+ * {canAdd && <button onClick={append}>Add</button>}
956
+ * </div>
957
+ * );
958
+ * ```
959
+ */
960
+ declare function useRepeatableField(repeatableId: string): UseRepeatableFieldReturn;
961
+
801
962
  interface UseFormMonitoringProps {
802
963
  formConfig: FormConfiguration;
803
964
  monitoring?: MonitoringConfig;
@@ -818,7 +979,7 @@ interface FormConfigContextValue {
818
979
  conditionsHelpers: Omit<UseFormConditionsReturn, 'fieldConditions'>;
819
980
  validateField: (fieldId: string, value?: unknown) => Promise<ValidationResult>;
820
981
  validateForm: () => Promise<ValidationResult>;
821
- submit: (event?: React__default.FormEvent) => Promise<boolean>;
982
+ submit: (eventOrOptions?: React__default.FormEvent | SubmitOptions) => Promise<boolean>;
822
983
  }
823
984
  /**
824
985
  * Access form configuration and validation methods
@@ -848,4 +1009,53 @@ interface FormSubmitButtonProps extends ComponentRendererBaseProps<FormSubmitBut
848
1009
  }
849
1010
  declare const FormSubmitButton: React__default.NamedExoticComponent<FormSubmitButtonProps>;
850
1011
 
851
- export { type ConditionEvaluationResult, type FieldConfig, Form, FormBody, form as FormBuilder, type FormConfigContextValue, FormField, FormProvider, type FormProviderProps, FormRow, type FormStore, FormStoreContext, type FormStoreState, FormSubmitButton, type UseFieldActionsResult, type UseFieldConditionsLazyOptions, type UseFormActionsResult, type UseFormConditionsProps, type UseFormConditionsReturn, type UseFormMonitoringProps, type UseFormMonitoringReturn, type UseFormSubmissionWithStoreProps, type UseFormValidationWithStoreProps, createFormStore, form, useConditionEvaluation, useConditionEvaluator, useFieldActions, useFieldConditions, useFieldConditionsLazy, useFieldConditionsWithRefresh, useFieldErrors, useFieldState, useFieldTouched, useFieldValidationState, useFieldValue, useFormActions, useFormConditions, useFormConfigContext, useFormDirty, useFormMonitoring, useFormStore, useFormStoreApi, useFormSubmissionWithStore, useFormSubmitState, useFormSubmitting, useFormValid, useFormValidationWithStore, useFormValues, useMultipleConditionEvaluation };
1012
+ interface RepeatableFieldProps {
1013
+ repeatableId: string;
1014
+ repeatableConfig: RepeatableFieldConfig;
1015
+ className?: string;
1016
+ }
1017
+ declare const RepeatableField: React__default.NamedExoticComponent<RepeatableFieldProps>;
1018
+
1019
+ interface RepeatableItemProps {
1020
+ item: RepeatableFieldItem;
1021
+ index: number;
1022
+ total: number;
1023
+ canRemove: boolean;
1024
+ canMoveUp: boolean;
1025
+ canMoveDown: boolean;
1026
+ onRemove: () => void;
1027
+ onMoveUp: () => void;
1028
+ onMoveDown: () => void;
1029
+ }
1030
+ declare const RepeatableItem: React__default.NamedExoticComponent<RepeatableItemProps>;
1031
+
1032
+ /**
1033
+ * Converts flat store values with composite keys into structured nested data.
1034
+ *
1035
+ * Input (store values):
1036
+ * { customerName: "John", "items[k0].name": "Widget", "items[k0].qty": 2, "items[k1].name": "Gadget", "items[k1].qty": 1 }
1037
+ *
1038
+ * Output (structured):
1039
+ * { customerName: "John", items: [{ name: "Widget", qty: 2 }, { name: "Gadget", qty: 1 }] }
1040
+ */
1041
+ declare function structureFormValues(values: Record<string, unknown>, repeatableConfigs: Record<string, RepeatableFieldConfig>, repeatableOrder: Record<string, string[]>): Record<string, unknown>;
1042
+ /**
1043
+ * Converts structured nested data into flat store values with composite keys.
1044
+ *
1045
+ * Input (structured):
1046
+ * { customerName: "John", items: [{ name: "Widget", qty: 2 }, { name: "Gadget", qty: 1 }] }
1047
+ *
1048
+ * Output:
1049
+ * {
1050
+ * values: { customerName: "John", "items[k0].name": "Widget", "items[k0].qty": 2, "items[k1].name": "Gadget", "items[k1].qty": 1 },
1051
+ * order: { items: ["k0", "k1"] },
1052
+ * nextKeys: { items: 2 }
1053
+ * }
1054
+ */
1055
+ declare function flattenRepeatableValues(data: Record<string, unknown>, repeatableConfigs: Record<string, RepeatableFieldConfig>): {
1056
+ values: Record<string, unknown>;
1057
+ order: Record<string, string[]>;
1058
+ nextKeys: Record<string, number>;
1059
+ };
1060
+
1061
+ export { type ConditionEvaluationResult, type FieldConfig, Form, FormBody, form as FormBuilder, type FormConfigContextValue, FormField, FormProvider, type FormProviderProps, FormRow, type FormStore, FormStoreContext, type FormStoreState, FormSubmitButton, RepeatableBuilder, RepeatableField, RepeatableItem, type UseFieldActionsResult, type UseFieldConditionsLazyOptions, type UseFormActionsResult, type UseFormConditionsProps, type UseFormConditionsReturn, type UseFormMonitoringProps, type UseFormMonitoringReturn, type UseFormSubmissionWithStoreProps, type UseFormValidationWithStoreProps, type UseRepeatableFieldReturn, createFormStore, flattenRepeatableValues, form, structureFormValues, useConditionEvaluation, useConditionEvaluator, useFieldActions, useFieldConditions, useFieldConditionsLazy, useFieldConditionsWithRefresh, useFieldErrors, useFieldState, useFieldTouched, useFieldValidationState, useFieldValue, useFormActions, useFormConditions, useFormConfigContext, useFormDirty, useFormMonitoring, useFormStore, useFormStoreApi, useFormSubmissionWithStore, useFormSubmitState, useFormSubmitting, useFormValid, useFormValidationWithStore, useFormValues, useMultipleConditionEvaluation, useRepeatableField, useRepeatableKeys };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,66 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ril, FieldValidationConfig, ConditionalBehavior, FormFieldConfig, FormFieldRow, FormValidationConfig, FormConfiguration, ComponentRendererBaseProps, FormBodyRendererProps, FieldConditions, FormState, ValidationError, ValidationState, FieldState, ValidationResult, MonitoringConfig, FormPerformanceMetrics, FormRowRendererProps, FormSubmitButtonRendererProps } from '@rilaykit/core';
2
+ import { ril, FieldValidationConfig, RepeatableFieldConfig, ConditionalBehavior, FormFieldConfig, FormRowEntry, FormValidationConfig, SubmitOptions, FormConfiguration, ComponentRendererBaseProps, FormBodyRendererProps, FieldConditions, FormState, ValidationError, ValidationState, FieldState, ValidationResult, RepeatableFieldItem, MonitoringConfig, FormPerformanceMetrics, FormRowRendererProps, FormFieldRow, FormSubmitButtonRendererProps } from '@rilaykit/core';
3
3
  import * as React$1 from 'react';
4
4
  import React__default from 'react';
5
5
  import * as zustand from 'zustand';
6
6
 
7
+ /**
8
+ * Fluent builder for configuring repeatable field groups
9
+ *
10
+ * Used via callback in `form.addRepeatable()`:
11
+ * ```typescript
12
+ * form.create(ril, "order")
13
+ * .addRepeatable("items", r => r
14
+ * .add(
15
+ * { id: "name", type: "text", props: { label: "Item" } },
16
+ * { id: "qty", type: "number", props: { label: "Qty" } }
17
+ * )
18
+ * .min(1)
19
+ * .max(10)
20
+ * .defaultValue({ name: "", qty: 1 })
21
+ * )
22
+ * .build()
23
+ * ```
24
+ */
25
+ declare class RepeatableBuilder<C extends Record<string, any>> {
26
+ private innerForm;
27
+ private _min?;
28
+ private _max?;
29
+ private _defaultValue?;
30
+ private _validation?;
31
+ constructor(config: ril<C>);
32
+ /**
33
+ * Add fields to the repeatable template
34
+ * Same API as form.add() — variadic ≤3 puts them on the same row
35
+ */
36
+ add<T extends keyof C & string>(...fields: FieldConfig<C, T>[]): this;
37
+ add<T extends keyof C & string>(fields: FieldConfig<C, T>[]): this;
38
+ /**
39
+ * Add fields each on their own row
40
+ */
41
+ addSeparateRows<T extends keyof C & string>(fields: FieldConfig<C, T>[]): this;
42
+ /**
43
+ * Set minimum number of items (defaults to 0)
44
+ */
45
+ min(value: number): this;
46
+ /**
47
+ * Set maximum number of items (unlimited if not set)
48
+ */
49
+ max(value: number): this;
50
+ /**
51
+ * Set default values for new items
52
+ */
53
+ defaultValue(value: Record<string, unknown>): this;
54
+ /**
55
+ * Set group-level validation (applied to the entire array)
56
+ */
57
+ validation(config: FieldValidationConfig): this;
58
+ /** @internal — called by form.addRepeatable */
59
+ _build(id: string): RepeatableFieldConfig;
60
+ /** @internal — check if the inner builder has repeatables (nesting forbidden) */
61
+ _hasRepeatables(): boolean;
62
+ }
63
+
7
64
  /**
8
65
  * Configuration for a form field with type safety
9
66
  *
@@ -88,6 +145,8 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
88
145
  private idGenerator;
89
146
  /** Form-level validation configuration */
90
147
  private formValidation?;
148
+ /** Default submit options for this form */
149
+ private _submitOptions?;
91
150
  /**
92
151
  * Creates a new form builder instance
93
152
  *
@@ -206,6 +265,30 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
206
265
  * ```
207
266
  */
208
267
  addSeparateRows<T extends keyof C & string>(fieldConfigs: FieldConfig<C, T>[]): this;
268
+ /**
269
+ * Adds a repeatable field group to the form
270
+ *
271
+ * Repeatable fields allow users to add/remove instances of a group of fields
272
+ * at runtime (e.g., "Add another item", "Add another contact").
273
+ *
274
+ * @param id - Unique identifier for the repeatable group (cannot contain [ or ])
275
+ * @param configure - Callback receiving a RepeatableBuilder for fluent configuration
276
+ * @returns The form builder instance for method chaining
277
+ *
278
+ * @example
279
+ * ```typescript
280
+ * builder.addRepeatable("items", r => r
281
+ * .add(
282
+ * { id: "name", type: "text", props: { label: "Item" } },
283
+ * { id: "qty", type: "number", props: { label: "Qty" } }
284
+ * )
285
+ * .min(1)
286
+ * .max(10)
287
+ * .defaultValue({ name: "", qty: 1 })
288
+ * );
289
+ * ```
290
+ */
291
+ addRepeatable(id: string, configure: (builder: RepeatableBuilder<C>) => RepeatableBuilder<C>): this;
209
292
  /**
210
293
  * Sets the form identifier
211
294
  *
@@ -308,7 +391,7 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
308
391
  * console.log(`Form has ${rows.length} rows`);
309
392
  * ```
310
393
  */
311
- getRows(): FormFieldRow[];
394
+ getRows(): FormRowEntry[];
312
395
  /**
313
396
  * Clears all fields and rows from the form
314
397
  *
@@ -349,6 +432,24 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
349
432
  * ```
350
433
  */
351
434
  setValidation(validationConfig: FormValidationConfig): this;
435
+ /**
436
+ * Sets default submit options for this form
437
+ *
438
+ * These options can be overridden at submit-time by passing options to `submit()`.
439
+ *
440
+ * @param options - Submit options to use as defaults
441
+ * @returns The form builder instance for method chaining
442
+ *
443
+ * @example
444
+ * ```typescript
445
+ * // Always skip invalid fields on submit
446
+ * builder.setSubmitOptions({ skipInvalid: true });
447
+ *
448
+ * // Force submit by default (bypass validation)
449
+ * builder.setSubmitOptions({ force: true });
450
+ * ```
451
+ */
452
+ setSubmitOptions(options: SubmitOptions): this;
352
453
  /**
353
454
  * Adds validators to the form-level validation
354
455
  *
@@ -516,16 +617,20 @@ declare class form<C extends Record<string, any> = Record<string, never>> {
516
617
  * - Useful for form complexity analysis
517
618
  */
518
619
  getStats(): {
519
- /** Total number of fields across all rows */
620
+ /** Total number of static fields across all rows */
520
621
  totalFields: number;
521
622
  /** Total number of rows in the form */
522
623
  totalRows: number;
523
- /** Average number of fields per row */
624
+ /** Average number of fields per row (field rows only) */
524
625
  averageFieldsPerRow: number;
525
626
  /** Maximum number of fields in any single row */
526
627
  maxFieldsInRow: number;
527
628
  /** Minimum number of fields in any single row */
528
629
  minFieldsInRow: number;
630
+ /** Total number of repeatable groups */
631
+ totalRepeatables: number;
632
+ /** Total number of fields across all repeatable templates */
633
+ totalRepeatableFields: number;
529
634
  };
530
635
  }
531
636
 
@@ -537,12 +642,14 @@ interface FormProps {
537
642
  className?: string;
538
643
  children: React.ReactNode;
539
644
  }
540
- declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, children }: FormProps): react_jsx_runtime.JSX.Element;
645
+ declare function Form({ formConfig, defaultValues, onSubmit, onFieldChange, className, children, }: FormProps): react_jsx_runtime.JSX.Element;
541
646
 
542
647
  declare const FormBody: React__default.NamedExoticComponent<ComponentRendererBaseProps<FormBodyRendererProps>>;
543
648
 
544
649
  interface FormFieldProps {
545
650
  fieldId: string;
651
+ /** Pre-resolved field config (used by RepeatableItem to skip allFields lookup) */
652
+ fieldConfig?: FormFieldConfig;
546
653
  disabled?: boolean;
547
654
  customProps?: Record<string, unknown>;
548
655
  className?: string;
@@ -626,6 +733,8 @@ declare function useFieldConditionsWithRefresh(fieldId: string, conditions?: Con
626
733
  interface UseFormConditionsProps {
627
734
  formConfig: FormConfiguration;
628
735
  formValues: Record<string, any>;
736
+ /** Active repeatable item keys, keyed by repeatable ID */
737
+ repeatableOrder?: Record<string, string[]>;
629
738
  }
630
739
  interface UseFormConditionsReturn {
631
740
  fieldConditions: Record<string, ConditionEvaluationResult>;
@@ -662,11 +771,14 @@ interface UseFormConditionsReturn {
662
771
  * }
663
772
  * ```
664
773
  */
665
- declare function useFormConditions({ formConfig, formValues, }: UseFormConditionsProps): UseFormConditionsReturn;
774
+ declare function useFormConditions({ formConfig, formValues, repeatableOrder, }: UseFormConditionsProps): UseFormConditionsReturn;
666
775
 
667
776
  interface FormStoreState extends FormState {
668
777
  _defaultValues: Record<string, unknown>;
669
778
  _fieldConditions: Record<string, FieldConditions>;
779
+ _repeatableConfigs: Record<string, RepeatableFieldConfig>;
780
+ _repeatableOrder: Record<string, string[]>;
781
+ _repeatableNextKey: Record<string, number>;
670
782
  _setValue: (fieldId: string, value: unknown) => void;
671
783
  _setTouched: (fieldId: string) => void;
672
784
  _setErrors: (fieldId: string, errors: ValidationError[]) => void;
@@ -676,6 +788,11 @@ interface FormStoreState extends FormState {
676
788
  _reset: (values?: Record<string, unknown>) => void;
677
789
  _setFieldConditions: (fieldId: string, conditions: FieldConditions) => void;
678
790
  _updateIsValid: () => void;
791
+ _setRepeatableConfig: (id: string, config: RepeatableFieldConfig) => void;
792
+ _appendRepeatableItem: (repeatableId: string, defaultValue?: Record<string, unknown>) => string | null;
793
+ _removeRepeatableItem: (repeatableId: string, key: string) => boolean;
794
+ _moveRepeatableItem: (repeatableId: string, fromIndex: number, toIndex: number) => void;
795
+ _insertRepeatableItem: (repeatableId: string, index: number, defaultValue?: Record<string, unknown>) => string | null;
679
796
  }
680
797
  type FormStore = ReturnType<typeof createFormStore>;
681
798
  declare function createFormStore(initialValues?: Record<string, unknown>): Omit<zustand.StoreApi<FormStoreState>, "subscribe"> & {
@@ -749,6 +866,10 @@ declare function useFormSubmitState(): {
749
866
  isValid: boolean;
750
867
  isDirty: boolean;
751
868
  };
869
+ /**
870
+ * Select ordered keys for a repeatable field — re-renders when the order changes
871
+ */
872
+ declare function useRepeatableKeys(repeatableId: string): string[];
752
873
  interface UseFieldActionsResult {
753
874
  setValue: (value: unknown) => void;
754
875
  setTouched: () => void;
@@ -783,9 +904,10 @@ interface UseFormSubmissionWithStoreProps {
783
904
  store: FormStore;
784
905
  onSubmit?: (data: Record<string, unknown>) => void | Promise<void>;
785
906
  validateForm: () => Promise<ValidationResult>;
907
+ defaultSubmitOptions?: SubmitOptions;
786
908
  }
787
- declare function useFormSubmissionWithStore({ store, onSubmit, validateForm, }: UseFormSubmissionWithStoreProps): {
788
- submit: (event?: React__default.FormEvent) => Promise<boolean>;
909
+ declare function useFormSubmissionWithStore({ store, onSubmit, validateForm, defaultSubmitOptions, }: UseFormSubmissionWithStoreProps): {
910
+ submit: (eventOrOptions?: React__default.FormEvent | SubmitOptions) => Promise<boolean>;
789
911
  };
790
912
 
791
913
  interface UseFormValidationWithStoreProps {
@@ -798,6 +920,45 @@ declare function useFormValidationWithStore({ formConfig, store, conditionsHelpe
798
920
  validateForm: () => Promise<ValidationResult>;
799
921
  };
800
922
 
923
+ interface UseRepeatableFieldReturn {
924
+ items: RepeatableFieldItem[];
925
+ append: (defaultValue?: Record<string, unknown>) => void;
926
+ remove: (key: string) => void;
927
+ move: (fromIndex: number, toIndex: number) => void;
928
+ canAdd: boolean;
929
+ canRemove: boolean;
930
+ count: number;
931
+ }
932
+ /**
933
+ * Hook to manage a repeatable field group
934
+ *
935
+ * Provides the list of items and actions to add, remove, and reorder them.
936
+ * Each item contains scoped field configs ready for rendering.
937
+ *
938
+ * @param repeatableId - The ID of the repeatable group (as defined in addRepeatable)
939
+ * @returns Items, actions, and constraints
940
+ *
941
+ * @example
942
+ * ```tsx
943
+ * const { items, append, remove, canAdd, canRemove } = useRepeatableField("items");
944
+ *
945
+ * return (
946
+ * <div>
947
+ * {items.map(item => (
948
+ * <div key={item.key}>
949
+ * {item.allFields.map(field => (
950
+ * <FormField key={field.id} fieldId={field.id} fieldConfig={field} />
951
+ * ))}
952
+ * {canRemove && <button onClick={() => remove(item.key)}>Remove</button>}
953
+ * </div>
954
+ * ))}
955
+ * {canAdd && <button onClick={append}>Add</button>}
956
+ * </div>
957
+ * );
958
+ * ```
959
+ */
960
+ declare function useRepeatableField(repeatableId: string): UseRepeatableFieldReturn;
961
+
801
962
  interface UseFormMonitoringProps {
802
963
  formConfig: FormConfiguration;
803
964
  monitoring?: MonitoringConfig;
@@ -818,7 +979,7 @@ interface FormConfigContextValue {
818
979
  conditionsHelpers: Omit<UseFormConditionsReturn, 'fieldConditions'>;
819
980
  validateField: (fieldId: string, value?: unknown) => Promise<ValidationResult>;
820
981
  validateForm: () => Promise<ValidationResult>;
821
- submit: (event?: React__default.FormEvent) => Promise<boolean>;
982
+ submit: (eventOrOptions?: React__default.FormEvent | SubmitOptions) => Promise<boolean>;
822
983
  }
823
984
  /**
824
985
  * Access form configuration and validation methods
@@ -848,4 +1009,53 @@ interface FormSubmitButtonProps extends ComponentRendererBaseProps<FormSubmitBut
848
1009
  }
849
1010
  declare const FormSubmitButton: React__default.NamedExoticComponent<FormSubmitButtonProps>;
850
1011
 
851
- export { type ConditionEvaluationResult, type FieldConfig, Form, FormBody, form as FormBuilder, type FormConfigContextValue, FormField, FormProvider, type FormProviderProps, FormRow, type FormStore, FormStoreContext, type FormStoreState, FormSubmitButton, type UseFieldActionsResult, type UseFieldConditionsLazyOptions, type UseFormActionsResult, type UseFormConditionsProps, type UseFormConditionsReturn, type UseFormMonitoringProps, type UseFormMonitoringReturn, type UseFormSubmissionWithStoreProps, type UseFormValidationWithStoreProps, createFormStore, form, useConditionEvaluation, useConditionEvaluator, useFieldActions, useFieldConditions, useFieldConditionsLazy, useFieldConditionsWithRefresh, useFieldErrors, useFieldState, useFieldTouched, useFieldValidationState, useFieldValue, useFormActions, useFormConditions, useFormConfigContext, useFormDirty, useFormMonitoring, useFormStore, useFormStoreApi, useFormSubmissionWithStore, useFormSubmitState, useFormSubmitting, useFormValid, useFormValidationWithStore, useFormValues, useMultipleConditionEvaluation };
1012
+ interface RepeatableFieldProps {
1013
+ repeatableId: string;
1014
+ repeatableConfig: RepeatableFieldConfig;
1015
+ className?: string;
1016
+ }
1017
+ declare const RepeatableField: React__default.NamedExoticComponent<RepeatableFieldProps>;
1018
+
1019
+ interface RepeatableItemProps {
1020
+ item: RepeatableFieldItem;
1021
+ index: number;
1022
+ total: number;
1023
+ canRemove: boolean;
1024
+ canMoveUp: boolean;
1025
+ canMoveDown: boolean;
1026
+ onRemove: () => void;
1027
+ onMoveUp: () => void;
1028
+ onMoveDown: () => void;
1029
+ }
1030
+ declare const RepeatableItem: React__default.NamedExoticComponent<RepeatableItemProps>;
1031
+
1032
+ /**
1033
+ * Converts flat store values with composite keys into structured nested data.
1034
+ *
1035
+ * Input (store values):
1036
+ * { customerName: "John", "items[k0].name": "Widget", "items[k0].qty": 2, "items[k1].name": "Gadget", "items[k1].qty": 1 }
1037
+ *
1038
+ * Output (structured):
1039
+ * { customerName: "John", items: [{ name: "Widget", qty: 2 }, { name: "Gadget", qty: 1 }] }
1040
+ */
1041
+ declare function structureFormValues(values: Record<string, unknown>, repeatableConfigs: Record<string, RepeatableFieldConfig>, repeatableOrder: Record<string, string[]>): Record<string, unknown>;
1042
+ /**
1043
+ * Converts structured nested data into flat store values with composite keys.
1044
+ *
1045
+ * Input (structured):
1046
+ * { customerName: "John", items: [{ name: "Widget", qty: 2 }, { name: "Gadget", qty: 1 }] }
1047
+ *
1048
+ * Output:
1049
+ * {
1050
+ * values: { customerName: "John", "items[k0].name": "Widget", "items[k0].qty": 2, "items[k1].name": "Gadget", "items[k1].qty": 1 },
1051
+ * order: { items: ["k0", "k1"] },
1052
+ * nextKeys: { items: 2 }
1053
+ * }
1054
+ */
1055
+ declare function flattenRepeatableValues(data: Record<string, unknown>, repeatableConfigs: Record<string, RepeatableFieldConfig>): {
1056
+ values: Record<string, unknown>;
1057
+ order: Record<string, string[]>;
1058
+ nextKeys: Record<string, number>;
1059
+ };
1060
+
1061
+ export { type ConditionEvaluationResult, type FieldConfig, Form, FormBody, form as FormBuilder, type FormConfigContextValue, FormField, FormProvider, type FormProviderProps, FormRow, type FormStore, FormStoreContext, type FormStoreState, FormSubmitButton, RepeatableBuilder, RepeatableField, RepeatableItem, type UseFieldActionsResult, type UseFieldConditionsLazyOptions, type UseFormActionsResult, type UseFormConditionsProps, type UseFormConditionsReturn, type UseFormMonitoringProps, type UseFormMonitoringReturn, type UseFormSubmissionWithStoreProps, type UseFormValidationWithStoreProps, type UseRepeatableFieldReturn, createFormStore, flattenRepeatableValues, form, structureFormValues, useConditionEvaluation, useConditionEvaluator, useFieldActions, useFieldConditions, useFieldConditionsLazy, useFieldConditionsWithRefresh, useFieldErrors, useFieldState, useFieldTouched, useFieldValidationState, useFieldValue, useFormActions, useFormConditions, useFormConfigContext, useFormDirty, useFormMonitoring, useFormStore, useFormStoreApi, useFormSubmissionWithStore, useFormSubmitState, useFormSubmitting, useFormValid, useFormValidationWithStore, useFormValues, useMultipleConditionEvaluation, useRepeatableField, useRepeatableKeys };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- 'use strict';var Xe=require('react'),core=require('@rilaykit/core'),zustand=require('zustand'),middleware=require('zustand/middleware'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var Xe__default=/*#__PURE__*/_interopDefault(Xe);var x=class o{constructor(e,t){this.rows=[];this.idGenerator=new core.IdGenerator;this.config=e,this.formId=t||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,t){return new o(e,t)}createFormField(e){let t=this.config.getComponent(e.type);if(!t)throw new Error(`No component found with type "${e.type}"`);let i;return (t.validation||e.validation)&&(i={validateOnChange:e.validation?.validateOnChange??t.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??t.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??t.validation?.debounceMs,validate:(()=>{let r=t.validation?.validate,n=e.validation?.validate;if(!r)return n;if(!n)return r;let a=Array.isArray(r)?r:[r],s=Array.isArray(n)?n:[n];return [...a,...s]})()}),{id:e.id||this.idGenerator.next("field"),componentId:t.id,props:{...t.defaultProps,...e.props},validation:i,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 t=e.map(i=>this.createFormField(i));return {id:this.idGenerator.next("row"),fields:t,maxColumns:e.length}}add(...e){let t,i=false;if(e.length===1&&Array.isArray(e[0])?(t=e[0],i=true):t=e,t.length===0)throw new Error("At least one field is required");if(i&&t.length>3)throw new Error("Maximum 3 fields per row");if(t.length===1){let r=this.createRow(t);return this.rows.push(r),this}if(t.length<=3){let r=this.createRow(t);return this.rows.push(r),this}for(let r of t){let n=this.createRow([r]);this.rows.push(n);}return this}addSeparateRows(e){for(let t of e)this.add(t);return this}setId(e){return this.formId=e,this}updateField(e,t){let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);return Object.assign(i,{...t,props:{...i.props,...t.props}}),this}findField(e){for(let t of this.rows){let i=t.fields.find(r=>r.id===e);if(i)return i}return null}removeField(e){return this.rows=this.rows.map(t=>({...t,fields:t.fields.filter(i=>i.id!==e)})).filter(t=>t.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,t){console.warn("addFieldValidation is deprecated. Use updateField with validation.validate property instead.");let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);let r={...i.validation,...t};return this.updateField(e,{validation:r})}addFieldConditions(e,t){let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);let r={...i.conditions,...t};return this.updateField(e,{conditions:r})}clone(e){let t=new o(this.config,e||`${this.formId}-clone`);return t.rows=core.deepClone(this.rows),t}validate(){let e=[],t=this.getFields(),i=t.map(r=>r.id);try{core.ensureUnique(i,"field");}catch(r){e.push(r instanceof Error?r.message:String(r));}for(let r of t)this.config.hasComponent(r.componentId)||e.push(`Component "${r.componentId}" not found for field "${r.id}"`);for(let r of this.rows)r.fields.length>3&&e.push(`Row "${r.id}" has ${r.fields.length} fields, maximum is 3`),r.fields.length===0&&e.push(`Row "${r.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(),t=this.rows.map(i=>i.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:t.length>0?Math.max(...t):0,minFieldsInRow:t.length>0?Math.min(...t):0}}};function Ft(o,e={},t={}){return Xe.useMemo(()=>{if(!o)return {visible:t.visible??true,disabled:t.disabled??false,required:t.required??false,readonly:t.readonly??false};let i=r=>{try{return r&&typeof r=="object"&&"build"in r?core.evaluateCondition(r.build(),e):core.evaluateCondition(r,e)}catch(n){return console.warn("Error evaluating condition:",n),false}};return {visible:o.visible?i(o.visible):t.visible??true,disabled:o.disabled?i(o.disabled):t.disabled??false,required:o.required?i(o.required):t.required??false,readonly:o.readonly?i(o.readonly):t.readonly??false}},[o,e,t])}function oe(o,e={}){return Xe.useMemo(()=>{let t={};for(let[i,r]of Object.entries(o))if(t[i]={visible:true,disabled:false,required:false,readonly:false},r){let n=a=>{try{return a&&typeof a=="object"&&"build"in a?core.evaluateCondition(a.build(),e):core.evaluateCondition(a,e)}catch(s){return console.warn(`Error evaluating condition for field ${i}:`,s),false}};t[i]={visible:r.visible?n(r.visible):true,disabled:r.disabled?n(r.disabled):false,required:r.required?n(r.required):false,readonly:r.readonly?n(r.readonly):false};}return t},[o,e])}function $(o={}){return zustand.createStore()(middleware.subscribeWithSelector((e,t)=>({values:{...o},errors:{},validationStates:{},touched:{},isDirty:false,isSubmitting:false,isValid:true,_defaultValues:{...o},_fieldConditions:{},_setValue:(i,r)=>{e(n=>({values:{...n.values,[i]:r},isDirty:true}));},_setTouched:i=>{e(r=>({touched:{...r.touched,[i]:true}}));},_setErrors:(i,r)=>{e(n=>{let a={...n.errors,[i]:r},s=r.length>0?"invalid":"valid";return {errors:a,validationStates:{...n.validationStates,[i]:s}}}),t()._updateIsValid();},_clearErrors:i=>{e(r=>{let n={...r.errors};return delete n[i],{errors:n,validationStates:{...r.validationStates,[i]:"idle"}}}),t()._updateIsValid();},_setValidationState:(i,r)=>{e(n=>({validationStates:{...n.validationStates,[i]:r}}));},_setSubmitting:i=>{e({isSubmitting:i});},_reset:i=>{let r=i??t()._defaultValues;e({values:{...r},errors:{},validationStates:{},touched:{},isDirty:false,isSubmitting:false,isValid:true});},_setFieldConditions:(i,r)=>{e(n=>({_fieldConditions:{...n._fieldConditions,[i]:r}}));},_updateIsValid:()=>{let i=t(),r=Object.values(i.errors).some(a=>a&&a.length>0),n=Object.values(i.validationStates).some(a=>a==="invalid");e({isValid:!r&&!n});}})))}var O=Xe.createContext(null);function v(){let o=Xe.useContext(O);if(!o)throw new Error("useFormStore must be used within a FormProvider");return o}var re=[];function N(o){let e=v();return zustand.useStore(e,t=>t.values[o])}function Me(o){let e=v();return zustand.useStore(e,t=>t.errors[o]??re)}function Be(o){let e=v();return zustand.useStore(e,t=>t.touched[o]??false)}function Te(o){let e=v();return zustand.useStore(e,t=>t.validationStates[o]??"idle")}var De={visible:true,disabled:false,required:false,readonly:false};function P(o){let e=v();return zustand.useStore(e,t=>t._fieldConditions[o]??De)}function W(o){let e=v(),t=zustand.useStore(e,s=>s.values[o]),i=zustand.useStore(e,s=>s.errors[o]??re),r=zustand.useStore(e,s=>s.validationStates[o]??"idle"),n=zustand.useStore(e,s=>s.touched[o]??false),a=zustand.useStore(e,s=>s._defaultValues[o]);return {value:t,errors:i,validationState:r,touched:n,dirty:t!==a}}function qe(){let o=v();return zustand.useStore(o,e=>e.isSubmitting)}function Oe(){let o=v();return zustand.useStore(o,e=>e.isValid)}function Ue(){let o=v();return zustand.useStore(o,e=>e.isDirty)}function Ae(){let o=v();return zustand.useStore(o,e=>e.values)}function H(){let o=v(),e=zustand.useStore(o,r=>r.isSubmitting),t=zustand.useStore(o,r=>r.isValid),i=zustand.useStore(o,r=>r.isDirty);return {isSubmitting:e,isValid:t,isDirty:i}}function L(o){let e=v();return {setValue:t=>e.getState()._setValue(o,t),setTouched:()=>e.getState()._setTouched(o),setErrors:t=>e.getState()._setErrors(o,t),clearErrors:()=>e.getState()._clearErrors(o),setValidationState:t=>e.getState()._setValidationState(o,t)}}function Ie(){let o=v();return {setValue:(e,t)=>o.getState()._setValue(e,t),setTouched:e=>o.getState()._setTouched(e),setErrors:(e,t)=>o.getState()._setErrors(e,t),setSubmitting:e=>o.getState()._setSubmitting(e),reset:e=>o.getState()._reset(e),setFieldConditions:(e,t)=>o.getState()._setFieldConditions(e,t)}}function B(){return v()}var se={visible:true,disabled:false,required:false,readonly:false};function ae(o){try{return JSON.stringify(o)}catch{return String(Date.now())}}function U(o,e){if(o)try{return typeof o=="object"&&"build"in o?core.evaluateCondition(o.build(),e):core.evaluateCondition(o,e)}catch(t){console.warn("Error evaluating condition:",t);return}}function j(o,e){if(!o)return se;let t=U(o.visible,e),i=U(o.disabled,e),r=U(o.required,e),n=U(o.readonly,e);return {visible:t??true,disabled:i??false,required:r??false,readonly:n??false}}function Vt(o,e={}){let{conditions:t,skip:i=false}=e,r=B(),n=P(o),a=Xe.useRef(null);if(i||!t)return n;let s=r.getState().values,F=ae(s);if(a.current?.valuesHash===F)return a.current.result;let m=j(t,s);return a.current={result:m,valuesHash:F},m}function xt(){let o=B(),e=Xe.useRef(new Map),t=Xe.useRef("");return Xe.useMemo(()=>function(r,n){if(!n)return se;let a=o.getState().values,s=ae(a);t.current!==s&&(e.current.clear(),t.current=s);let F=e.current.get(r);if(F)return F.result;let m=j(n,a);return e.current.set(r,{result:m,valuesHash:s}),m},[o])}function Pt(o,e){let t=B(),i=P(o),r=Xe.useMemo(()=>()=>{if(!e)return i;let n=t.getState().values;return j(e,n)},[t,e,i]);return {conditions:i,refresh:r}}function de({formConfig:o,formValues:e}){let t=Xe.useMemo(()=>{let l={};for(let u of o.allFields)u.conditions&&(l[u.id]=u.conditions);return l},[o.allFields]),i=Xe.useMemo(()=>Object.keys(t).length>0,[t]),r=oe(i?t:{},i?e:{}),n=Xe.useCallback(l=>r[l],[r]),a=Xe.useCallback(l=>{let u=r[l];return u?u.visible:true},[r]),s=Xe.useCallback(l=>{let u=r[l];return u?u.disabled:false},[r]),F=Xe.useCallback(l=>{let u=r[l];return u?u.required:false},[r]),m=Xe.useCallback(l=>{let u=r[l];return u?u.readonly:false},[r]);return Xe.useMemo(()=>({fieldConditions:r,hasConditionalFields:i,getFieldCondition:n,isFieldVisible:a,isFieldDisabled:s,isFieldRequired:F,isFieldReadonly:m}),[r,i,n,a,s,F,m])}function le({store:o,onSubmit:e,validateForm:t}){let i=Xe.useRef(e);return i.current=e,{submit:Xe.useCallback(async n=>{n?.preventDefault();let a=o.getState();if(a.isSubmitting)return false;a._setSubmitting(true);try{if(!(await t()).isValid)return a._setSubmitting(!1),!1;let F=o.getState().values;return i.current&&await i.current(F),a._setSubmitting(!1),!0}catch(s){return a._setSubmitting(false),console.error("Form submission error:",s),false}},[o,t])}}function A(){return {isValid:true,errors:[]}}function fe({formConfig:o,store:e,conditionsHelpers:t}){let i=Xe.useRef(o),r=Xe.useRef(t);i.current=o,r.current=t;let n=Xe.useCallback(async(s,F)=>{let m=i.current.allFields.find(d=>d.id===s),l=e.getState();if(!m)return A();if(!r.current.isFieldVisible(s))return l._setErrors(s,[]),l._setValidationState(s,"valid"),A();if(!m.validation||!core.hasUnifiedValidation(m.validation))return l._setErrors(s,[]),l._setValidationState(s,"valid"),A();let u=F!==void 0?F:l.values[s],c=core.createValidationContext({fieldId:s,formId:i.current.id,allFormData:{...l.values,[s]:u}});l._setValidationState(s,"validating");try{let d=await core.validateWithUnifiedConfig(m.validation,u,c),f=r.current.isFieldRequired(s),p=u==null||u==="";if(f&&p&&!d.errors.some(g=>g.code==="REQUIRED"||g.message.toLowerCase().includes("required"))){let g={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...d.errors]};return l._setErrors(s,g.errors),l._setValidationState(s,"invalid"),g}return l._setErrors(s,d.errors),l._setValidationState(s,d.isValid?"valid":"invalid"),d}catch(d){let f={isValid:false,errors:[{message:d instanceof Error?d.message:"Validation failed",code:"VALIDATION_ERROR"}]};return l._setErrors(s,f.errors),l._setValidationState(s,"invalid"),f}},[e]),a=Xe.useCallback(async()=>{let s=e.getState(),F=i.current.allFields.filter(d=>{let f=r.current.isFieldVisible(d.id),p=d.validation&&core.hasUnifiedValidation(d.validation);return f&&p}),m=i.current.allFields.filter(d=>!r.current.isFieldVisible(d.id));for(let d of m)s._setErrors(d.id,[]),s._setValidationState(d.id,"valid");let l=await Promise.all(F.map(d=>n(d.id))),u=l.some(d=>!d.isValid),c=A();if(i.current.validation&&core.hasUnifiedValidation(i.current.validation)){let d=Object.keys(s.values).reduce((p,b)=>(r.current.isFieldVisible(b)&&(p[b]=s.values[b]),p),{}),f=core.createValidationContext({formId:i.current.id,allFormData:d});try{c=await core.validateFormWithUnifiedConfig(i.current.validation,d,f);}catch(p){c={isValid:false,errors:[{message:p instanceof Error?p.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!u&&c.isValid,errors:[...l.flatMap(d=>d.errors),...c.errors]}},[e,n]);return {validateField:n,validateForm:a}}function je({formConfig:o,enabled:e=true}){let t=core.getGlobalMonitor(),i=Xe.useRef(null),r=Xe.useRef(0),n=Xe.useRef(0);Xe.useEffect(()=>{t&&e&&(i.current=t.getProfiler());},[t,e]);let a=Xe.useCallback(c=>{if(!t||!e)return;r.current++;let d={formId:o.id,fieldCount:o.allFields.length,timestamp:Date.now(),duration:0,renderDuration:0,validationDuration:0,validationErrors:0,renderCount:c||r.current};t.track("component_render",`form_${o.id}`,{formId:o.id,fieldCount:o.allFields.length,renderCount:r.current},d,"low");},[t,e,o.id,o.allFields.length]),s=Xe.useCallback((c,d)=>{if(!t||!e)return;let f=i.current?.getMetrics(`form_validation_${o.id}`),p={formId:o.id,fieldCount:d||o.allFields.length,timestamp:Date.now(),duration:f?.duration||0,renderDuration:0,validationDuration:f?.duration||0,validationErrors:c,renderCount:r.current};t.track("form_validation",`form_${o.id}`,{formId:o.id,validationErrors:c,fieldCount:d||o.allFields.length},p,c>0?"medium":"low");},[t,e,o.id,o.allFields.length]),F=Xe.useCallback((c,d)=>{if(!t||!e)return;let f=i.current?.getMetrics(`form_submission_${o.id}`),p={formId:o.id,fieldCount:d||o.allFields.length,timestamp:Date.now(),duration:f?.duration||0,renderDuration:0,validationDuration:0,validationErrors:c?0:1,renderCount:r.current};t.track("form_submission",`form_${o.id}`,{formId:o.id,success:c,fieldCount:d||o.allFields.length,fieldChanges:n.current},p,c?"low":"high");},[t,e,o.id,o.allFields.length]),m=Xe.useCallback((c,d)=>{!t||!e||(n.current++,t.track("component_update",`field_${c}`,{formId:o.id,fieldId:c,componentType:d,changeCount:n.current},void 0,"low"));},[t,e,o.id]),l=Xe.useCallback(c=>{!i.current||!e||i.current.start(c,{formId:o.id,renderCount:r.current});},[e,o.id]),u=Xe.useCallback(c=>{if(!i.current||!e)return null;let d=i.current.end(c);return d?{...d,formId:o.id,fieldCount:o.allFields.length,renderDuration:d.duration,validationDuration:0,validationErrors:0}:null},[e,o.id,o.allFields.length]);return {trackFormRender:a,trackFormValidation:s,trackFormSubmission:F,trackFieldChange:m,startPerformanceTracking:l,endPerformanceTracking:u}}var Ce=Xe.createContext(null);function y(){let o=Xe.useContext(Ce);if(!o)throw new Error("useFormConfigContext must be used within a FormProvider");return o}function K({children:o,formConfig:e,defaultValues:t={},onSubmit:i,onFieldChange:r,className:n}){let[a]=Xe.useState(()=>$(t)),s=Xe.useRef(e.id),F=Xe.useRef(r);F.current=r,Xe.useEffect(()=>F.current?a.subscribe(C=>C.values,(C,M)=>{for(let R of Object.keys(C))C[R]!==M[R]&&F.current?.(R,C[R],C);}):void 0,[a]),Xe.useEffect(()=>{s.current!==e.id&&(s.current=e.id,a.getState()._reset(t));},[e.id,a,t]);let[m,l]=Xe.useState(()=>a.getState().values);Xe.useEffect(()=>a.subscribe(C=>C.values,C=>l(C)),[a]);let{fieldConditions:u,hasConditionalFields:c,getFieldCondition:d,isFieldVisible:f,isFieldDisabled:p,isFieldRequired:b,isFieldReadonly:g}=de({formConfig:e,formValues:m});Xe.useEffect(()=>{for(let[V,C]of Object.entries(u)){let M={visible:C.visible,disabled:C.disabled,required:C.required,readonly:C.readonly};a.getState()._setFieldConditions(V,M);}},[u,a]);let w=Xe.useMemo(()=>({hasConditionalFields:c,getFieldCondition:d,isFieldVisible:f,isFieldDisabled:p,isFieldRequired:b,isFieldReadonly:g}),[c,d,f,p,b,g]),{validateField:_,validateForm:S}=fe({formConfig:e,store:a,conditionsHelpers:w}),{submit:k}=le({store:a,onSubmit:i,validateForm:S}),D=Xe.useMemo(()=>({formConfig:e,conditionsHelpers:w,validateField:_,validateForm:S,submit:k}),[e,w,_,S,k]);return jsxRuntime.jsx(O.Provider,{value:a,children:jsxRuntime.jsx(Ce.Provider,{value:D,children:jsxRuntime.jsx("form",{onSubmit:k,className:n,noValidate:true,children:o})})})}function Ye({formConfig:o,defaultValues:e,onSubmit:t,onFieldChange:i,children:r}){let n=Xe.useMemo(()=>o instanceof x?o.build():o,[o]);return jsxRuntime.jsx(K,{formConfig:n,defaultValues:e,onSubmit:t,onFieldChange:i,children:r})}var Z=Xe__default.default.memo(function({fieldId:e,disabled:t=false,customProps:i={},className:r,forceVisible:n=false}){let{formConfig:a,validateField:s,conditionsHelpers:F}=y(),m=N(e),l=W(e),u=P(e),{setValue:c,setTouched:d}=L(e),f=a.allFields.find(R=>R.id===e);if(!f)throw new Error(`Field with ID "${e}" not found`);let p=a.config.getComponent(f.componentId);if(!p)throw new Error(`Component with ID "${f.componentId}" not found`);let b=l.validationState==="validating",g=Xe.useMemo(()=>({isVisible:n||u.visible,isFieldDisabled:t||u.disabled,isFieldRequired:u.required||F.isFieldRequired(e),isFieldReadonly:u.readonly}),[n,t,u,F,e]),w=Xe.useCallback(async R=>{c(R),(f.validation?.validateOnChange||l.touched)&&await s(e,R);},[e,c,s,f.validation?.validateOnChange,l.touched]),_=Xe.useCallback(async()=>{l.touched||d(),f.validation?.validateOnBlur!==false&&await s(e);},[e,l.touched,d,s,f.validation?.validateOnBlur]),S=Xe.useMemo(()=>({...p.defaultProps??{},...f.props,...i,disabled:g.isFieldDisabled,required:g.isFieldRequired,readOnly:g.isFieldReadonly}),[p.defaultProps,f.props,i,g.isFieldDisabled,g.isFieldRequired,g.isFieldReadonly]),k=Xe.useMemo(()=>({id:e,props:S,value:m,onChange:w,onBlur:_,disabled:g.isFieldDisabled,error:l.errors,isValidating:b,touched:l.touched}),[e,S,m,w,_,g.isFieldDisabled,l.errors,b,l.touched]);if(!g.isVisible)return null;let D=p.renderer(k),V=a.renderConfig?.fieldRenderer,C=p.useFieldRenderer!==false,M=V&&C?V({children:D,id:e,...S,error:l.errors,isValidating:b,touched:l.touched}):D;return jsxRuntime.jsx("div",{className:r,"data-field-id":e,"data-field-type":p.type,"data-field-visible":g.isVisible,"data-field-disabled":g.isFieldDisabled,"data-field-required":g.isFieldRequired,"data-field-readonly":g.isFieldReadonly,children:M})});var be=Xe__default.default.memo(function({row:e,className:t,...i}){let{formConfig:r,conditionsHelpers:n}=y(),a=Xe.useMemo(()=>e.fields.filter(m=>n.isFieldVisible(m.id)),[e.fields,n]),s=Xe.useMemo(()=>a.map(m=>jsxRuntime.jsx(Z,{fieldId:m.id},m.id)),[a]),F=Xe.useMemo(()=>({row:e,children:s,className:t}),[e,s,t]);return a.length===0?null:jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormRow",renderer:r.renderConfig?.rowRenderer,props:F,...i,children:s})}),Re=be;var it=Xe__default.default.memo(function({className:e,...t}){let{formConfig:i}=y(),r=Xe.useMemo(()=>i.rows.map(a=>jsxRuntime.jsx(Re,{row:a},a.id)),[i.rows]),n=Xe.useMemo(()=>({formConfig:i,children:r,className:e}),[i,r,e]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormBody",renderer:i.renderConfig?.bodyRenderer,props:n,...t,children:r})});var dt=Xe__default.default.memo(function({className:e,isSubmitting:t,...i}){let{formConfig:r,submit:n}=y(),{isSubmitting:a}=H(),s=Xe.useMemo(()=>({isSubmitting:t??a,onSubmit:n,className:e}),[t,a,n,e]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormSubmitButton",renderer:r.renderConfig?.submitButtonRenderer,props:s,...i})});exports.Form=Ye;exports.FormBody=it;exports.FormBuilder=x;exports.FormField=Z;exports.FormProvider=K;exports.FormRow=be;exports.FormStoreContext=O;exports.FormSubmitButton=dt;exports.createFormStore=$;exports.form=x;exports.useConditionEvaluation=Ft;exports.useConditionEvaluator=xt;exports.useFieldActions=L;exports.useFieldConditions=P;exports.useFieldConditionsLazy=Vt;exports.useFieldConditionsWithRefresh=Pt;exports.useFieldErrors=Me;exports.useFieldState=W;exports.useFieldTouched=Be;exports.useFieldValidationState=Te;exports.useFieldValue=N;exports.useFormActions=Ie;exports.useFormConditions=de;exports.useFormConfigContext=y;exports.useFormDirty=Ue;exports.useFormMonitoring=je;exports.useFormStore=v;exports.useFormStoreApi=B;exports.useFormSubmissionWithStore=le;exports.useFormSubmitState=H;exports.useFormSubmitting=qe;exports.useFormValid=Oe;exports.useFormValidationWithStore=fe;exports.useFormValues=Ae;exports.useMultipleConditionEvaluation=oe;
1
+ 'use strict';var Mt=require('react'),core=require('@rilaykit/core'),zustand=require('zustand'),middleware=require('zustand/middleware'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var Mt__default=/*#__PURE__*/_interopDefault(Mt);var W=class{constructor(e){this.innerForm=new T(e,"__repeatable_template__");}add(...e){return this.innerForm.add(...e),this}addSeparateRows(e){return this.innerForm.addSeparateRows(e),this}min(e){return this._min=e,this}max(e){return this._max=e,this}defaultValue(e){return this._defaultValue=e,this}validation(e){return this._validation=e,this}_build(e){let t=this.innerForm.getRows(),i=this.innerForm.getFields();if(t.length===0)throw new Error(`Repeatable "${e}" must have at least one field`);for(let o of i)if(o.id.includes("[")||o.id.includes("]"))throw new Error(`Repeatable template field ID "${o.id}" cannot contain "[" or "]" (reserved for composite keys)`);if(this._min!==void 0&&this._max!==void 0&&this._min>this._max)throw new Error(`Repeatable "${e}": min (${this._min}) cannot be greater than max (${this._max})`);return {id:e,rows:t.map(o=>({...o,kind:"fields"})),allFields:i,min:this._min,max:this._max,defaultValue:this._defaultValue,validation:this._validation}}_hasRepeatables(){return this.innerForm.getRows().some(e=>"kind"in e&&e.kind==="repeatable")}};var T=class r{constructor(e,t){this.rows=[];this.idGenerator=new core.IdGenerator;this.config=e,this.formId=t||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,t){return new r(e,t)}createFormField(e){let t=this.config.getComponent(e.type);if(!t)throw new Error(`No component found with type "${e.type}"`);let i;return (t.validation||e.validation)&&(i={validateOnChange:e.validation?.validateOnChange??t.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??t.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??t.validation?.debounceMs,validate:(()=>{let o=t.validation?.validate,s=e.validation?.validate;if(!o)return s;if(!s)return o;let a=Array.isArray(o)?o:[o],n=Array.isArray(s)?s:[s];return [...a,...n]})()}),{id:e.id||this.idGenerator.next("field"),componentId:t.id,props:{...t.defaultProps,...e.props},validation:i,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 t=e.map(i=>this.createFormField(i));return {kind:"fields",id:this.idGenerator.next("row"),fields:t,maxColumns:e.length}}add(...e){let t,i=false;if(e.length===1&&Array.isArray(e[0])?(t=e[0],i=true):t=e,t.length===0)throw new Error("At least one field is required");if(i&&t.length>3)throw new Error("Maximum 3 fields per row");if(t.length===1){let o=this.createRow(t);return this.rows.push(o),this}if(t.length<=3){let o=this.createRow(t);return this.rows.push(o),this}for(let o of t){let s=this.createRow([o]);this.rows.push(s);}return this}addSeparateRows(e){for(let t of e)this.add(t);return this}addRepeatable(e,t){if(e.includes("[")||e.includes("]"))throw new Error(`Repeatable ID "${e}" cannot contain "[" or "]" (reserved for composite keys)`);let i=new W(this.config),o=t(i);if(o._hasRepeatables())throw new Error(`Nested repeatables are not supported (in repeatable "${e}")`);let s=o._build(e),a={kind:"repeatable",id:this.idGenerator.next("repeatable"),repeatable:s};return this.rows.push(a),this}setId(e){return this.formId=e,this}updateField(e,t){let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);return Object.assign(i,{...t,props:{...i.props,...t.props}}),this}findField(e){for(let t of this.rows)if(t.kind==="fields"){let i=t.fields.find(o=>o.id===e);if(i)return i}else {let i=t.repeatable.allFields.find(o=>o.id===e);if(i)return i}return null}removeField(e){return this.rows=this.rows.map(t=>t.kind==="repeatable"?t:{...t,fields:t.fields.filter(i=>i.id!==e)}).filter(t=>t.kind==="repeatable"||t.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.filter(e=>e.kind==="fields").flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.idGenerator.reset(),this}setValidation(e){return this.formValidation=e,this}setSubmitOptions(e){return this._submitOptions=e,this}addFieldValidation(e,t){console.warn("addFieldValidation is deprecated. Use updateField with validation.validate property instead.");let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);let o={...i.validation,...t};return this.updateField(e,{validation:o})}addFieldConditions(e,t){let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);let o={...i.conditions,...t};return this.updateField(e,{conditions:o})}clone(e){let t=new r(this.config,e||`${this.formId}-clone`);return t.rows=core.deepClone(this.rows),t}validate(){let e=[],t=this.getFields(),i=this.rows.filter(n=>n.kind==="repeatable"),o=i.flatMap(n=>n.repeatable.allFields),s=[...t.map(n=>n.id),...o.map(n=>n.id)];try{core.ensureUnique(s,"field");}catch(n){e.push(n instanceof Error?n.message:String(n));}let a=i.map(n=>n.repeatable.id);try{core.ensureUnique(a,"repeatable");}catch(n){e.push(n instanceof Error?n.message:String(n));}for(let n of t)this.config.hasComponent(n.componentId)||e.push(`Component "${n.componentId}" not found for field "${n.id}"`);for(let n of o)this.config.hasComponent(n.componentId)||e.push(`Component "${n.componentId}" not found for repeatable template field "${n.id}"`);for(let n of this.rows)n.kind==="fields"&&(n.fields.length>3&&e.push(`Row "${n.id}" has ${n.fields.length} fields, maximum is 3`),n.fields.length===0&&e.push(`Row "${n.id}" is empty`));for(let n of t)(n.id.includes("[")||n.id.includes("]"))&&e.push(`Field ID "${n.id}" cannot contain "[" or "]" (reserved for repeatable composite keys)`);for(let n of a)(n.includes("[")||n.includes("]"))&&e.push(`Repeatable ID "${n}" cannot contain "[" or "]" (reserved for composite keys)`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);let t=this.rows.filter(o=>o.kind==="repeatable"),i=t.length>0?Object.fromEntries(t.map(o=>[o.repeatable.id,o.repeatable])):void 0;return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),repeatableFields:i,config:this.config,renderConfig:this.config.getFormRenderConfig(),validation:this.formValidation,submitOptions:this._submitOptions}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows.map(t=>t.kind?t:{...t,kind:"fields"})),this}getStats(){let e=this.getFields(),t=this.rows.filter(s=>s.kind==="fields"),i=this.rows.filter(s=>s.kind==="repeatable"),o=t.map(s=>s.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:t.length>0?e.length/t.length:0,maxFieldsInRow:o.length>0?Math.max(...o):0,minFieldsInRow:o.length>0?Math.min(...o):0,totalRepeatables:i.length,totalRepeatableFields:i.reduce((s,a)=>s+a.repeatable.allFields.length,0)}}};function tr(r,e={},t={}){return Mt.useMemo(()=>{if(!r)return {visible:t.visible??true,disabled:t.disabled??false,required:t.required??false,readonly:t.readonly??false};let i=o=>{try{return o&&typeof o=="object"&&"build"in o?core.evaluateCondition(o.build(),e):core.evaluateCondition(o,e)}catch(s){return console.warn("Error evaluating condition:",s),false}};return {visible:r.visible?i(r.visible):t.visible??true,disabled:r.disabled?i(r.disabled):t.disabled??false,required:r.required?i(r.required):t.required??false,readonly:r.readonly?i(r.readonly):t.readonly??false}},[r,e,t])}function Te(r,e={}){return Mt.useMemo(()=>{let t={};for(let[i,o]of Object.entries(r))if(t[i]={visible:true,disabled:false,required:false,readonly:false},o){let s=a=>{try{return a&&typeof a=="object"&&"build"in a?core.evaluateCondition(a.build(),e):core.evaluateCondition(a,e)}catch(n){return console.warn(`Error evaluating condition for field ${i}:`,n),false}};t[i]={visible:o.visible?s(o.visible):true,disabled:o.disabled?s(o.disabled):false,required:o.required?s(o.required):false,readonly:o.readonly?s(o.readonly):false};}return t},[r,e])}var nt=/^([^[\]]+)\[([^\]]+)\]\.(.+)$/;function V(r,e,t){return `${r}[${e}].${t}`}function L(r){let e=nt.exec(r);return e?{repeatableId:e[1],itemKey:e[2],fieldId:e[3]}:null}function re(r,e,t){let i={},o=new Set;for(let[s,a]of Object.entries(t)){if(!e[s])continue;let n=e[s],f=[];for(let p of a){let m={};for(let c of n.allFields){let l=V(s,p,c.id);l in r&&(m[c.id]=r[l],o.add(l));}f.push(m);}i[s]=f;}for(let[s,a]of Object.entries(r))!o.has(s)&&!L(s)&&(i[s]=a);return i}function oe(r,e){let t={},i={},o={};for(let[s,a]of Object.entries(r))if(e[s]&&Array.isArray(a)){let n=[],f=0;for(let p of a){let m=`k${f}`;n.push(m);for(let[c,l]of Object.entries(p))t[V(s,m,c)]=l;f++;}i[s]=n,o[s]=f;}else t[s]=a;return {values:t,order:i,nextKeys:o}}function ue(r={}){return zustand.createStore()(middleware.subscribeWithSelector((e,t)=>({values:{...r},errors:{},validationStates:{},touched:{},isDirty:false,isSubmitting:false,isValid:true,_defaultValues:{...r},_fieldConditions:{},_repeatableConfigs:{},_repeatableOrder:{},_repeatableNextKey:{},_setValue:(i,o)=>{e(s=>({values:{...s.values,[i]:o},isDirty:true}));},_setTouched:i=>{e(o=>({touched:{...o.touched,[i]:true}}));},_setErrors:(i,o)=>{e(s=>{let a={...s.errors,[i]:o},n=o.length>0?"invalid":"valid";return {errors:a,validationStates:{...s.validationStates,[i]:n}}}),t()._updateIsValid();},_clearErrors:i=>{e(o=>{let s={...o.errors};return delete s[i],{errors:s,validationStates:{...o.validationStates,[i]:"idle"}}}),t()._updateIsValid();},_setValidationState:(i,o)=>{e(s=>({validationStates:{...s.validationStates,[i]:o}}));},_setSubmitting:i=>{e({isSubmitting:i});},_reset:i=>{let o=i??t()._defaultValues;e({values:{...o},errors:{},validationStates:{},touched:{},isDirty:false,isSubmitting:false,isValid:true,_repeatableOrder:{},_repeatableNextKey:{}});},_setFieldConditions:(i,o)=>{e(s=>({_fieldConditions:{...s._fieldConditions,[i]:o}}));},_updateIsValid:()=>{let i=t(),o=Object.values(i.errors).some(a=>a&&a.length>0),s=Object.values(i.validationStates).some(a=>a==="invalid");e({isValid:!o&&!s});},_setRepeatableConfig:(i,o)=>{e(s=>({_repeatableConfigs:{...s._repeatableConfigs,[i]:o}}));},_appendRepeatableItem:(i,o)=>{let s=t(),a=s._repeatableConfigs[i];if(!a)return null;let n=s._repeatableOrder[i]??[];if(a.max!==void 0&&n.length>=a.max)return null;let f=s._repeatableNextKey[i]??0,p=`k${f}`,m=o??a.defaultValue??{},c={...s.values};for(let l of a.allFields){let d=V(i,p,l.id);c[d]=m[l.id]??void 0;}return e({values:c,isDirty:true,_repeatableOrder:{...s._repeatableOrder,[i]:[...n,p]},_repeatableNextKey:{...s._repeatableNextKey,[i]:f+1}}),p},_removeRepeatableItem:(i,o)=>{let s=t(),a=s._repeatableConfigs[i];if(!a)return false;let n=s._repeatableOrder[i]??[];if(a.min!==void 0&&n.length<=a.min||!n.includes(o))return false;let f=n.filter(F=>F!==o),p={...s.values},m={...s.errors},c={...s.validationStates},l={...s.touched},d={...s._fieldConditions};for(let F of a.allFields){let g=V(i,o,F.id);delete p[g],delete m[g],delete c[g],delete l[g],delete d[g];}return e({values:p,errors:m,validationStates:c,touched:l,isDirty:true,_fieldConditions:d,_repeatableOrder:{...s._repeatableOrder,[i]:f}}),t()._updateIsValid(),true},_moveRepeatableItem:(i,o,s)=>{let a=t(),n=a._repeatableOrder[i];if(!n||o<0||o>=n.length||s<0||s>=n.length||o===s)return;let f=[...n],[p]=f.splice(o,1);f.splice(s,0,p),e({_repeatableOrder:{...a._repeatableOrder,[i]:f}});},_insertRepeatableItem:(i,o,s)=>{let a=t(),n=a._repeatableConfigs[i];if(!n)return null;let f=a._repeatableOrder[i]??[];if(n.max!==void 0&&f.length>=n.max)return null;let p=a._repeatableNextKey[i]??0,m=`k${p}`,c=s??n.defaultValue??{},l={...a.values};for(let g of n.allFields){let u=V(i,m,g.id);l[u]=c[g.id]??void 0;}let d=[...f],F=Math.max(0,Math.min(o,d.length));return d.splice(F,0,m),e({values:l,isDirty:true,_repeatableOrder:{...a._repeatableOrder,[i]:d},_repeatableNextKey:{...a._repeatableNextKey,[i]:p+1}}),m}})))}var ie=Mt.createContext(null);function S(){let r=Mt.useContext(ie);if(!r)throw new Error("useFormStore must be used within a FormProvider");return r}var De=[];function ce(r){let e=S();return zustand.useStore(e,t=>t.values[r])}function ut(r){let e=S();return zustand.useStore(e,t=>t.errors[r]??De)}function ct(r){let e=S();return zustand.useStore(e,t=>t.touched[r]??false)}function mt(r){let e=S();return zustand.useStore(e,t=>t.validationStates[r]??"idle")}var ft={visible:true,disabled:false,required:false,readonly:false};function U(r){let e=S();return zustand.useStore(e,t=>t._fieldConditions[r]??ft)}function me(r){let e=S(),t=zustand.useStore(e,n=>n.values[r]),i=zustand.useStore(e,n=>n.errors[r]??De),o=zustand.useStore(e,n=>n.validationStates[r]??"idle"),s=zustand.useStore(e,n=>n.touched[r]??false),a=zustand.useStore(e,n=>n._defaultValues[r]);return {value:t,errors:i,validationState:o,touched:s,dirty:t!==a}}function pt(){let r=S();return zustand.useStore(r,e=>e.isSubmitting)}function Ft(){let r=S();return zustand.useStore(r,e=>e.isValid)}function gt(){let r=S();return zustand.useStore(r,e=>e.isDirty)}function bt(){let r=S();return zustand.useStore(r,e=>e.values)}function fe(){let r=S(),e=zustand.useStore(r,o=>o.isSubmitting),t=zustand.useStore(r,o=>o.isValid),i=zustand.useStore(r,o=>o.isDirty);return {isSubmitting:e,isValid:t,isDirty:i}}var Ct=[];function pe(r){let e=S();return zustand.useStore(e,t=>t._repeatableOrder[r]??Ct)}function Fe(r){let e=S();return {setValue:t=>e.getState()._setValue(r,t),setTouched:()=>e.getState()._setTouched(r),setErrors:t=>e.getState()._setErrors(r,t),clearErrors:()=>e.getState()._clearErrors(r),setValidationState:t=>e.getState()._setValidationState(r,t)}}function Rt(){let r=S();return {setValue:(e,t)=>r.getState()._setValue(e,t),setTouched:e=>r.getState()._setTouched(e),setErrors:(e,t)=>r.getState()._setErrors(e,t),setSubmitting:e=>r.getState()._setSubmitting(e),reset:e=>r.getState()._reset(e),setFieldConditions:(e,t)=>r.getState()._setFieldConditions(e,t)}}function H(){return S()}var Ae={visible:true,disabled:false,required:false,readonly:false};function Ke(r){try{return JSON.stringify(r)}catch{return String(Date.now())}}function ne(r,e){if(r)try{return typeof r=="object"&&"build"in r?core.evaluateCondition(r.build(),e):core.evaluateCondition(r,e)}catch(t){console.warn("Error evaluating condition:",t);return}}function be(r,e){if(!r)return Ae;let t=ne(r.visible,e),i=ne(r.disabled,e),o=ne(r.required,e),s=ne(r.readonly,e);return {visible:t??true,disabled:i??false,required:o??false,readonly:s??false}}function pr(r,e={}){let{conditions:t,skip:i=false}=e,o=H(),s=U(r),a=Mt.useRef(null);if(i||!t)return s;let n=o.getState().values,f=Ke(n);if(a.current?.valuesHash===f)return a.current.result;let p=be(t,n);return a.current={result:p,valuesHash:f},p}function Fr(){let r=H(),e=Mt.useRef(new Map),t=Mt.useRef("");return Mt.useMemo(()=>function(o,s){if(!s)return Ae;let a=r.getState().values,n=Ke(a);t.current!==n&&(e.current.clear(),t.current=n);let f=e.current.get(o);if(f)return f.result;let p=be(s,a);return e.current.set(o,{result:p,valuesHash:n}),p},[r])}function gr(r,e){let t=H(),i=U(r),o=Mt.useMemo(()=>()=>{if(!e)return i;let s=t.getState().values;return be(e,s)},[t,e,i]);return {conditions:i,refresh:o}}function Y(r,e,t,i){let o={};return r.visible&&(o.visible=G(r.visible,e,t,i)),r.disabled&&(o.disabled=G(r.disabled,e,t,i)),r.required&&(o.required=G(r.required,e,t,i)),r.readonly&&(o.readonly=G(r.readonly,e,t,i)),o}function G(r,e,t,i){let o=r.field&&i.has(r.field)?`${e}[${t}].${r.field}`:r.field,s=r.conditions?.map(a=>G(a,e,t,i));return {...r,field:o,conditions:s}}function Ie({formConfig:r,formValues:e,repeatableOrder:t}){let i=Mt.useMemo(()=>{let c={};for(let l of r.allFields)l.conditions&&(c[l.id]=l.conditions);if(t&&r.repeatableFields)for(let[l,d]of Object.entries(r.repeatableFields)){let F=t[l]??[];if(F.length===0)continue;let g=new Set(d.allFields.map(u=>u.id));for(let u of F)for(let C of d.allFields){if(!C.conditions)continue;let b=V(l,u,C.id);c[b]=Y(C.conditions,l,u,g);}}return c},[r.allFields,r.repeatableFields,t]),o=Mt.useMemo(()=>Object.keys(i).length>0,[i]),s=Te(o?i:{},o?e:{}),a=Mt.useCallback(c=>s[c],[s]),n=Mt.useCallback(c=>{let l=s[c];return l?l.visible:true},[s]),f=Mt.useCallback(c=>{let l=s[c];return l?l.disabled:false},[s]),p=Mt.useCallback(c=>{let l=s[c];return l?l.required:false},[s]),m=Mt.useCallback(c=>{let l=s[c];return l?l.readonly:false},[s]);return Mt.useMemo(()=>({fieldConditions:s,hasConditionalFields:o,getFieldCondition:a,isFieldVisible:n,isFieldDisabled:f,isFieldRequired:p,isFieldReadonly:m}),[s,o,a,n,f,p,m])}function vt(r){return typeof r=="object"&&r!==null&&"preventDefault"in r}function $e({store:r,onSubmit:e,validateForm:t,defaultSubmitOptions:i}){let o=Mt.useRef(e);o.current=e;let s=Mt.useRef(i);return s.current=i,{submit:Mt.useCallback(async n=>{let f={};vt(n)?n.preventDefault():n&&(f=n);let p={...s.current,...f},m=r.getState();if(m.isSubmitting)return false;m._setSubmitting(true);try{if(p.force){let u=r.getState(),b=Object.keys(u._repeatableConfigs).length>0?re(u.values,u._repeatableConfigs,u._repeatableOrder):u.values;return o.current&&await o.current(b),m._setSubmitting(!1),!0}let c=await t();if(!c.isValid&&!p.skipInvalid)return m._setSubmitting(!1),!1;let l=r.getState(),d=l.values;if(p.skipInvalid&&!c.isValid){let u=new Set(Object.entries(l.errors).filter(([,C])=>C.length>0).map(([C])=>C));d=Object.fromEntries(Object.entries(d).filter(([C])=>!u.has(C)));}let g=Object.keys(l._repeatableConfigs).length>0?re(d,l._repeatableConfigs,l._repeatableOrder):d;return o.current&&await o.current(g),m._setSubmitting(!1),!0}catch(c){return m._setSubmitting(false),console.error("Form submission error:",c),false}},[r,t])}}function se(){return {isValid:true,errors:[]}}function He({formConfig:r,store:e,conditionsHelpers:t}){let i=Mt.useRef(r),o=Mt.useRef(t);i.current=r,o.current=t;let s=Mt.useCallback(async(n,f)=>{let p=i.current.allFields.find(d=>d.id===n);if(!p){let d=L(n);if(d&&i.current.repeatableFields){let F=i.current.repeatableFields[d.repeatableId];if(F){let g=F.allFields.find(u=>u.id===d.fieldId);g&&(p={...g,id:n});}}}let m=e.getState();if(!p)return se();if(!o.current.isFieldVisible(n))return m._setErrors(n,[]),m._setValidationState(n,"valid"),se();if(!p.validation||!core.hasUnifiedValidation(p.validation)){let d=o.current.isFieldRequired(n),F=f!==void 0?f:m.values[n];if(d&&core.isEmptyValue(F)){let g={isValid:false,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"}]};return m._setErrors(n,g.errors),m._setValidationState(n,"invalid"),g}return m._setErrors(n,[]),m._setValidationState(n,"valid"),se()}let c=f!==void 0?f:m.values[n],l=core.createValidationContext({fieldId:n,formId:i.current.id,allFormData:{...m.values,[n]:c}});m._setValidationState(n,"validating");try{let d=await core.validateWithUnifiedConfig(p.validation,c,l);if(o.current.isFieldRequired(n)&&core.isEmptyValue(c)&&!d.errors.some(u=>u.code==="REQUIRED"||u.message.toLowerCase().includes("required"))){let u={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...d.errors]};return m._setErrors(n,u.errors),m._setValidationState(n,"invalid"),u}return m._setErrors(n,d.errors),m._setValidationState(n,d.isValid?"valid":"invalid"),d}catch(d){let F={isValid:false,errors:[{message:d instanceof Error?d.message:"Validation failed",code:"VALIDATION_ERROR"}]};return m._setErrors(n,F.errors),m._setValidationState(n,"invalid"),F}},[e]),a=Mt.useCallback(async()=>{let n=e.getState(),f=i.current.allFields.filter(u=>{if(!o.current.isFieldVisible(u.id))return false;let b=u.validation&&core.hasUnifiedValidation(u.validation),k=o.current.isFieldRequired(u.id);return b||k}),p=i.current.allFields.filter(u=>!o.current.isFieldVisible(u.id));for(let u of p)n._setErrors(u.id,[]),n._setValidationState(u.id,"valid");let m=await Promise.all(f.map(u=>s(u.id))),c=m.some(u=>!u.isValid),l=i.current.repeatableFields??{},d=[];for(let[u,C]of Object.entries(l)){let b=n._repeatableOrder[u]??[];for(let k of b)for(let P of C.allFields){let O=V(u,k,P.id);if(!o.current.isFieldVisible(O)){n._setErrors(O,[]),n._setValidationState(O,"valid");continue}let D=await s(O);d.push(D);}C.min!==void 0&&b.length<C.min&&d.push({isValid:false,errors:[{message:`At least ${C.min} item(s) required`,code:"REPEATABLE_MIN_COUNT",path:u}]});}let F=d.some(u=>!u.isValid);c=c||F;let g=se();if(i.current.validation&&core.hasUnifiedValidation(i.current.validation)){let u=Object.keys(n.values).reduce((b,k)=>(o.current.isFieldVisible(k)&&(b[k]=n.values[k]),b),{}),C=core.createValidationContext({formId:i.current.id,allFormData:u});try{g=await core.validateFormWithUnifiedConfig(i.current.validation,u,C);}catch(b){g={isValid:false,errors:[{message:b instanceof Error?b.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!c&&g.isValid,errors:[...m.flatMap(u=>u.errors),...d.flatMap(u=>u.errors),...g.errors]}},[e,s]);return {validateField:s,validateForm:a}}function ve(r){let e=S(),{formConfig:t}=E(),i=pe(r),o=t.repeatableFields?.[r],s=Mt.useMemo(()=>o?new Set(o.allFields.map(l=>l.id)):new Set,[o]),a=Mt.useMemo(()=>o?i.map((l,d)=>{let F=o.allFields.map(u=>{let C=V(r,l,u.id),b=u.conditions?Y(u.conditions,r,l,s):void 0;return {...u,id:C,conditions:b}}),g=o.rows.map(u=>({...u,fields:u.fields.map(C=>{let b=V(r,l,C.id),k=C.conditions?Y(C.conditions,r,l,s):void 0;return {...C,id:b,conditions:k}})}));return {key:l,index:d,rows:g,allFields:F}}):[],[r,i,o,s]),n=Mt.useMemo(()=>o?o.max===void 0?true:i.length<o.max:false,[o,i.length]),f=Mt.useMemo(()=>{if(!o)return false;let l=o.min??0;return i.length>l},[o,i.length]),p=Mt.useCallback(l=>{e.getState()._appendRepeatableItem(r,l);},[e,r]),m=Mt.useCallback(l=>{e.getState()._removeRepeatableItem(r,l);},[e,r]),c=Mt.useCallback((l,d)=>{e.getState()._moveRepeatableItem(r,l,d);},[e,r]);return {items:a,append:p,remove:m,move:c,canAdd:n,canRemove:f,count:i.length}}function xt({formConfig:r,enabled:e=true}){let t=core.getGlobalMonitor(),i=Mt.useRef(null),o=Mt.useRef(0),s=Mt.useRef(0);Mt.useEffect(()=>{t&&e&&(i.current=t.getProfiler());},[t,e]);let a=Mt.useCallback(l=>{if(!t||!e)return;o.current++;let d={formId:r.id,fieldCount:r.allFields.length,timestamp:Date.now(),duration:0,renderDuration:0,validationDuration:0,validationErrors:0,renderCount:l||o.current};t.track("component_render",`form_${r.id}`,{formId:r.id,fieldCount:r.allFields.length,renderCount:o.current},d,"low");},[t,e,r.id,r.allFields.length]),n=Mt.useCallback((l,d)=>{if(!t||!e)return;let F=i.current?.getMetrics(`form_validation_${r.id}`),g={formId:r.id,fieldCount:d||r.allFields.length,timestamp:Date.now(),duration:F?.duration||0,renderDuration:0,validationDuration:F?.duration||0,validationErrors:l,renderCount:o.current};t.track("form_validation",`form_${r.id}`,{formId:r.id,validationErrors:l,fieldCount:d||r.allFields.length},g,l>0?"medium":"low");},[t,e,r.id,r.allFields.length]),f=Mt.useCallback((l,d)=>{if(!t||!e)return;let F=i.current?.getMetrics(`form_submission_${r.id}`),g={formId:r.id,fieldCount:d||r.allFields.length,timestamp:Date.now(),duration:F?.duration||0,renderDuration:0,validationDuration:0,validationErrors:l?0:1,renderCount:o.current};t.track("form_submission",`form_${r.id}`,{formId:r.id,success:l,fieldCount:d||r.allFields.length,fieldChanges:s.current},g,l?"low":"high");},[t,e,r.id,r.allFields.length]),p=Mt.useCallback((l,d)=>{!t||!e||(s.current++,t.track("component_update",`field_${l}`,{formId:r.id,fieldId:l,componentType:d,changeCount:s.current},void 0,"low"));},[t,e,r.id]),m=Mt.useCallback(l=>{!i.current||!e||i.current.start(l,{formId:r.id,renderCount:o.current});},[e,r.id]),c=Mt.useCallback(l=>{if(!i.current||!e)return null;let d=i.current.end(l);return d?{...d,formId:r.id,fieldCount:r.allFields.length,renderDuration:d.duration,validationDuration:0,validationErrors:0}:null},[e,r.id,r.allFields.length]);return {trackFormRender:a,trackFormValidation:n,trackFormSubmission:f,trackFieldChange:p,startPerformanceTracking:m,endPerformanceTracking:c}}var ze=Mt.createContext(null);function E(){let r=Mt.useContext(ze);if(!r)throw new Error("useFormConfigContext must be used within a FormProvider");return r}function _e({children:r,formConfig:e,defaultValues:t={},onSubmit:i,onFieldChange:o,className:s}){let[a]=Mt.useState(()=>{let x=e.repeatableFields??{},R={...t},h={},y={};if(Object.keys(x).some(v=>Array.isArray(t[v]))){let v=oe(t,x);R=v.values,h=v.order,y=v.nextKeys;}for(let[v,B]of Object.entries(x))if(!h[v]){let Z=B.min??0,K=[],I=y[v]??0;for(let N=0;N<Z;N++){let j=`k${I}`;K.push(j);for(let ee of B.allFields){let rt=V(v,j,ee.id);R[rt]=B.defaultValue?.[ee.id]??void 0;}I++;}h[v]=K,y[v]=I;}let M=ue(R),_=M.getState();for(let[v,B]of Object.entries(x))_._setRepeatableConfig(v,B);return M.setState({_repeatableOrder:h,_repeatableNextKey:y}),M}),n=Mt.useRef(e.id),f=Mt.useRef(o);f.current=o,Mt.useEffect(()=>f.current?a.subscribe(R=>R.values,(R,h)=>{for(let y of Object.keys(R))R[y]!==h[y]&&f.current?.(y,R[y],R);}):void 0,[a]),Mt.useEffect(()=>{if(n.current!==e.id){n.current=e.id;let x=e.repeatableFields??{},R={...t},h={},y={};if(Object.keys(x).some(_=>Array.isArray(t[_]))){let _=oe(t,x);R=_.values,h=_.order,y=_.nextKeys;}for(let[_,v]of Object.entries(x))if(!h[_]){let B=v.min??0,Z=[],K=y[_]??0;for(let I=0;I<B;I++){let N=`k${K}`;Z.push(N);for(let j of v.allFields){let ee=V(_,N,j.id);R[ee]=v.defaultValue?.[j.id]??void 0;}K++;}h[_]=Z,y[_]=K;}a.getState()._reset(R);let M=a.getState();for(let[_,v]of Object.entries(x))M._setRepeatableConfig(_,v);a.setState({_repeatableOrder:h,_repeatableNextKey:y});}},[e.id,e.repeatableFields,a,t]);let[p,m]=Mt.useState(()=>a.getState().values);Mt.useEffect(()=>a.subscribe(R=>R.values,R=>m(R)),[a]);let[c,l]=Mt.useState(()=>a.getState()._repeatableOrder);Mt.useEffect(()=>a.subscribe(R=>R._repeatableOrder,R=>l(R)),[a]);let{fieldConditions:d,hasConditionalFields:F,getFieldCondition:g,isFieldVisible:u,isFieldDisabled:C,isFieldRequired:b,isFieldReadonly:k}=Ie({formConfig:e,formValues:p,repeatableOrder:c});Mt.useEffect(()=>{for(let[x,R]of Object.entries(d)){let h={visible:R.visible,disabled:R.disabled,required:R.required,readonly:R.readonly};a.getState()._setFieldConditions(x,h);}},[d,a]);let P=Mt.useMemo(()=>({hasConditionalFields:F,getFieldCondition:g,isFieldVisible:u,isFieldDisabled:C,isFieldRequired:b,isFieldReadonly:k}),[F,g,u,C,b,k]),{validateField:O,validateForm:D}=He({formConfig:e,store:a,conditionsHelpers:P}),{submit:q}=$e({store:a,onSubmit:i,validateForm:D,defaultSubmitOptions:e.submitOptions}),X=Mt.useMemo(()=>({formConfig:e,conditionsHelpers:P,validateField:O,validateForm:D,submit:q}),[e,P,O,D,q]);return jsxRuntime.jsx(ie.Provider,{value:a,children:jsxRuntime.jsx(ze.Provider,{value:X,children:jsxRuntime.jsx("form",{onSubmit:q,className:s,noValidate:true,children:r})})})}function Ot({formConfig:r,defaultValues:e,onSubmit:t,onFieldChange:i,className:o,children:s}){let a=Mt.useMemo(()=>r instanceof T?r.build():r,[r]);return jsxRuntime.jsx(_e,{formConfig:a,defaultValues:e,onSubmit:t,onFieldChange:i,className:o,children:s})}var Q=Mt__default.default.memo(function({fieldId:e,fieldConfig:t,disabled:i=false,customProps:o={},className:s,forceVisible:a=false}){let{formConfig:n,validateField:f,conditionsHelpers:p}=E(),m=ce(e),c=me(e),l=U(e),{setValue:d,setTouched:F}=Fe(e),g=Mt.useMemo(()=>{if(t)return t;let h=n.allFields.find(A=>A.id===e);if(h)return h;let y=L(e);if(y&&n.repeatableFields){let A=n.repeatableFields[y.repeatableId];if(A){let M=A.allFields.find(_=>_.id===y.fieldId);if(M)return {...M,id:e}}}},[t,n.allFields,n.repeatableFields,e]);if(!g)throw new Error(`Field with ID "${e}" not found`);let u=n.config.getComponent(g.componentId);if(!u)throw new Error(`Component with ID "${g.componentId}" not found`);let C=c.validationState==="validating",b=Mt.useMemo(()=>({isVisible:a||l.visible,isFieldDisabled:i||l.disabled,isFieldRequired:l.required||p.isFieldRequired(e),isFieldReadonly:l.readonly}),[a,i,l,p,e]),k=Mt.useCallback(async h=>{d(h),(g.validation?.validateOnChange||c.touched)&&await f(e,h);},[e,d,f,g.validation?.validateOnChange,c.touched]),P=Mt.useCallback(async()=>{c.touched||F(),g.validation?.validateOnBlur!==false&&await f(e);},[e,c.touched,F,f,g.validation?.validateOnBlur]),O=Mt.useMemo(()=>({...u.defaultProps??{},...g.props,...o,disabled:b.isFieldDisabled,required:b.isFieldRequired,readOnly:b.isFieldReadonly}),[u.defaultProps,g.props,o,b.isFieldDisabled,b.isFieldRequired,b.isFieldReadonly]),D=Mt.useMemo(()=>({id:e,props:O,value:m,onChange:k,onBlur:P,disabled:b.isFieldDisabled,error:c.errors,isValidating:C,touched:c.touched}),[e,O,m,k,P,b.isFieldDisabled,c.errors,C,c.touched]);if(!b.isVisible)return null;let q=u.renderer(D),X=n.renderConfig?.fieldRenderer,x=u.useFieldRenderer!==false,R=X&&x?X({children:q,id:e,...O,error:c.errors,isValidating:C,touched:c.touched}):q;return jsxRuntime.jsx("div",{className:s,"data-field-id":e,"data-field-type":u.type,"data-field-visible":b.isVisible,"data-field-disabled":b.isFieldDisabled,"data-field-required":b.isFieldRequired,"data-field-readonly":b.isFieldReadonly,children:R})});var Xe=Mt__default.default.memo(function({row:e,className:t,...i}){let{formConfig:o,conditionsHelpers:s}=E(),a=Mt.useMemo(()=>e.fields.filter(p=>s.isFieldVisible(p.id)),[e.fields,s]),n=Mt.useMemo(()=>a.map(p=>jsxRuntime.jsx(Q,{fieldId:p.id},p.id)),[a]),f=Mt.useMemo(()=>({row:e,children:n,className:t}),[e,n,t]);return a.length===0?null:jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormRow",renderer:o.renderConfig?.rowRenderer,props:f,...i,children:n})}),de=Xe;var ke=Mt__default.default.memo(function({item:e,index:t,total:i,canRemove:o,canMoveUp:s,canMoveDown:a,onRemove:n,onMoveUp:f,onMoveDown:p}){let{formConfig:m}=E(),c=Mt.useMemo(()=>new Map(e.allFields.map(F=>[F.id,F])),[e.allFields]),l=Mt.useMemo(()=>e.rows.map(F=>jsxRuntime.jsx(de,{row:F,children:F.fields.map(g=>jsxRuntime.jsx(Q,{fieldId:g.id,fieldConfig:c.get(g.id)},g.id))},F.id)),[e.rows,c]),d=m.renderConfig?.repeatableItemRenderer;return d?d({item:e,index:t,total:i,canRemove:o,canMoveUp:s,canMoveDown:a,onRemove:n,onMoveUp:f,onMoveDown:p,children:l}):jsxRuntime.jsx("div",{"data-repeatable-item":e.key,"data-repeatable-index":t,children:l})});var Ee=Mt__default.default.memo(function({repeatableId:e,repeatableConfig:t,className:i}){let{formConfig:o}=E(),{items:s,append:a,remove:n,move:f,canAdd:p,canRemove:m}=ve(e),c=Mt.useMemo(()=>s.map((d,F)=>jsxRuntime.jsx(ke,{item:d,index:F,total:s.length,canRemove:m,canMoveUp:F>0,canMoveDown:F<s.length-1,onRemove:()=>n(d.key),onMoveUp:()=>f(F,F-1),onMoveDown:()=>f(F,F+1)},d.key)),[s,m,n,f]),l=o.renderConfig?.repeatableRenderer;return l?l({repeatableId:e,items:s,canAdd:p,canRemove:m,onAdd:()=>a(),min:t.min,max:t.max,children:c}):jsxRuntime.jsxs("div",{className:i,"data-repeatable-id":e,children:[c,p&&jsxRuntime.jsx("button",{type:"button",onClick:()=>a(),"data-repeatable-add":e,children:"Add"})]})});var Nt=Mt__default.default.memo(function({className:e,...t}){let{formConfig:i}=E(),o=Mt.useMemo(()=>i.rows.map(a=>a.kind==="repeatable"?jsxRuntime.jsx(Ee,{repeatableId:a.repeatable.id,repeatableConfig:a.repeatable},a.id):jsxRuntime.jsx(de,{row:a},a.id)),[i.rows]),s=Mt.useMemo(()=>({formConfig:i,children:o,className:e}),[i,o,e]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormBody",renderer:i.renderConfig?.bodyRenderer,props:s,...t,children:o})});var Ht=Mt__default.default.memo(function({className:e,isSubmitting:t,...i}){let{formConfig:o,submit:s}=E(),{isSubmitting:a}=fe(),n=Mt.useMemo(()=>({isSubmitting:t??a,onSubmit:s,className:e}),[t,a,s,e]);return jsxRuntime.jsx(core.ComponentRendererWrapper,{name:"FormSubmitButton",renderer:o.renderConfig?.submitButtonRenderer,props:n,...i})});exports.Form=Ot;exports.FormBody=Nt;exports.FormBuilder=T;exports.FormField=Q;exports.FormProvider=_e;exports.FormRow=Xe;exports.FormStoreContext=ie;exports.FormSubmitButton=Ht;exports.RepeatableBuilder=W;exports.RepeatableField=Ee;exports.RepeatableItem=ke;exports.createFormStore=ue;exports.flattenRepeatableValues=oe;exports.form=T;exports.structureFormValues=re;exports.useConditionEvaluation=tr;exports.useConditionEvaluator=Fr;exports.useFieldActions=Fe;exports.useFieldConditions=U;exports.useFieldConditionsLazy=pr;exports.useFieldConditionsWithRefresh=gr;exports.useFieldErrors=ut;exports.useFieldState=me;exports.useFieldTouched=ct;exports.useFieldValidationState=mt;exports.useFieldValue=ce;exports.useFormActions=Rt;exports.useFormConditions=Ie;exports.useFormConfigContext=E;exports.useFormDirty=gt;exports.useFormMonitoring=xt;exports.useFormStore=S;exports.useFormStoreApi=H;exports.useFormSubmissionWithStore=$e;exports.useFormSubmitState=fe;exports.useFormSubmitting=pt;exports.useFormValid=Ft;exports.useFormValidationWithStore=He;exports.useFormValues=bt;exports.useMultipleConditionEvaluation=Te;exports.useRepeatableField=ve;exports.useRepeatableKeys=pe;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import Xe,{createContext,useMemo,useCallback,useContext,useRef,useEffect,useState}from'react';import {ComponentRendererWrapper,IdGenerator,deepClone,ensureUnique,hasUnifiedValidation,createValidationContext,validateWithUnifiedConfig,validateFormWithUnifiedConfig,getGlobalMonitor,evaluateCondition}from'@rilaykit/core';import {useStore,createStore}from'zustand';import {subscribeWithSelector}from'zustand/middleware';import {jsx}from'react/jsx-runtime';var x=class o{constructor(e,t){this.rows=[];this.idGenerator=new IdGenerator;this.config=e,this.formId=t||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,t){return new o(e,t)}createFormField(e){let t=this.config.getComponent(e.type);if(!t)throw new Error(`No component found with type "${e.type}"`);let i;return (t.validation||e.validation)&&(i={validateOnChange:e.validation?.validateOnChange??t.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??t.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??t.validation?.debounceMs,validate:(()=>{let r=t.validation?.validate,n=e.validation?.validate;if(!r)return n;if(!n)return r;let a=Array.isArray(r)?r:[r],s=Array.isArray(n)?n:[n];return [...a,...s]})()}),{id:e.id||this.idGenerator.next("field"),componentId:t.id,props:{...t.defaultProps,...e.props},validation:i,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 t=e.map(i=>this.createFormField(i));return {id:this.idGenerator.next("row"),fields:t,maxColumns:e.length}}add(...e){let t,i=false;if(e.length===1&&Array.isArray(e[0])?(t=e[0],i=true):t=e,t.length===0)throw new Error("At least one field is required");if(i&&t.length>3)throw new Error("Maximum 3 fields per row");if(t.length===1){let r=this.createRow(t);return this.rows.push(r),this}if(t.length<=3){let r=this.createRow(t);return this.rows.push(r),this}for(let r of t){let n=this.createRow([r]);this.rows.push(n);}return this}addSeparateRows(e){for(let t of e)this.add(t);return this}setId(e){return this.formId=e,this}updateField(e,t){let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);return Object.assign(i,{...t,props:{...i.props,...t.props}}),this}findField(e){for(let t of this.rows){let i=t.fields.find(r=>r.id===e);if(i)return i}return null}removeField(e){return this.rows=this.rows.map(t=>({...t,fields:t.fields.filter(i=>i.id!==e)})).filter(t=>t.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,t){console.warn("addFieldValidation is deprecated. Use updateField with validation.validate property instead.");let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);let r={...i.validation,...t};return this.updateField(e,{validation:r})}addFieldConditions(e,t){let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);let r={...i.conditions,...t};return this.updateField(e,{conditions:r})}clone(e){let t=new o(this.config,e||`${this.formId}-clone`);return t.rows=deepClone(this.rows),t}validate(){let e=[],t=this.getFields(),i=t.map(r=>r.id);try{ensureUnique(i,"field");}catch(r){e.push(r instanceof Error?r.message:String(r));}for(let r of t)this.config.hasComponent(r.componentId)||e.push(`Component "${r.componentId}" not found for field "${r.id}"`);for(let r of this.rows)r.fields.length>3&&e.push(`Row "${r.id}" has ${r.fields.length} fields, maximum is 3`),r.fields.length===0&&e.push(`Row "${r.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(),t=this.rows.map(i=>i.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:this.rows.length>0?e.length/this.rows.length:0,maxFieldsInRow:t.length>0?Math.max(...t):0,minFieldsInRow:t.length>0?Math.min(...t):0}}};function Ft(o,e={},t={}){return useMemo(()=>{if(!o)return {visible:t.visible??true,disabled:t.disabled??false,required:t.required??false,readonly:t.readonly??false};let i=r=>{try{return r&&typeof r=="object"&&"build"in r?evaluateCondition(r.build(),e):evaluateCondition(r,e)}catch(n){return console.warn("Error evaluating condition:",n),false}};return {visible:o.visible?i(o.visible):t.visible??true,disabled:o.disabled?i(o.disabled):t.disabled??false,required:o.required?i(o.required):t.required??false,readonly:o.readonly?i(o.readonly):t.readonly??false}},[o,e,t])}function oe(o,e={}){return useMemo(()=>{let t={};for(let[i,r]of Object.entries(o))if(t[i]={visible:true,disabled:false,required:false,readonly:false},r){let n=a=>{try{return a&&typeof a=="object"&&"build"in a?evaluateCondition(a.build(),e):evaluateCondition(a,e)}catch(s){return console.warn(`Error evaluating condition for field ${i}:`,s),false}};t[i]={visible:r.visible?n(r.visible):true,disabled:r.disabled?n(r.disabled):false,required:r.required?n(r.required):false,readonly:r.readonly?n(r.readonly):false};}return t},[o,e])}function $(o={}){return createStore()(subscribeWithSelector((e,t)=>({values:{...o},errors:{},validationStates:{},touched:{},isDirty:false,isSubmitting:false,isValid:true,_defaultValues:{...o},_fieldConditions:{},_setValue:(i,r)=>{e(n=>({values:{...n.values,[i]:r},isDirty:true}));},_setTouched:i=>{e(r=>({touched:{...r.touched,[i]:true}}));},_setErrors:(i,r)=>{e(n=>{let a={...n.errors,[i]:r},s=r.length>0?"invalid":"valid";return {errors:a,validationStates:{...n.validationStates,[i]:s}}}),t()._updateIsValid();},_clearErrors:i=>{e(r=>{let n={...r.errors};return delete n[i],{errors:n,validationStates:{...r.validationStates,[i]:"idle"}}}),t()._updateIsValid();},_setValidationState:(i,r)=>{e(n=>({validationStates:{...n.validationStates,[i]:r}}));},_setSubmitting:i=>{e({isSubmitting:i});},_reset:i=>{let r=i??t()._defaultValues;e({values:{...r},errors:{},validationStates:{},touched:{},isDirty:false,isSubmitting:false,isValid:true});},_setFieldConditions:(i,r)=>{e(n=>({_fieldConditions:{...n._fieldConditions,[i]:r}}));},_updateIsValid:()=>{let i=t(),r=Object.values(i.errors).some(a=>a&&a.length>0),n=Object.values(i.validationStates).some(a=>a==="invalid");e({isValid:!r&&!n});}})))}var O=createContext(null);function v(){let o=useContext(O);if(!o)throw new Error("useFormStore must be used within a FormProvider");return o}var re=[];function N(o){let e=v();return useStore(e,t=>t.values[o])}function Me(o){let e=v();return useStore(e,t=>t.errors[o]??re)}function Be(o){let e=v();return useStore(e,t=>t.touched[o]??false)}function Te(o){let e=v();return useStore(e,t=>t.validationStates[o]??"idle")}var De={visible:true,disabled:false,required:false,readonly:false};function P(o){let e=v();return useStore(e,t=>t._fieldConditions[o]??De)}function W(o){let e=v(),t=useStore(e,s=>s.values[o]),i=useStore(e,s=>s.errors[o]??re),r=useStore(e,s=>s.validationStates[o]??"idle"),n=useStore(e,s=>s.touched[o]??false),a=useStore(e,s=>s._defaultValues[o]);return {value:t,errors:i,validationState:r,touched:n,dirty:t!==a}}function qe(){let o=v();return useStore(o,e=>e.isSubmitting)}function Oe(){let o=v();return useStore(o,e=>e.isValid)}function Ue(){let o=v();return useStore(o,e=>e.isDirty)}function Ae(){let o=v();return useStore(o,e=>e.values)}function H(){let o=v(),e=useStore(o,r=>r.isSubmitting),t=useStore(o,r=>r.isValid),i=useStore(o,r=>r.isDirty);return {isSubmitting:e,isValid:t,isDirty:i}}function L(o){let e=v();return {setValue:t=>e.getState()._setValue(o,t),setTouched:()=>e.getState()._setTouched(o),setErrors:t=>e.getState()._setErrors(o,t),clearErrors:()=>e.getState()._clearErrors(o),setValidationState:t=>e.getState()._setValidationState(o,t)}}function Ie(){let o=v();return {setValue:(e,t)=>o.getState()._setValue(e,t),setTouched:e=>o.getState()._setTouched(e),setErrors:(e,t)=>o.getState()._setErrors(e,t),setSubmitting:e=>o.getState()._setSubmitting(e),reset:e=>o.getState()._reset(e),setFieldConditions:(e,t)=>o.getState()._setFieldConditions(e,t)}}function B(){return v()}var se={visible:true,disabled:false,required:false,readonly:false};function ae(o){try{return JSON.stringify(o)}catch{return String(Date.now())}}function U(o,e){if(o)try{return typeof o=="object"&&"build"in o?evaluateCondition(o.build(),e):evaluateCondition(o,e)}catch(t){console.warn("Error evaluating condition:",t);return}}function j(o,e){if(!o)return se;let t=U(o.visible,e),i=U(o.disabled,e),r=U(o.required,e),n=U(o.readonly,e);return {visible:t??true,disabled:i??false,required:r??false,readonly:n??false}}function Vt(o,e={}){let{conditions:t,skip:i=false}=e,r=B(),n=P(o),a=useRef(null);if(i||!t)return n;let s=r.getState().values,F=ae(s);if(a.current?.valuesHash===F)return a.current.result;let m=j(t,s);return a.current={result:m,valuesHash:F},m}function xt(){let o=B(),e=useRef(new Map),t=useRef("");return useMemo(()=>function(r,n){if(!n)return se;let a=o.getState().values,s=ae(a);t.current!==s&&(e.current.clear(),t.current=s);let F=e.current.get(r);if(F)return F.result;let m=j(n,a);return e.current.set(r,{result:m,valuesHash:s}),m},[o])}function Pt(o,e){let t=B(),i=P(o),r=useMemo(()=>()=>{if(!e)return i;let n=t.getState().values;return j(e,n)},[t,e,i]);return {conditions:i,refresh:r}}function de({formConfig:o,formValues:e}){let t=useMemo(()=>{let l={};for(let u of o.allFields)u.conditions&&(l[u.id]=u.conditions);return l},[o.allFields]),i=useMemo(()=>Object.keys(t).length>0,[t]),r=oe(i?t:{},i?e:{}),n=useCallback(l=>r[l],[r]),a=useCallback(l=>{let u=r[l];return u?u.visible:true},[r]),s=useCallback(l=>{let u=r[l];return u?u.disabled:false},[r]),F=useCallback(l=>{let u=r[l];return u?u.required:false},[r]),m=useCallback(l=>{let u=r[l];return u?u.readonly:false},[r]);return useMemo(()=>({fieldConditions:r,hasConditionalFields:i,getFieldCondition:n,isFieldVisible:a,isFieldDisabled:s,isFieldRequired:F,isFieldReadonly:m}),[r,i,n,a,s,F,m])}function le({store:o,onSubmit:e,validateForm:t}){let i=useRef(e);return i.current=e,{submit:useCallback(async n=>{n?.preventDefault();let a=o.getState();if(a.isSubmitting)return false;a._setSubmitting(true);try{if(!(await t()).isValid)return a._setSubmitting(!1),!1;let F=o.getState().values;return i.current&&await i.current(F),a._setSubmitting(!1),!0}catch(s){return a._setSubmitting(false),console.error("Form submission error:",s),false}},[o,t])}}function A(){return {isValid:true,errors:[]}}function fe({formConfig:o,store:e,conditionsHelpers:t}){let i=useRef(o),r=useRef(t);i.current=o,r.current=t;let n=useCallback(async(s,F)=>{let m=i.current.allFields.find(d=>d.id===s),l=e.getState();if(!m)return A();if(!r.current.isFieldVisible(s))return l._setErrors(s,[]),l._setValidationState(s,"valid"),A();if(!m.validation||!hasUnifiedValidation(m.validation))return l._setErrors(s,[]),l._setValidationState(s,"valid"),A();let u=F!==void 0?F:l.values[s],c=createValidationContext({fieldId:s,formId:i.current.id,allFormData:{...l.values,[s]:u}});l._setValidationState(s,"validating");try{let d=await validateWithUnifiedConfig(m.validation,u,c),f=r.current.isFieldRequired(s),p=u==null||u==="";if(f&&p&&!d.errors.some(g=>g.code==="REQUIRED"||g.message.toLowerCase().includes("required"))){let g={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...d.errors]};return l._setErrors(s,g.errors),l._setValidationState(s,"invalid"),g}return l._setErrors(s,d.errors),l._setValidationState(s,d.isValid?"valid":"invalid"),d}catch(d){let f={isValid:false,errors:[{message:d instanceof Error?d.message:"Validation failed",code:"VALIDATION_ERROR"}]};return l._setErrors(s,f.errors),l._setValidationState(s,"invalid"),f}},[e]),a=useCallback(async()=>{let s=e.getState(),F=i.current.allFields.filter(d=>{let f=r.current.isFieldVisible(d.id),p=d.validation&&hasUnifiedValidation(d.validation);return f&&p}),m=i.current.allFields.filter(d=>!r.current.isFieldVisible(d.id));for(let d of m)s._setErrors(d.id,[]),s._setValidationState(d.id,"valid");let l=await Promise.all(F.map(d=>n(d.id))),u=l.some(d=>!d.isValid),c=A();if(i.current.validation&&hasUnifiedValidation(i.current.validation)){let d=Object.keys(s.values).reduce((p,b)=>(r.current.isFieldVisible(b)&&(p[b]=s.values[b]),p),{}),f=createValidationContext({formId:i.current.id,allFormData:d});try{c=await validateFormWithUnifiedConfig(i.current.validation,d,f);}catch(p){c={isValid:false,errors:[{message:p instanceof Error?p.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!u&&c.isValid,errors:[...l.flatMap(d=>d.errors),...c.errors]}},[e,n]);return {validateField:n,validateForm:a}}function je({formConfig:o,enabled:e=true}){let t=getGlobalMonitor(),i=useRef(null),r=useRef(0),n=useRef(0);useEffect(()=>{t&&e&&(i.current=t.getProfiler());},[t,e]);let a=useCallback(c=>{if(!t||!e)return;r.current++;let d={formId:o.id,fieldCount:o.allFields.length,timestamp:Date.now(),duration:0,renderDuration:0,validationDuration:0,validationErrors:0,renderCount:c||r.current};t.track("component_render",`form_${o.id}`,{formId:o.id,fieldCount:o.allFields.length,renderCount:r.current},d,"low");},[t,e,o.id,o.allFields.length]),s=useCallback((c,d)=>{if(!t||!e)return;let f=i.current?.getMetrics(`form_validation_${o.id}`),p={formId:o.id,fieldCount:d||o.allFields.length,timestamp:Date.now(),duration:f?.duration||0,renderDuration:0,validationDuration:f?.duration||0,validationErrors:c,renderCount:r.current};t.track("form_validation",`form_${o.id}`,{formId:o.id,validationErrors:c,fieldCount:d||o.allFields.length},p,c>0?"medium":"low");},[t,e,o.id,o.allFields.length]),F=useCallback((c,d)=>{if(!t||!e)return;let f=i.current?.getMetrics(`form_submission_${o.id}`),p={formId:o.id,fieldCount:d||o.allFields.length,timestamp:Date.now(),duration:f?.duration||0,renderDuration:0,validationDuration:0,validationErrors:c?0:1,renderCount:r.current};t.track("form_submission",`form_${o.id}`,{formId:o.id,success:c,fieldCount:d||o.allFields.length,fieldChanges:n.current},p,c?"low":"high");},[t,e,o.id,o.allFields.length]),m=useCallback((c,d)=>{!t||!e||(n.current++,t.track("component_update",`field_${c}`,{formId:o.id,fieldId:c,componentType:d,changeCount:n.current},void 0,"low"));},[t,e,o.id]),l=useCallback(c=>{!i.current||!e||i.current.start(c,{formId:o.id,renderCount:r.current});},[e,o.id]),u=useCallback(c=>{if(!i.current||!e)return null;let d=i.current.end(c);return d?{...d,formId:o.id,fieldCount:o.allFields.length,renderDuration:d.duration,validationDuration:0,validationErrors:0}:null},[e,o.id,o.allFields.length]);return {trackFormRender:a,trackFormValidation:s,trackFormSubmission:F,trackFieldChange:m,startPerformanceTracking:l,endPerformanceTracking:u}}var Ce=createContext(null);function y(){let o=useContext(Ce);if(!o)throw new Error("useFormConfigContext must be used within a FormProvider");return o}function K({children:o,formConfig:e,defaultValues:t={},onSubmit:i,onFieldChange:r,className:n}){let[a]=useState(()=>$(t)),s=useRef(e.id),F=useRef(r);F.current=r,useEffect(()=>F.current?a.subscribe(C=>C.values,(C,M)=>{for(let R of Object.keys(C))C[R]!==M[R]&&F.current?.(R,C[R],C);}):void 0,[a]),useEffect(()=>{s.current!==e.id&&(s.current=e.id,a.getState()._reset(t));},[e.id,a,t]);let[m,l]=useState(()=>a.getState().values);useEffect(()=>a.subscribe(C=>C.values,C=>l(C)),[a]);let{fieldConditions:u,hasConditionalFields:c,getFieldCondition:d,isFieldVisible:f,isFieldDisabled:p,isFieldRequired:b,isFieldReadonly:g}=de({formConfig:e,formValues:m});useEffect(()=>{for(let[V,C]of Object.entries(u)){let M={visible:C.visible,disabled:C.disabled,required:C.required,readonly:C.readonly};a.getState()._setFieldConditions(V,M);}},[u,a]);let w=useMemo(()=>({hasConditionalFields:c,getFieldCondition:d,isFieldVisible:f,isFieldDisabled:p,isFieldRequired:b,isFieldReadonly:g}),[c,d,f,p,b,g]),{validateField:_,validateForm:S}=fe({formConfig:e,store:a,conditionsHelpers:w}),{submit:k}=le({store:a,onSubmit:i,validateForm:S}),D=useMemo(()=>({formConfig:e,conditionsHelpers:w,validateField:_,validateForm:S,submit:k}),[e,w,_,S,k]);return jsx(O.Provider,{value:a,children:jsx(Ce.Provider,{value:D,children:jsx("form",{onSubmit:k,className:n,noValidate:true,children:o})})})}function Ye({formConfig:o,defaultValues:e,onSubmit:t,onFieldChange:i,children:r}){let n=useMemo(()=>o instanceof x?o.build():o,[o]);return jsx(K,{formConfig:n,defaultValues:e,onSubmit:t,onFieldChange:i,children:r})}var Z=Xe.memo(function({fieldId:e,disabled:t=false,customProps:i={},className:r,forceVisible:n=false}){let{formConfig:a,validateField:s,conditionsHelpers:F}=y(),m=N(e),l=W(e),u=P(e),{setValue:c,setTouched:d}=L(e),f=a.allFields.find(R=>R.id===e);if(!f)throw new Error(`Field with ID "${e}" not found`);let p=a.config.getComponent(f.componentId);if(!p)throw new Error(`Component with ID "${f.componentId}" not found`);let b=l.validationState==="validating",g=useMemo(()=>({isVisible:n||u.visible,isFieldDisabled:t||u.disabled,isFieldRequired:u.required||F.isFieldRequired(e),isFieldReadonly:u.readonly}),[n,t,u,F,e]),w=useCallback(async R=>{c(R),(f.validation?.validateOnChange||l.touched)&&await s(e,R);},[e,c,s,f.validation?.validateOnChange,l.touched]),_=useCallback(async()=>{l.touched||d(),f.validation?.validateOnBlur!==false&&await s(e);},[e,l.touched,d,s,f.validation?.validateOnBlur]),S=useMemo(()=>({...p.defaultProps??{},...f.props,...i,disabled:g.isFieldDisabled,required:g.isFieldRequired,readOnly:g.isFieldReadonly}),[p.defaultProps,f.props,i,g.isFieldDisabled,g.isFieldRequired,g.isFieldReadonly]),k=useMemo(()=>({id:e,props:S,value:m,onChange:w,onBlur:_,disabled:g.isFieldDisabled,error:l.errors,isValidating:b,touched:l.touched}),[e,S,m,w,_,g.isFieldDisabled,l.errors,b,l.touched]);if(!g.isVisible)return null;let D=p.renderer(k),V=a.renderConfig?.fieldRenderer,C=p.useFieldRenderer!==false,M=V&&C?V({children:D,id:e,...S,error:l.errors,isValidating:b,touched:l.touched}):D;return jsx("div",{className:r,"data-field-id":e,"data-field-type":p.type,"data-field-visible":g.isVisible,"data-field-disabled":g.isFieldDisabled,"data-field-required":g.isFieldRequired,"data-field-readonly":g.isFieldReadonly,children:M})});var be=Xe.memo(function({row:e,className:t,...i}){let{formConfig:r,conditionsHelpers:n}=y(),a=useMemo(()=>e.fields.filter(m=>n.isFieldVisible(m.id)),[e.fields,n]),s=useMemo(()=>a.map(m=>jsx(Z,{fieldId:m.id},m.id)),[a]),F=useMemo(()=>({row:e,children:s,className:t}),[e,s,t]);return a.length===0?null:jsx(ComponentRendererWrapper,{name:"FormRow",renderer:r.renderConfig?.rowRenderer,props:F,...i,children:s})}),Re=be;var it=Xe.memo(function({className:e,...t}){let{formConfig:i}=y(),r=useMemo(()=>i.rows.map(a=>jsx(Re,{row:a},a.id)),[i.rows]),n=useMemo(()=>({formConfig:i,children:r,className:e}),[i,r,e]);return jsx(ComponentRendererWrapper,{name:"FormBody",renderer:i.renderConfig?.bodyRenderer,props:n,...t,children:r})});var dt=Xe.memo(function({className:e,isSubmitting:t,...i}){let{formConfig:r,submit:n}=y(),{isSubmitting:a}=H(),s=useMemo(()=>({isSubmitting:t??a,onSubmit:n,className:e}),[t,a,n,e]);return jsx(ComponentRendererWrapper,{name:"FormSubmitButton",renderer:r.renderConfig?.submitButtonRenderer,props:s,...i})});export{Ye as Form,it as FormBody,x as FormBuilder,Z as FormField,K as FormProvider,be as FormRow,O as FormStoreContext,dt as FormSubmitButton,$ as createFormStore,x as form,Ft as useConditionEvaluation,xt as useConditionEvaluator,L as useFieldActions,P as useFieldConditions,Vt as useFieldConditionsLazy,Pt as useFieldConditionsWithRefresh,Me as useFieldErrors,W as useFieldState,Be as useFieldTouched,Te as useFieldValidationState,N as useFieldValue,Ie as useFormActions,de as useFormConditions,y as useFormConfigContext,Ue as useFormDirty,je as useFormMonitoring,v as useFormStore,B as useFormStoreApi,le as useFormSubmissionWithStore,H as useFormSubmitState,qe as useFormSubmitting,Oe as useFormValid,fe as useFormValidationWithStore,Ae as useFormValues,oe as useMultipleConditionEvaluation};
1
+ import Mt,{createContext,useMemo,useCallback,useContext,useRef,useEffect,useState}from'react';import {ComponentRendererWrapper,IdGenerator,deepClone,ensureUnique,hasUnifiedValidation,isEmptyValue,createValidationContext,validateWithUnifiedConfig,validateFormWithUnifiedConfig,getGlobalMonitor,evaluateCondition}from'@rilaykit/core';import {useStore,createStore}from'zustand';import {subscribeWithSelector}from'zustand/middleware';import {jsx,jsxs}from'react/jsx-runtime';var W=class{constructor(e){this.innerForm=new T(e,"__repeatable_template__");}add(...e){return this.innerForm.add(...e),this}addSeparateRows(e){return this.innerForm.addSeparateRows(e),this}min(e){return this._min=e,this}max(e){return this._max=e,this}defaultValue(e){return this._defaultValue=e,this}validation(e){return this._validation=e,this}_build(e){let t=this.innerForm.getRows(),i=this.innerForm.getFields();if(t.length===0)throw new Error(`Repeatable "${e}" must have at least one field`);for(let o of i)if(o.id.includes("[")||o.id.includes("]"))throw new Error(`Repeatable template field ID "${o.id}" cannot contain "[" or "]" (reserved for composite keys)`);if(this._min!==void 0&&this._max!==void 0&&this._min>this._max)throw new Error(`Repeatable "${e}": min (${this._min}) cannot be greater than max (${this._max})`);return {id:e,rows:t.map(o=>({...o,kind:"fields"})),allFields:i,min:this._min,max:this._max,defaultValue:this._defaultValue,validation:this._validation}}_hasRepeatables(){return this.innerForm.getRows().some(e=>"kind"in e&&e.kind==="repeatable")}};var T=class r{constructor(e,t){this.rows=[];this.idGenerator=new IdGenerator;this.config=e,this.formId=t||`form-${Math.random().toString(36).substring(2,15)}`;}static create(e,t){return new r(e,t)}createFormField(e){let t=this.config.getComponent(e.type);if(!t)throw new Error(`No component found with type "${e.type}"`);let i;return (t.validation||e.validation)&&(i={validateOnChange:e.validation?.validateOnChange??t.validation?.validateOnChange,validateOnBlur:e.validation?.validateOnBlur??t.validation?.validateOnBlur,debounceMs:e.validation?.debounceMs??t.validation?.debounceMs,validate:(()=>{let o=t.validation?.validate,s=e.validation?.validate;if(!o)return s;if(!s)return o;let a=Array.isArray(o)?o:[o],n=Array.isArray(s)?s:[s];return [...a,...n]})()}),{id:e.id||this.idGenerator.next("field"),componentId:t.id,props:{...t.defaultProps,...e.props},validation:i,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 t=e.map(i=>this.createFormField(i));return {kind:"fields",id:this.idGenerator.next("row"),fields:t,maxColumns:e.length}}add(...e){let t,i=false;if(e.length===1&&Array.isArray(e[0])?(t=e[0],i=true):t=e,t.length===0)throw new Error("At least one field is required");if(i&&t.length>3)throw new Error("Maximum 3 fields per row");if(t.length===1){let o=this.createRow(t);return this.rows.push(o),this}if(t.length<=3){let o=this.createRow(t);return this.rows.push(o),this}for(let o of t){let s=this.createRow([o]);this.rows.push(s);}return this}addSeparateRows(e){for(let t of e)this.add(t);return this}addRepeatable(e,t){if(e.includes("[")||e.includes("]"))throw new Error(`Repeatable ID "${e}" cannot contain "[" or "]" (reserved for composite keys)`);let i=new W(this.config),o=t(i);if(o._hasRepeatables())throw new Error(`Nested repeatables are not supported (in repeatable "${e}")`);let s=o._build(e),a={kind:"repeatable",id:this.idGenerator.next("repeatable"),repeatable:s};return this.rows.push(a),this}setId(e){return this.formId=e,this}updateField(e,t){let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);return Object.assign(i,{...t,props:{...i.props,...t.props}}),this}findField(e){for(let t of this.rows)if(t.kind==="fields"){let i=t.fields.find(o=>o.id===e);if(i)return i}else {let i=t.repeatable.allFields.find(o=>o.id===e);if(i)return i}return null}removeField(e){return this.rows=this.rows.map(t=>t.kind==="repeatable"?t:{...t,fields:t.fields.filter(i=>i.id!==e)}).filter(t=>t.kind==="repeatable"||t.fields.length>0),this}getField(e){return this.findField(e)||void 0}getFields(){return this.rows.filter(e=>e.kind==="fields").flatMap(e=>e.fields)}getRows(){return [...this.rows]}clear(){return this.rows=[],this.idGenerator.reset(),this}setValidation(e){return this.formValidation=e,this}setSubmitOptions(e){return this._submitOptions=e,this}addFieldValidation(e,t){console.warn("addFieldValidation is deprecated. Use updateField with validation.validate property instead.");let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);let o={...i.validation,...t};return this.updateField(e,{validation:o})}addFieldConditions(e,t){let i=this.findField(e);if(!i)throw new Error(`Field with ID "${e}" not found`);let o={...i.conditions,...t};return this.updateField(e,{conditions:o})}clone(e){let t=new r(this.config,e||`${this.formId}-clone`);return t.rows=deepClone(this.rows),t}validate(){let e=[],t=this.getFields(),i=this.rows.filter(n=>n.kind==="repeatable"),o=i.flatMap(n=>n.repeatable.allFields),s=[...t.map(n=>n.id),...o.map(n=>n.id)];try{ensureUnique(s,"field");}catch(n){e.push(n instanceof Error?n.message:String(n));}let a=i.map(n=>n.repeatable.id);try{ensureUnique(a,"repeatable");}catch(n){e.push(n instanceof Error?n.message:String(n));}for(let n of t)this.config.hasComponent(n.componentId)||e.push(`Component "${n.componentId}" not found for field "${n.id}"`);for(let n of o)this.config.hasComponent(n.componentId)||e.push(`Component "${n.componentId}" not found for repeatable template field "${n.id}"`);for(let n of this.rows)n.kind==="fields"&&(n.fields.length>3&&e.push(`Row "${n.id}" has ${n.fields.length} fields, maximum is 3`),n.fields.length===0&&e.push(`Row "${n.id}" is empty`));for(let n of t)(n.id.includes("[")||n.id.includes("]"))&&e.push(`Field ID "${n.id}" cannot contain "[" or "]" (reserved for repeatable composite keys)`);for(let n of a)(n.includes("[")||n.includes("]"))&&e.push(`Repeatable ID "${n}" cannot contain "[" or "]" (reserved for composite keys)`);return e}build(){let e=this.validate();if(e.length>0)throw new Error(`Form validation failed: ${e.join(", ")}`);let t=this.rows.filter(o=>o.kind==="repeatable"),i=t.length>0?Object.fromEntries(t.map(o=>[o.repeatable.id,o.repeatable])):void 0;return {id:this.formId,rows:[...this.rows],allFields:this.getFields(),repeatableFields:i,config:this.config,renderConfig:this.config.getFormRenderConfig(),validation:this.formValidation,submitOptions:this._submitOptions}}toJSON(){return {id:this.formId,rows:this.rows}}fromJSON(e){return e.id&&(this.formId=e.id),e.rows&&(this.rows=e.rows.map(t=>t.kind?t:{...t,kind:"fields"})),this}getStats(){let e=this.getFields(),t=this.rows.filter(s=>s.kind==="fields"),i=this.rows.filter(s=>s.kind==="repeatable"),o=t.map(s=>s.fields.length);return {totalFields:e.length,totalRows:this.rows.length,averageFieldsPerRow:t.length>0?e.length/t.length:0,maxFieldsInRow:o.length>0?Math.max(...o):0,minFieldsInRow:o.length>0?Math.min(...o):0,totalRepeatables:i.length,totalRepeatableFields:i.reduce((s,a)=>s+a.repeatable.allFields.length,0)}}};function tr(r,e={},t={}){return useMemo(()=>{if(!r)return {visible:t.visible??true,disabled:t.disabled??false,required:t.required??false,readonly:t.readonly??false};let i=o=>{try{return o&&typeof o=="object"&&"build"in o?evaluateCondition(o.build(),e):evaluateCondition(o,e)}catch(s){return console.warn("Error evaluating condition:",s),false}};return {visible:r.visible?i(r.visible):t.visible??true,disabled:r.disabled?i(r.disabled):t.disabled??false,required:r.required?i(r.required):t.required??false,readonly:r.readonly?i(r.readonly):t.readonly??false}},[r,e,t])}function Te(r,e={}){return useMemo(()=>{let t={};for(let[i,o]of Object.entries(r))if(t[i]={visible:true,disabled:false,required:false,readonly:false},o){let s=a=>{try{return a&&typeof a=="object"&&"build"in a?evaluateCondition(a.build(),e):evaluateCondition(a,e)}catch(n){return console.warn(`Error evaluating condition for field ${i}:`,n),false}};t[i]={visible:o.visible?s(o.visible):true,disabled:o.disabled?s(o.disabled):false,required:o.required?s(o.required):false,readonly:o.readonly?s(o.readonly):false};}return t},[r,e])}var nt=/^([^[\]]+)\[([^\]]+)\]\.(.+)$/;function V(r,e,t){return `${r}[${e}].${t}`}function L(r){let e=nt.exec(r);return e?{repeatableId:e[1],itemKey:e[2],fieldId:e[3]}:null}function re(r,e,t){let i={},o=new Set;for(let[s,a]of Object.entries(t)){if(!e[s])continue;let n=e[s],f=[];for(let p of a){let m={};for(let c of n.allFields){let l=V(s,p,c.id);l in r&&(m[c.id]=r[l],o.add(l));}f.push(m);}i[s]=f;}for(let[s,a]of Object.entries(r))!o.has(s)&&!L(s)&&(i[s]=a);return i}function oe(r,e){let t={},i={},o={};for(let[s,a]of Object.entries(r))if(e[s]&&Array.isArray(a)){let n=[],f=0;for(let p of a){let m=`k${f}`;n.push(m);for(let[c,l]of Object.entries(p))t[V(s,m,c)]=l;f++;}i[s]=n,o[s]=f;}else t[s]=a;return {values:t,order:i,nextKeys:o}}function ue(r={}){return createStore()(subscribeWithSelector((e,t)=>({values:{...r},errors:{},validationStates:{},touched:{},isDirty:false,isSubmitting:false,isValid:true,_defaultValues:{...r},_fieldConditions:{},_repeatableConfigs:{},_repeatableOrder:{},_repeatableNextKey:{},_setValue:(i,o)=>{e(s=>({values:{...s.values,[i]:o},isDirty:true}));},_setTouched:i=>{e(o=>({touched:{...o.touched,[i]:true}}));},_setErrors:(i,o)=>{e(s=>{let a={...s.errors,[i]:o},n=o.length>0?"invalid":"valid";return {errors:a,validationStates:{...s.validationStates,[i]:n}}}),t()._updateIsValid();},_clearErrors:i=>{e(o=>{let s={...o.errors};return delete s[i],{errors:s,validationStates:{...o.validationStates,[i]:"idle"}}}),t()._updateIsValid();},_setValidationState:(i,o)=>{e(s=>({validationStates:{...s.validationStates,[i]:o}}));},_setSubmitting:i=>{e({isSubmitting:i});},_reset:i=>{let o=i??t()._defaultValues;e({values:{...o},errors:{},validationStates:{},touched:{},isDirty:false,isSubmitting:false,isValid:true,_repeatableOrder:{},_repeatableNextKey:{}});},_setFieldConditions:(i,o)=>{e(s=>({_fieldConditions:{...s._fieldConditions,[i]:o}}));},_updateIsValid:()=>{let i=t(),o=Object.values(i.errors).some(a=>a&&a.length>0),s=Object.values(i.validationStates).some(a=>a==="invalid");e({isValid:!o&&!s});},_setRepeatableConfig:(i,o)=>{e(s=>({_repeatableConfigs:{...s._repeatableConfigs,[i]:o}}));},_appendRepeatableItem:(i,o)=>{let s=t(),a=s._repeatableConfigs[i];if(!a)return null;let n=s._repeatableOrder[i]??[];if(a.max!==void 0&&n.length>=a.max)return null;let f=s._repeatableNextKey[i]??0,p=`k${f}`,m=o??a.defaultValue??{},c={...s.values};for(let l of a.allFields){let d=V(i,p,l.id);c[d]=m[l.id]??void 0;}return e({values:c,isDirty:true,_repeatableOrder:{...s._repeatableOrder,[i]:[...n,p]},_repeatableNextKey:{...s._repeatableNextKey,[i]:f+1}}),p},_removeRepeatableItem:(i,o)=>{let s=t(),a=s._repeatableConfigs[i];if(!a)return false;let n=s._repeatableOrder[i]??[];if(a.min!==void 0&&n.length<=a.min||!n.includes(o))return false;let f=n.filter(F=>F!==o),p={...s.values},m={...s.errors},c={...s.validationStates},l={...s.touched},d={...s._fieldConditions};for(let F of a.allFields){let g=V(i,o,F.id);delete p[g],delete m[g],delete c[g],delete l[g],delete d[g];}return e({values:p,errors:m,validationStates:c,touched:l,isDirty:true,_fieldConditions:d,_repeatableOrder:{...s._repeatableOrder,[i]:f}}),t()._updateIsValid(),true},_moveRepeatableItem:(i,o,s)=>{let a=t(),n=a._repeatableOrder[i];if(!n||o<0||o>=n.length||s<0||s>=n.length||o===s)return;let f=[...n],[p]=f.splice(o,1);f.splice(s,0,p),e({_repeatableOrder:{...a._repeatableOrder,[i]:f}});},_insertRepeatableItem:(i,o,s)=>{let a=t(),n=a._repeatableConfigs[i];if(!n)return null;let f=a._repeatableOrder[i]??[];if(n.max!==void 0&&f.length>=n.max)return null;let p=a._repeatableNextKey[i]??0,m=`k${p}`,c=s??n.defaultValue??{},l={...a.values};for(let g of n.allFields){let u=V(i,m,g.id);l[u]=c[g.id]??void 0;}let d=[...f],F=Math.max(0,Math.min(o,d.length));return d.splice(F,0,m),e({values:l,isDirty:true,_repeatableOrder:{...a._repeatableOrder,[i]:d},_repeatableNextKey:{...a._repeatableNextKey,[i]:p+1}}),m}})))}var ie=createContext(null);function S(){let r=useContext(ie);if(!r)throw new Error("useFormStore must be used within a FormProvider");return r}var De=[];function ce(r){let e=S();return useStore(e,t=>t.values[r])}function ut(r){let e=S();return useStore(e,t=>t.errors[r]??De)}function ct(r){let e=S();return useStore(e,t=>t.touched[r]??false)}function mt(r){let e=S();return useStore(e,t=>t.validationStates[r]??"idle")}var ft={visible:true,disabled:false,required:false,readonly:false};function U(r){let e=S();return useStore(e,t=>t._fieldConditions[r]??ft)}function me(r){let e=S(),t=useStore(e,n=>n.values[r]),i=useStore(e,n=>n.errors[r]??De),o=useStore(e,n=>n.validationStates[r]??"idle"),s=useStore(e,n=>n.touched[r]??false),a=useStore(e,n=>n._defaultValues[r]);return {value:t,errors:i,validationState:o,touched:s,dirty:t!==a}}function pt(){let r=S();return useStore(r,e=>e.isSubmitting)}function Ft(){let r=S();return useStore(r,e=>e.isValid)}function gt(){let r=S();return useStore(r,e=>e.isDirty)}function bt(){let r=S();return useStore(r,e=>e.values)}function fe(){let r=S(),e=useStore(r,o=>o.isSubmitting),t=useStore(r,o=>o.isValid),i=useStore(r,o=>o.isDirty);return {isSubmitting:e,isValid:t,isDirty:i}}var Ct=[];function pe(r){let e=S();return useStore(e,t=>t._repeatableOrder[r]??Ct)}function Fe(r){let e=S();return {setValue:t=>e.getState()._setValue(r,t),setTouched:()=>e.getState()._setTouched(r),setErrors:t=>e.getState()._setErrors(r,t),clearErrors:()=>e.getState()._clearErrors(r),setValidationState:t=>e.getState()._setValidationState(r,t)}}function Rt(){let r=S();return {setValue:(e,t)=>r.getState()._setValue(e,t),setTouched:e=>r.getState()._setTouched(e),setErrors:(e,t)=>r.getState()._setErrors(e,t),setSubmitting:e=>r.getState()._setSubmitting(e),reset:e=>r.getState()._reset(e),setFieldConditions:(e,t)=>r.getState()._setFieldConditions(e,t)}}function H(){return S()}var Ae={visible:true,disabled:false,required:false,readonly:false};function Ke(r){try{return JSON.stringify(r)}catch{return String(Date.now())}}function ne(r,e){if(r)try{return typeof r=="object"&&"build"in r?evaluateCondition(r.build(),e):evaluateCondition(r,e)}catch(t){console.warn("Error evaluating condition:",t);return}}function be(r,e){if(!r)return Ae;let t=ne(r.visible,e),i=ne(r.disabled,e),o=ne(r.required,e),s=ne(r.readonly,e);return {visible:t??true,disabled:i??false,required:o??false,readonly:s??false}}function pr(r,e={}){let{conditions:t,skip:i=false}=e,o=H(),s=U(r),a=useRef(null);if(i||!t)return s;let n=o.getState().values,f=Ke(n);if(a.current?.valuesHash===f)return a.current.result;let p=be(t,n);return a.current={result:p,valuesHash:f},p}function Fr(){let r=H(),e=useRef(new Map),t=useRef("");return useMemo(()=>function(o,s){if(!s)return Ae;let a=r.getState().values,n=Ke(a);t.current!==n&&(e.current.clear(),t.current=n);let f=e.current.get(o);if(f)return f.result;let p=be(s,a);return e.current.set(o,{result:p,valuesHash:n}),p},[r])}function gr(r,e){let t=H(),i=U(r),o=useMemo(()=>()=>{if(!e)return i;let s=t.getState().values;return be(e,s)},[t,e,i]);return {conditions:i,refresh:o}}function Y(r,e,t,i){let o={};return r.visible&&(o.visible=G(r.visible,e,t,i)),r.disabled&&(o.disabled=G(r.disabled,e,t,i)),r.required&&(o.required=G(r.required,e,t,i)),r.readonly&&(o.readonly=G(r.readonly,e,t,i)),o}function G(r,e,t,i){let o=r.field&&i.has(r.field)?`${e}[${t}].${r.field}`:r.field,s=r.conditions?.map(a=>G(a,e,t,i));return {...r,field:o,conditions:s}}function Ie({formConfig:r,formValues:e,repeatableOrder:t}){let i=useMemo(()=>{let c={};for(let l of r.allFields)l.conditions&&(c[l.id]=l.conditions);if(t&&r.repeatableFields)for(let[l,d]of Object.entries(r.repeatableFields)){let F=t[l]??[];if(F.length===0)continue;let g=new Set(d.allFields.map(u=>u.id));for(let u of F)for(let C of d.allFields){if(!C.conditions)continue;let b=V(l,u,C.id);c[b]=Y(C.conditions,l,u,g);}}return c},[r.allFields,r.repeatableFields,t]),o=useMemo(()=>Object.keys(i).length>0,[i]),s=Te(o?i:{},o?e:{}),a=useCallback(c=>s[c],[s]),n=useCallback(c=>{let l=s[c];return l?l.visible:true},[s]),f=useCallback(c=>{let l=s[c];return l?l.disabled:false},[s]),p=useCallback(c=>{let l=s[c];return l?l.required:false},[s]),m=useCallback(c=>{let l=s[c];return l?l.readonly:false},[s]);return useMemo(()=>({fieldConditions:s,hasConditionalFields:o,getFieldCondition:a,isFieldVisible:n,isFieldDisabled:f,isFieldRequired:p,isFieldReadonly:m}),[s,o,a,n,f,p,m])}function vt(r){return typeof r=="object"&&r!==null&&"preventDefault"in r}function $e({store:r,onSubmit:e,validateForm:t,defaultSubmitOptions:i}){let o=useRef(e);o.current=e;let s=useRef(i);return s.current=i,{submit:useCallback(async n=>{let f={};vt(n)?n.preventDefault():n&&(f=n);let p={...s.current,...f},m=r.getState();if(m.isSubmitting)return false;m._setSubmitting(true);try{if(p.force){let u=r.getState(),b=Object.keys(u._repeatableConfigs).length>0?re(u.values,u._repeatableConfigs,u._repeatableOrder):u.values;return o.current&&await o.current(b),m._setSubmitting(!1),!0}let c=await t();if(!c.isValid&&!p.skipInvalid)return m._setSubmitting(!1),!1;let l=r.getState(),d=l.values;if(p.skipInvalid&&!c.isValid){let u=new Set(Object.entries(l.errors).filter(([,C])=>C.length>0).map(([C])=>C));d=Object.fromEntries(Object.entries(d).filter(([C])=>!u.has(C)));}let g=Object.keys(l._repeatableConfigs).length>0?re(d,l._repeatableConfigs,l._repeatableOrder):d;return o.current&&await o.current(g),m._setSubmitting(!1),!0}catch(c){return m._setSubmitting(false),console.error("Form submission error:",c),false}},[r,t])}}function se(){return {isValid:true,errors:[]}}function He({formConfig:r,store:e,conditionsHelpers:t}){let i=useRef(r),o=useRef(t);i.current=r,o.current=t;let s=useCallback(async(n,f)=>{let p=i.current.allFields.find(d=>d.id===n);if(!p){let d=L(n);if(d&&i.current.repeatableFields){let F=i.current.repeatableFields[d.repeatableId];if(F){let g=F.allFields.find(u=>u.id===d.fieldId);g&&(p={...g,id:n});}}}let m=e.getState();if(!p)return se();if(!o.current.isFieldVisible(n))return m._setErrors(n,[]),m._setValidationState(n,"valid"),se();if(!p.validation||!hasUnifiedValidation(p.validation)){let d=o.current.isFieldRequired(n),F=f!==void 0?f:m.values[n];if(d&&isEmptyValue(F)){let g={isValid:false,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"}]};return m._setErrors(n,g.errors),m._setValidationState(n,"invalid"),g}return m._setErrors(n,[]),m._setValidationState(n,"valid"),se()}let c=f!==void 0?f:m.values[n],l=createValidationContext({fieldId:n,formId:i.current.id,allFormData:{...m.values,[n]:c}});m._setValidationState(n,"validating");try{let d=await validateWithUnifiedConfig(p.validation,c,l);if(o.current.isFieldRequired(n)&&isEmptyValue(c)&&!d.errors.some(u=>u.code==="REQUIRED"||u.message.toLowerCase().includes("required"))){let u={isValid:!1,errors:[{message:"This field is required",code:"CONDITIONAL_REQUIRED"},...d.errors]};return m._setErrors(n,u.errors),m._setValidationState(n,"invalid"),u}return m._setErrors(n,d.errors),m._setValidationState(n,d.isValid?"valid":"invalid"),d}catch(d){let F={isValid:false,errors:[{message:d instanceof Error?d.message:"Validation failed",code:"VALIDATION_ERROR"}]};return m._setErrors(n,F.errors),m._setValidationState(n,"invalid"),F}},[e]),a=useCallback(async()=>{let n=e.getState(),f=i.current.allFields.filter(u=>{if(!o.current.isFieldVisible(u.id))return false;let b=u.validation&&hasUnifiedValidation(u.validation),k=o.current.isFieldRequired(u.id);return b||k}),p=i.current.allFields.filter(u=>!o.current.isFieldVisible(u.id));for(let u of p)n._setErrors(u.id,[]),n._setValidationState(u.id,"valid");let m=await Promise.all(f.map(u=>s(u.id))),c=m.some(u=>!u.isValid),l=i.current.repeatableFields??{},d=[];for(let[u,C]of Object.entries(l)){let b=n._repeatableOrder[u]??[];for(let k of b)for(let P of C.allFields){let O=V(u,k,P.id);if(!o.current.isFieldVisible(O)){n._setErrors(O,[]),n._setValidationState(O,"valid");continue}let D=await s(O);d.push(D);}C.min!==void 0&&b.length<C.min&&d.push({isValid:false,errors:[{message:`At least ${C.min} item(s) required`,code:"REPEATABLE_MIN_COUNT",path:u}]});}let F=d.some(u=>!u.isValid);c=c||F;let g=se();if(i.current.validation&&hasUnifiedValidation(i.current.validation)){let u=Object.keys(n.values).reduce((b,k)=>(o.current.isFieldVisible(k)&&(b[k]=n.values[k]),b),{}),C=createValidationContext({formId:i.current.id,allFormData:u});try{g=await validateFormWithUnifiedConfig(i.current.validation,u,C);}catch(b){g={isValid:false,errors:[{message:b instanceof Error?b.message:"Form validation failed",code:"FORM_VALIDATION_ERROR"}]};}}return {isValid:!c&&g.isValid,errors:[...m.flatMap(u=>u.errors),...d.flatMap(u=>u.errors),...g.errors]}},[e,s]);return {validateField:s,validateForm:a}}function ve(r){let e=S(),{formConfig:t}=E(),i=pe(r),o=t.repeatableFields?.[r],s=useMemo(()=>o?new Set(o.allFields.map(l=>l.id)):new Set,[o]),a=useMemo(()=>o?i.map((l,d)=>{let F=o.allFields.map(u=>{let C=V(r,l,u.id),b=u.conditions?Y(u.conditions,r,l,s):void 0;return {...u,id:C,conditions:b}}),g=o.rows.map(u=>({...u,fields:u.fields.map(C=>{let b=V(r,l,C.id),k=C.conditions?Y(C.conditions,r,l,s):void 0;return {...C,id:b,conditions:k}})}));return {key:l,index:d,rows:g,allFields:F}}):[],[r,i,o,s]),n=useMemo(()=>o?o.max===void 0?true:i.length<o.max:false,[o,i.length]),f=useMemo(()=>{if(!o)return false;let l=o.min??0;return i.length>l},[o,i.length]),p=useCallback(l=>{e.getState()._appendRepeatableItem(r,l);},[e,r]),m=useCallback(l=>{e.getState()._removeRepeatableItem(r,l);},[e,r]),c=useCallback((l,d)=>{e.getState()._moveRepeatableItem(r,l,d);},[e,r]);return {items:a,append:p,remove:m,move:c,canAdd:n,canRemove:f,count:i.length}}function xt({formConfig:r,enabled:e=true}){let t=getGlobalMonitor(),i=useRef(null),o=useRef(0),s=useRef(0);useEffect(()=>{t&&e&&(i.current=t.getProfiler());},[t,e]);let a=useCallback(l=>{if(!t||!e)return;o.current++;let d={formId:r.id,fieldCount:r.allFields.length,timestamp:Date.now(),duration:0,renderDuration:0,validationDuration:0,validationErrors:0,renderCount:l||o.current};t.track("component_render",`form_${r.id}`,{formId:r.id,fieldCount:r.allFields.length,renderCount:o.current},d,"low");},[t,e,r.id,r.allFields.length]),n=useCallback((l,d)=>{if(!t||!e)return;let F=i.current?.getMetrics(`form_validation_${r.id}`),g={formId:r.id,fieldCount:d||r.allFields.length,timestamp:Date.now(),duration:F?.duration||0,renderDuration:0,validationDuration:F?.duration||0,validationErrors:l,renderCount:o.current};t.track("form_validation",`form_${r.id}`,{formId:r.id,validationErrors:l,fieldCount:d||r.allFields.length},g,l>0?"medium":"low");},[t,e,r.id,r.allFields.length]),f=useCallback((l,d)=>{if(!t||!e)return;let F=i.current?.getMetrics(`form_submission_${r.id}`),g={formId:r.id,fieldCount:d||r.allFields.length,timestamp:Date.now(),duration:F?.duration||0,renderDuration:0,validationDuration:0,validationErrors:l?0:1,renderCount:o.current};t.track("form_submission",`form_${r.id}`,{formId:r.id,success:l,fieldCount:d||r.allFields.length,fieldChanges:s.current},g,l?"low":"high");},[t,e,r.id,r.allFields.length]),p=useCallback((l,d)=>{!t||!e||(s.current++,t.track("component_update",`field_${l}`,{formId:r.id,fieldId:l,componentType:d,changeCount:s.current},void 0,"low"));},[t,e,r.id]),m=useCallback(l=>{!i.current||!e||i.current.start(l,{formId:r.id,renderCount:o.current});},[e,r.id]),c=useCallback(l=>{if(!i.current||!e)return null;let d=i.current.end(l);return d?{...d,formId:r.id,fieldCount:r.allFields.length,renderDuration:d.duration,validationDuration:0,validationErrors:0}:null},[e,r.id,r.allFields.length]);return {trackFormRender:a,trackFormValidation:n,trackFormSubmission:f,trackFieldChange:p,startPerformanceTracking:m,endPerformanceTracking:c}}var ze=createContext(null);function E(){let r=useContext(ze);if(!r)throw new Error("useFormConfigContext must be used within a FormProvider");return r}function _e({children:r,formConfig:e,defaultValues:t={},onSubmit:i,onFieldChange:o,className:s}){let[a]=useState(()=>{let x=e.repeatableFields??{},R={...t},h={},y={};if(Object.keys(x).some(v=>Array.isArray(t[v]))){let v=oe(t,x);R=v.values,h=v.order,y=v.nextKeys;}for(let[v,B]of Object.entries(x))if(!h[v]){let Z=B.min??0,K=[],I=y[v]??0;for(let N=0;N<Z;N++){let j=`k${I}`;K.push(j);for(let ee of B.allFields){let rt=V(v,j,ee.id);R[rt]=B.defaultValue?.[ee.id]??void 0;}I++;}h[v]=K,y[v]=I;}let M=ue(R),_=M.getState();for(let[v,B]of Object.entries(x))_._setRepeatableConfig(v,B);return M.setState({_repeatableOrder:h,_repeatableNextKey:y}),M}),n=useRef(e.id),f=useRef(o);f.current=o,useEffect(()=>f.current?a.subscribe(R=>R.values,(R,h)=>{for(let y of Object.keys(R))R[y]!==h[y]&&f.current?.(y,R[y],R);}):void 0,[a]),useEffect(()=>{if(n.current!==e.id){n.current=e.id;let x=e.repeatableFields??{},R={...t},h={},y={};if(Object.keys(x).some(_=>Array.isArray(t[_]))){let _=oe(t,x);R=_.values,h=_.order,y=_.nextKeys;}for(let[_,v]of Object.entries(x))if(!h[_]){let B=v.min??0,Z=[],K=y[_]??0;for(let I=0;I<B;I++){let N=`k${K}`;Z.push(N);for(let j of v.allFields){let ee=V(_,N,j.id);R[ee]=v.defaultValue?.[j.id]??void 0;}K++;}h[_]=Z,y[_]=K;}a.getState()._reset(R);let M=a.getState();for(let[_,v]of Object.entries(x))M._setRepeatableConfig(_,v);a.setState({_repeatableOrder:h,_repeatableNextKey:y});}},[e.id,e.repeatableFields,a,t]);let[p,m]=useState(()=>a.getState().values);useEffect(()=>a.subscribe(R=>R.values,R=>m(R)),[a]);let[c,l]=useState(()=>a.getState()._repeatableOrder);useEffect(()=>a.subscribe(R=>R._repeatableOrder,R=>l(R)),[a]);let{fieldConditions:d,hasConditionalFields:F,getFieldCondition:g,isFieldVisible:u,isFieldDisabled:C,isFieldRequired:b,isFieldReadonly:k}=Ie({formConfig:e,formValues:p,repeatableOrder:c});useEffect(()=>{for(let[x,R]of Object.entries(d)){let h={visible:R.visible,disabled:R.disabled,required:R.required,readonly:R.readonly};a.getState()._setFieldConditions(x,h);}},[d,a]);let P=useMemo(()=>({hasConditionalFields:F,getFieldCondition:g,isFieldVisible:u,isFieldDisabled:C,isFieldRequired:b,isFieldReadonly:k}),[F,g,u,C,b,k]),{validateField:O,validateForm:D}=He({formConfig:e,store:a,conditionsHelpers:P}),{submit:q}=$e({store:a,onSubmit:i,validateForm:D,defaultSubmitOptions:e.submitOptions}),X=useMemo(()=>({formConfig:e,conditionsHelpers:P,validateField:O,validateForm:D,submit:q}),[e,P,O,D,q]);return jsx(ie.Provider,{value:a,children:jsx(ze.Provider,{value:X,children:jsx("form",{onSubmit:q,className:s,noValidate:true,children:r})})})}function Ot({formConfig:r,defaultValues:e,onSubmit:t,onFieldChange:i,className:o,children:s}){let a=useMemo(()=>r instanceof T?r.build():r,[r]);return jsx(_e,{formConfig:a,defaultValues:e,onSubmit:t,onFieldChange:i,className:o,children:s})}var Q=Mt.memo(function({fieldId:e,fieldConfig:t,disabled:i=false,customProps:o={},className:s,forceVisible:a=false}){let{formConfig:n,validateField:f,conditionsHelpers:p}=E(),m=ce(e),c=me(e),l=U(e),{setValue:d,setTouched:F}=Fe(e),g=useMemo(()=>{if(t)return t;let h=n.allFields.find(A=>A.id===e);if(h)return h;let y=L(e);if(y&&n.repeatableFields){let A=n.repeatableFields[y.repeatableId];if(A){let M=A.allFields.find(_=>_.id===y.fieldId);if(M)return {...M,id:e}}}},[t,n.allFields,n.repeatableFields,e]);if(!g)throw new Error(`Field with ID "${e}" not found`);let u=n.config.getComponent(g.componentId);if(!u)throw new Error(`Component with ID "${g.componentId}" not found`);let C=c.validationState==="validating",b=useMemo(()=>({isVisible:a||l.visible,isFieldDisabled:i||l.disabled,isFieldRequired:l.required||p.isFieldRequired(e),isFieldReadonly:l.readonly}),[a,i,l,p,e]),k=useCallback(async h=>{d(h),(g.validation?.validateOnChange||c.touched)&&await f(e,h);},[e,d,f,g.validation?.validateOnChange,c.touched]),P=useCallback(async()=>{c.touched||F(),g.validation?.validateOnBlur!==false&&await f(e);},[e,c.touched,F,f,g.validation?.validateOnBlur]),O=useMemo(()=>({...u.defaultProps??{},...g.props,...o,disabled:b.isFieldDisabled,required:b.isFieldRequired,readOnly:b.isFieldReadonly}),[u.defaultProps,g.props,o,b.isFieldDisabled,b.isFieldRequired,b.isFieldReadonly]),D=useMemo(()=>({id:e,props:O,value:m,onChange:k,onBlur:P,disabled:b.isFieldDisabled,error:c.errors,isValidating:C,touched:c.touched}),[e,O,m,k,P,b.isFieldDisabled,c.errors,C,c.touched]);if(!b.isVisible)return null;let q=u.renderer(D),X=n.renderConfig?.fieldRenderer,x=u.useFieldRenderer!==false,R=X&&x?X({children:q,id:e,...O,error:c.errors,isValidating:C,touched:c.touched}):q;return jsx("div",{className:s,"data-field-id":e,"data-field-type":u.type,"data-field-visible":b.isVisible,"data-field-disabled":b.isFieldDisabled,"data-field-required":b.isFieldRequired,"data-field-readonly":b.isFieldReadonly,children:R})});var Xe=Mt.memo(function({row:e,className:t,...i}){let{formConfig:o,conditionsHelpers:s}=E(),a=useMemo(()=>e.fields.filter(p=>s.isFieldVisible(p.id)),[e.fields,s]),n=useMemo(()=>a.map(p=>jsx(Q,{fieldId:p.id},p.id)),[a]),f=useMemo(()=>({row:e,children:n,className:t}),[e,n,t]);return a.length===0?null:jsx(ComponentRendererWrapper,{name:"FormRow",renderer:o.renderConfig?.rowRenderer,props:f,...i,children:n})}),de=Xe;var ke=Mt.memo(function({item:e,index:t,total:i,canRemove:o,canMoveUp:s,canMoveDown:a,onRemove:n,onMoveUp:f,onMoveDown:p}){let{formConfig:m}=E(),c=useMemo(()=>new Map(e.allFields.map(F=>[F.id,F])),[e.allFields]),l=useMemo(()=>e.rows.map(F=>jsx(de,{row:F,children:F.fields.map(g=>jsx(Q,{fieldId:g.id,fieldConfig:c.get(g.id)},g.id))},F.id)),[e.rows,c]),d=m.renderConfig?.repeatableItemRenderer;return d?d({item:e,index:t,total:i,canRemove:o,canMoveUp:s,canMoveDown:a,onRemove:n,onMoveUp:f,onMoveDown:p,children:l}):jsx("div",{"data-repeatable-item":e.key,"data-repeatable-index":t,children:l})});var Ee=Mt.memo(function({repeatableId:e,repeatableConfig:t,className:i}){let{formConfig:o}=E(),{items:s,append:a,remove:n,move:f,canAdd:p,canRemove:m}=ve(e),c=useMemo(()=>s.map((d,F)=>jsx(ke,{item:d,index:F,total:s.length,canRemove:m,canMoveUp:F>0,canMoveDown:F<s.length-1,onRemove:()=>n(d.key),onMoveUp:()=>f(F,F-1),onMoveDown:()=>f(F,F+1)},d.key)),[s,m,n,f]),l=o.renderConfig?.repeatableRenderer;return l?l({repeatableId:e,items:s,canAdd:p,canRemove:m,onAdd:()=>a(),min:t.min,max:t.max,children:c}):jsxs("div",{className:i,"data-repeatable-id":e,children:[c,p&&jsx("button",{type:"button",onClick:()=>a(),"data-repeatable-add":e,children:"Add"})]})});var Nt=Mt.memo(function({className:e,...t}){let{formConfig:i}=E(),o=useMemo(()=>i.rows.map(a=>a.kind==="repeatable"?jsx(Ee,{repeatableId:a.repeatable.id,repeatableConfig:a.repeatable},a.id):jsx(de,{row:a},a.id)),[i.rows]),s=useMemo(()=>({formConfig:i,children:o,className:e}),[i,o,e]);return jsx(ComponentRendererWrapper,{name:"FormBody",renderer:i.renderConfig?.bodyRenderer,props:s,...t,children:o})});var Ht=Mt.memo(function({className:e,isSubmitting:t,...i}){let{formConfig:o,submit:s}=E(),{isSubmitting:a}=fe(),n=useMemo(()=>({isSubmitting:t??a,onSubmit:s,className:e}),[t,a,s,e]);return jsx(ComponentRendererWrapper,{name:"FormSubmitButton",renderer:o.renderConfig?.submitButtonRenderer,props:n,...i})});export{Ot as Form,Nt as FormBody,T as FormBuilder,Q as FormField,_e as FormProvider,Xe as FormRow,ie as FormStoreContext,Ht as FormSubmitButton,W as RepeatableBuilder,Ee as RepeatableField,ke as RepeatableItem,ue as createFormStore,oe as flattenRepeatableValues,T as form,re as structureFormValues,tr as useConditionEvaluation,Fr as useConditionEvaluator,Fe as useFieldActions,U as useFieldConditions,pr as useFieldConditionsLazy,gr as useFieldConditionsWithRefresh,ut as useFieldErrors,me as useFieldState,ct as useFieldTouched,mt as useFieldValidationState,ce as useFieldValue,Rt as useFormActions,Ie as useFormConditions,E as useFormConfigContext,gt as useFormDirty,xt as useFormMonitoring,S as useFormStore,H as useFormStoreApi,$e as useFormSubmissionWithStore,fe as useFormSubmitState,pt as useFormSubmitting,Ft as useFormValid,He as useFormValidationWithStore,bt as useFormValues,Te as useMultipleConditionEvaluation,ve as useRepeatableField,pe as useRepeatableKeys};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rilaykit/forms",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "description": "Form building utilities and components for RilayKit",
6
6
  "main": "dist/index.js",
@@ -16,6 +16,9 @@
16
16
  "files": [
17
17
  "dist"
18
18
  ],
19
+ "publishConfig": {
20
+ "provenance": true
21
+ },
19
22
  "keywords": [
20
23
  "react",
21
24
  "forms",
@@ -24,17 +27,17 @@
24
27
  ],
25
28
  "author": "AND YOU CREATE <contact@andyoucreate.com>",
26
29
  "license": "MIT",
27
- "homepage": "https://rilay.io",
30
+ "homepage": "https://rilay.dev",
28
31
  "repository": {
29
32
  "type": "git",
30
- "url": "https://github.com/andyoucreate/rilay.git"
33
+ "url": "https://github.com/andyoucreate/rilaykit.git"
31
34
  },
32
35
  "bugs": {
33
- "url": "https://github.com/andyoucreate/rilay/issues"
36
+ "url": "https://github.com/andyoucreate/rilaykit/issues"
34
37
  },
35
38
  "dependencies": {
36
39
  "zustand": "^5.0.5",
37
- "@rilaykit/core": "0.1.1"
40
+ "@rilaykit/core": "0.1.3"
38
41
  },
39
42
  "peerDependencies": {
40
43
  "react": ">=18.0.0",
@@ -44,10 +47,10 @@
44
47
  "@testing-library/jest-dom": "^6.6.3",
45
48
  "@testing-library/react": "^16.3.0",
46
49
  "@testing-library/user-event": "^14.6.1",
47
- "@types/react": "^18.3.23",
48
- "@types/react-dom": "^18.3.0",
49
- "react": "^18.3.1",
50
- "react-dom": "^18.3.1",
50
+ "@types/react": "^19.0.0",
51
+ "@types/react-dom": "^19.0.0",
52
+ "react": "^19.0.0",
53
+ "react-dom": "^19.0.0",
51
54
  "typescript": "^5.8.3",
52
55
  "vitest": "^3.2.4"
53
56
  },