@lucas-barake/effect-form 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/Form/package.json +6 -0
  2. package/FormAtoms/package.json +6 -0
  3. package/LICENSE +21 -0
  4. package/Mode/package.json +6 -0
  5. package/README.md +5 -0
  6. package/Validation/package.json +6 -0
  7. package/dist/cjs/Form.js +299 -0
  8. package/dist/cjs/Form.js.map +1 -0
  9. package/dist/cjs/FormAtoms.js +266 -0
  10. package/dist/cjs/FormAtoms.js.map +1 -0
  11. package/dist/cjs/Mode.js +64 -0
  12. package/dist/cjs/Mode.js.map +1 -0
  13. package/dist/cjs/Validation.js +69 -0
  14. package/dist/cjs/Validation.js.map +1 -0
  15. package/dist/cjs/index.js +35 -0
  16. package/dist/cjs/index.js.map +1 -0
  17. package/dist/cjs/internal/dirty.js +101 -0
  18. package/dist/cjs/internal/dirty.js.map +1 -0
  19. package/dist/cjs/internal/path.js +96 -0
  20. package/dist/cjs/internal/path.js.map +1 -0
  21. package/dist/cjs/internal/weak-registry.js +52 -0
  22. package/dist/cjs/internal/weak-registry.js.map +1 -0
  23. package/dist/dts/Form.d.ts +317 -0
  24. package/dist/dts/Form.d.ts.map +1 -0
  25. package/dist/dts/FormAtoms.d.ts +145 -0
  26. package/dist/dts/FormAtoms.d.ts.map +1 -0
  27. package/dist/dts/Mode.d.ts +55 -0
  28. package/dist/dts/Mode.d.ts.map +1 -0
  29. package/dist/dts/Validation.d.ts +23 -0
  30. package/dist/dts/Validation.d.ts.map +1 -0
  31. package/dist/dts/index.d.ts +26 -0
  32. package/dist/dts/index.d.ts.map +1 -0
  33. package/dist/dts/internal/dirty.d.ts +13 -0
  34. package/dist/dts/internal/dirty.d.ts.map +1 -0
  35. package/dist/dts/internal/path.d.ts +32 -0
  36. package/dist/dts/internal/path.d.ts.map +1 -0
  37. package/dist/dts/internal/weak-registry.d.ts +7 -0
  38. package/dist/dts/internal/weak-registry.d.ts.map +1 -0
  39. package/dist/esm/Form.js +263 -0
  40. package/dist/esm/Form.js.map +1 -0
  41. package/dist/esm/FormAtoms.js +238 -0
  42. package/dist/esm/FormAtoms.js.map +1 -0
  43. package/dist/esm/Mode.js +36 -0
  44. package/dist/esm/Mode.js.map +1 -0
  45. package/dist/esm/Validation.js +40 -0
  46. package/dist/esm/Validation.js.map +1 -0
  47. package/dist/esm/index.js +26 -0
  48. package/dist/esm/index.js.map +1 -0
  49. package/dist/esm/internal/dirty.js +72 -0
  50. package/dist/esm/internal/dirty.js.map +1 -0
  51. package/dist/esm/internal/path.js +86 -0
  52. package/dist/esm/internal/path.js.map +1 -0
  53. package/dist/esm/internal/weak-registry.js +45 -0
  54. package/dist/esm/internal/weak-registry.js.map +1 -0
  55. package/dist/esm/package.json +4 -0
  56. package/package.json +64 -0
  57. package/src/Form.ts +522 -0
  58. package/src/FormAtoms.ts +485 -0
  59. package/src/Mode.ts +59 -0
  60. package/src/Validation.ts +43 -0
  61. package/src/index.ts +28 -0
  62. package/src/internal/dirty.ts +96 -0
  63. package/src/internal/path.ts +93 -0
  64. package/src/internal/weak-registry.ts +60 -0
@@ -0,0 +1,317 @@
1
+ /**
2
+ * @since 1.0.0
3
+ */
4
+ import type * as Effect from "effect/Effect";
5
+ import * as Schema from "effect/Schema";
6
+ /**
7
+ * Unique identifier for FormBuilder instances.
8
+ *
9
+ * @since 1.0.0
10
+ * @category Symbols
11
+ */
12
+ export declare const TypeId: unique symbol;
13
+ /**
14
+ * @since 1.0.0
15
+ * @category Symbols
16
+ */
17
+ export type TypeId = typeof TypeId;
18
+ /**
19
+ * A field reference carrying type and path info for type-safe setValue operations.
20
+ *
21
+ * @since 1.0.0
22
+ * @category Models
23
+ */
24
+ export interface Field<S> {
25
+ readonly [FieldTypeId]: FieldTypeId;
26
+ readonly _S: S;
27
+ readonly key: string;
28
+ }
29
+ /**
30
+ * A scalar field definition containing the key and schema.
31
+ *
32
+ * @since 1.0.0
33
+ * @category Models
34
+ */
35
+ export interface FieldDef<K extends string, S extends Schema.Schema.Any> {
36
+ readonly _tag: "field";
37
+ readonly key: K;
38
+ readonly schema: S;
39
+ }
40
+ /**
41
+ * An array field definition containing a schema for items.
42
+ *
43
+ * @since 1.0.0
44
+ * @category Models
45
+ */
46
+ export interface ArrayFieldDef<K extends string, S extends Schema.Schema.Any> {
47
+ readonly _tag: "array";
48
+ readonly key: K;
49
+ readonly itemSchema: S;
50
+ }
51
+ /**
52
+ * Union of all field definition types.
53
+ *
54
+ * @since 1.0.0
55
+ * @category Models
56
+ */
57
+ export type AnyFieldDef = FieldDef<string, Schema.Schema.Any> | ArrayFieldDef<string, Schema.Schema.Any>;
58
+ /**
59
+ * Creates a scalar field definition.
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * const NameField = Form.makeField("name", Schema.String)
64
+ * const form = Form.empty.addField(NameField)
65
+ * ```
66
+ *
67
+ * @since 1.0.0
68
+ * @category Constructors
69
+ */
70
+ export declare const makeField: <K extends string, S extends Schema.Schema.Any>(key: K, schema: S) => FieldDef<K, S>;
71
+ /**
72
+ * Creates an array field definition.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * // Array of primitives
77
+ * const TagsField = Form.makeArrayField("tags", Schema.String)
78
+ *
79
+ * // Array of objects
80
+ * const ItemsField = Form.makeArrayField("items", Schema.Struct({
81
+ * name: Schema.String,
82
+ * quantity: Schema.Number
83
+ * }))
84
+ * ```
85
+ *
86
+ * @since 1.0.0
87
+ * @category Constructors
88
+ */
89
+ export declare const makeArrayField: <K extends string, S extends Schema.Schema.Any>(key: K, itemSchema: S) => ArrayFieldDef<K, S>;
90
+ /**
91
+ * A record of field definitions.
92
+ *
93
+ * @since 1.0.0
94
+ * @category Models
95
+ */
96
+ export type FieldsRecord = Record<string, AnyFieldDef>;
97
+ /**
98
+ * Extracts the encoded (input) type from a fields record.
99
+ *
100
+ * @since 1.0.0
101
+ * @category Type Helpers
102
+ */
103
+ export type EncodedFromFields<T extends FieldsRecord> = {
104
+ readonly [K in keyof T]: T[K] extends FieldDef<any, infer S> ? Schema.Schema.Encoded<S> : T[K] extends ArrayFieldDef<any, infer S> ? ReadonlyArray<Schema.Schema.Encoded<S>> : never;
105
+ };
106
+ /**
107
+ * Extracts the decoded (output) type from a fields record.
108
+ *
109
+ * @since 1.0.0
110
+ * @category Type Helpers
111
+ */
112
+ export type DecodedFromFields<T extends FieldsRecord> = {
113
+ readonly [K in keyof T]: T[K] extends FieldDef<any, infer S> ? Schema.Schema.Type<S> : T[K] extends ArrayFieldDef<any, infer S> ? ReadonlyArray<Schema.Schema.Type<S>> : never;
114
+ };
115
+ /**
116
+ * The state of a form at runtime.
117
+ *
118
+ * @since 1.0.0
119
+ * @category Models
120
+ */
121
+ export interface FormState<TFields extends FieldsRecord> {
122
+ readonly values: EncodedFromFields<TFields>;
123
+ readonly initialValues: EncodedFromFields<TFields>;
124
+ readonly touched: {
125
+ readonly [K in keyof TFields]: boolean;
126
+ };
127
+ readonly submitCount: number;
128
+ readonly dirtyFields: ReadonlySet<string>;
129
+ }
130
+ interface SyncRefinement {
131
+ readonly _tag: "sync";
132
+ readonly fn: (values: unknown) => Schema.FilterOutput;
133
+ }
134
+ interface AsyncRefinement {
135
+ readonly _tag: "async";
136
+ readonly fn: (values: unknown) => Effect.Effect<Schema.FilterOutput, never, unknown>;
137
+ }
138
+ type Refinement = SyncRefinement | AsyncRefinement;
139
+ /**
140
+ * A builder for constructing type-safe forms with Effect Schema validation.
141
+ *
142
+ * **Details**
143
+ *
144
+ * FormBuilder uses a fluent API pattern to define form fields. Each field
145
+ * includes a Schema for validation. The builder accumulates field definitions
146
+ * and context requirements (`R`) from schemas that use Effect services.
147
+ *
148
+ * @since 1.0.0
149
+ * @category Models
150
+ */
151
+ export interface FormBuilder<TFields extends FieldsRecord, R> {
152
+ readonly [TypeId]: TypeId;
153
+ readonly fields: TFields;
154
+ readonly refinements: ReadonlyArray<Refinement>;
155
+ readonly _R?: R;
156
+ /**
157
+ * Adds a scalar field to the form builder.
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * const NameField = Form.makeField("name", Schema.String)
162
+ * const form = Form.empty.addField(NameField)
163
+ * ```
164
+ */
165
+ addField<K extends string, S extends Schema.Schema.Any>(this: FormBuilder<TFields, R>, field: FieldDef<K, S>): FormBuilder<TFields & {
166
+ readonly [key in K]: FieldDef<K, S>;
167
+ }, R | Schema.Schema.Context<S>>;
168
+ /**
169
+ * Adds an array field to the form builder.
170
+ *
171
+ * @example
172
+ * ```ts
173
+ * const ItemsField = Form.makeArrayField("items", Schema.Struct({ name: Schema.String }))
174
+ * const form = Form.empty.addField(ItemsField)
175
+ * ```
176
+ */
177
+ addField<K extends string, S extends Schema.Schema.Any>(this: FormBuilder<TFields, R>, field: ArrayFieldDef<K, S>): FormBuilder<TFields & {
178
+ readonly [key in K]: ArrayFieldDef<K, S>;
179
+ }, R | Schema.Schema.Context<S>>;
180
+ /**
181
+ * Merges another FormBuilder's fields into this one.
182
+ * Useful for composing reusable field groups.
183
+ *
184
+ * @example
185
+ * ```ts
186
+ * const addressFields = Form.empty
187
+ * .addField("street", Schema.String)
188
+ * .addField("city", Schema.String)
189
+ *
190
+ * const userForm = Form.empty
191
+ * .addField("name", Schema.String)
192
+ * .merge(addressFields)
193
+ * ```
194
+ */
195
+ merge<TFields2 extends FieldsRecord, R2>(this: FormBuilder<TFields, R>, other: FormBuilder<TFields2, R2>): FormBuilder<TFields & TFields2, R | R2>;
196
+ /**
197
+ * Adds a synchronous cross-field validation refinement to the form.
198
+ *
199
+ * @example
200
+ * ```ts
201
+ * const form = Form.empty
202
+ * .addField("password", Schema.String)
203
+ * .addField("confirmPassword", Schema.String)
204
+ * .refine((values) => {
205
+ * if (values.password !== values.confirmPassword) {
206
+ * return { path: ["confirmPassword"], message: "Passwords must match" }
207
+ * }
208
+ * })
209
+ * ```
210
+ */
211
+ refine(this: FormBuilder<TFields, R>, predicate: (values: DecodedFromFields<TFields>) => Schema.FilterOutput): FormBuilder<TFields, R>;
212
+ /**
213
+ * Adds an asynchronous cross-field validation refinement to the form.
214
+ *
215
+ * @example
216
+ * ```ts
217
+ * const form = Form.empty
218
+ * .addField("username", Schema.String)
219
+ * .refineEffect((values) =>
220
+ * Effect.gen(function* () {
221
+ * const taken = yield* checkUsername(values.username)
222
+ * if (taken) return { path: ["username"], message: "Already taken" }
223
+ * })
224
+ * )
225
+ * ```
226
+ */
227
+ refineEffect<RD>(this: FormBuilder<TFields, R>, predicate: (values: DecodedFromFields<TFields>) => Effect.Effect<Schema.FilterOutput, never, RD>): FormBuilder<TFields, R | RD>;
228
+ }
229
+ /**
230
+ * Checks if a value is a `FormBuilder`.
231
+ *
232
+ * @example
233
+ * ```ts
234
+ * import * as Form from "@lucas-barake/effect-form"
235
+ *
236
+ * const builder = Form.empty
237
+ *
238
+ * console.log(Form.isFormBuilder(builder))
239
+ * // Output: true
240
+ *
241
+ * console.log(Form.isFormBuilder({}))
242
+ * // Output: false
243
+ * ```
244
+ *
245
+ * @since 1.0.0
246
+ * @category Guards
247
+ */
248
+ export declare const isFormBuilder: (u: unknown) => u is FormBuilder<any, any>;
249
+ /**
250
+ * Checks if a field definition is an array field.
251
+ *
252
+ * @since 1.0.0
253
+ * @category Guards
254
+ */
255
+ export declare const isArrayFieldDef: (def: AnyFieldDef) => def is ArrayFieldDef<string, any>;
256
+ /**
257
+ * Checks if a field definition is a simple field.
258
+ *
259
+ * @since 1.0.0
260
+ * @category Guards
261
+ */
262
+ export declare const isFieldDef: (def: AnyFieldDef) => def is FieldDef<string, Schema.Schema.Any>;
263
+ /**
264
+ * Gets a default encoded value from a schema.
265
+ *
266
+ * @since 1.0.0
267
+ * @category Helpers
268
+ */
269
+ export declare const getDefaultFromSchema: (schema: Schema.Schema.Any) => unknown;
270
+ /**
271
+ * An empty `FormBuilder` to start building a form.
272
+ *
273
+ * **Details**
274
+ *
275
+ * This is the entry point for building a form. Use method chaining to add
276
+ * fields and then build the form with a React adapter.
277
+ *
278
+ * @example
279
+ * ```ts
280
+ * import * as Form from "@lucas-barake/effect-form"
281
+ * import * as Schema from "effect/Schema"
282
+ *
283
+ * const EmailField = Form.makeField("email", Schema.String)
284
+ * const PasswordField = Form.makeField("password", Schema.String)
285
+ *
286
+ * const loginForm = Form.empty
287
+ * .addField(EmailField)
288
+ * .addField(PasswordField)
289
+ * ```
290
+ *
291
+ * @since 1.0.0
292
+ * @category Constructors
293
+ */
294
+ export declare const empty: FormBuilder<{}, never>;
295
+ /**
296
+ * Builds a combined Schema from a FormBuilder's field definitions.
297
+ *
298
+ * @since 1.0.0
299
+ * @category Schema
300
+ */
301
+ export declare const buildSchema: <TFields extends FieldsRecord, R>(self: FormBuilder<TFields, R>) => Schema.Schema<DecodedFromFields<TFields>, EncodedFromFields<TFields>, R>;
302
+ /**
303
+ * Gets default encoded values for a fields record.
304
+ *
305
+ * @since 1.0.0
306
+ * @category Helpers
307
+ */
308
+ export declare const getDefaultEncodedValues: (fields: FieldsRecord) => Record<string, unknown>;
309
+ /**
310
+ * Creates a touched record with all fields set to the given value.
311
+ *
312
+ * @since 1.0.0
313
+ * @category Helpers
314
+ */
315
+ export declare const createTouchedRecord: (fields: FieldsRecord, value: boolean) => Record<string, boolean>;
316
+ export {};
317
+ //# sourceMappingURL=Form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Form.d.ts","sourceRoot":"","sources":["../../src/Form.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Atom infrastructure for form state management.
3
+ *
4
+ * This module provides the core atom infrastructure that framework adapters
5
+ * (React, Vue, Svelte, Solid) can use to build reactive form components.
6
+ *
7
+ * @since 1.0.0
8
+ */
9
+ import * as Atom from "@effect-atom/atom/Atom";
10
+ import type * as Registry from "@effect-atom/atom/Registry";
11
+ import * as Option from "effect/Option";
12
+ import type * as ParseResult from "effect/ParseResult";
13
+ import * as Schema from "effect/Schema";
14
+ import type * as Form from "./Form.js";
15
+ import { type WeakRegistry } from "./internal/weak-registry.js";
16
+ /**
17
+ * Atoms for a single field.
18
+ *
19
+ * @since 1.0.0
20
+ * @category Models
21
+ */
22
+ export interface FieldAtoms {
23
+ readonly valueAtom: Atom.Writable<unknown, unknown>;
24
+ readonly initialValueAtom: Atom.Atom<unknown>;
25
+ readonly touchedAtom: Atom.Writable<boolean, boolean>;
26
+ readonly crossFieldErrorAtom: Atom.Atom<Option.Option<string>>;
27
+ }
28
+ /**
29
+ * Configuration for creating form atoms.
30
+ *
31
+ * @since 1.0.0
32
+ * @category Models
33
+ */
34
+ export interface FormAtomsConfig<TFields extends Form.FieldsRecord, R> {
35
+ readonly runtime: Atom.AtomRuntime<R, any>;
36
+ readonly formBuilder: Form.FormBuilder<TFields, R>;
37
+ }
38
+ /**
39
+ * Maps field names to their type-safe Field references for setValue operations.
40
+ *
41
+ * @since 1.0.0
42
+ * @category Models
43
+ */
44
+ export type FieldRefs<TFields extends Form.FieldsRecord> = {
45
+ readonly [K in keyof TFields]: TFields[K] extends Form.FieldDef<any, infer S> ? Form.Field<Schema.Schema.Encoded<S>> : TFields[K] extends Form.ArrayFieldDef<any, infer S> ? Form.Field<ReadonlyArray<Schema.Schema.Encoded<S>>> : never;
46
+ };
47
+ /**
48
+ * The complete form atoms infrastructure.
49
+ *
50
+ * @since 1.0.0
51
+ * @category Models
52
+ */
53
+ export interface FormAtoms<TFields extends Form.FieldsRecord, R> {
54
+ readonly stateAtom: Atom.Writable<Option.Option<Form.FormState<TFields>>, Option.Option<Form.FormState<TFields>>>;
55
+ readonly crossFieldErrorsAtom: Atom.Writable<Map<string, string>, Map<string, string>>;
56
+ readonly dirtyFieldsAtom: Atom.Atom<ReadonlySet<string>>;
57
+ readonly isDirtyAtom: Atom.Atom<boolean>;
58
+ readonly submitCountAtom: Atom.Atom<number>;
59
+ readonly onSubmitAtom: Atom.Writable<Atom.AtomResultFn<Form.DecodedFromFields<TFields>, unknown, unknown> | null, Atom.AtomResultFn<Form.DecodedFromFields<TFields>, unknown, unknown> | null>;
60
+ readonly decodeAndSubmit: Atom.AtomResultFn<Form.EncodedFromFields<TFields>, unknown, unknown>;
61
+ readonly combinedSchema: Schema.Schema<Form.DecodedFromFields<TFields>, Form.EncodedFromFields<TFields>, R>;
62
+ readonly fieldRefs: FieldRefs<TFields>;
63
+ readonly validationAtomsRegistry: WeakRegistry<Atom.AtomResultFn<unknown, void, ParseResult.ParseError>>;
64
+ readonly fieldAtomsRegistry: WeakRegistry<FieldAtoms>;
65
+ readonly getOrCreateValidationAtom: (fieldPath: string, schema: Schema.Schema.Any) => Atom.AtomResultFn<unknown, void, ParseResult.ParseError>;
66
+ readonly getOrCreateFieldAtoms: (fieldPath: string) => FieldAtoms;
67
+ readonly resetValidationAtoms: (registry: Registry.Registry) => void;
68
+ readonly operations: FormOperations<TFields>;
69
+ }
70
+ /**
71
+ * Pure state operations for form manipulation.
72
+ *
73
+ * @since 1.0.0
74
+ * @category Models
75
+ */
76
+ export interface FormOperations<TFields extends Form.FieldsRecord> {
77
+ /**
78
+ * Creates the initial form state from default values.
79
+ */
80
+ readonly createInitialState: (defaultValues: Form.EncodedFromFields<TFields>) => Form.FormState<TFields>;
81
+ /**
82
+ * Creates a reset state (back to initial values).
83
+ */
84
+ readonly createResetState: (state: Form.FormState<TFields>) => Form.FormState<TFields>;
85
+ /**
86
+ * Creates state with all fields marked as touched and submit count incremented.
87
+ */
88
+ readonly createSubmitState: (state: Form.FormState<TFields>) => Form.FormState<TFields>;
89
+ /**
90
+ * Updates a single field value in the state.
91
+ */
92
+ readonly setFieldValue: (state: Form.FormState<TFields>, fieldPath: string, value: unknown) => Form.FormState<TFields>;
93
+ /**
94
+ * Sets all form values, recalculating dirty fields.
95
+ */
96
+ readonly setFormValues: (state: Form.FormState<TFields>, values: Form.EncodedFromFields<TFields>) => Form.FormState<TFields>;
97
+ /**
98
+ * Sets a field as touched.
99
+ */
100
+ readonly setFieldTouched: (state: Form.FormState<TFields>, fieldPath: string, touched: boolean) => Form.FormState<TFields>;
101
+ /**
102
+ * Appends an item to an array field.
103
+ */
104
+ readonly appendArrayItem: (state: Form.FormState<TFields>, arrayPath: string, itemSchema: Schema.Schema.Any, value?: unknown) => Form.FormState<TFields>;
105
+ /**
106
+ * Removes an item from an array field.
107
+ */
108
+ readonly removeArrayItem: (state: Form.FormState<TFields>, arrayPath: string, index: number) => Form.FormState<TFields>;
109
+ /**
110
+ * Swaps two items in an array field.
111
+ */
112
+ readonly swapArrayItems: (state: Form.FormState<TFields>, arrayPath: string, indexA: number, indexB: number) => Form.FormState<TFields>;
113
+ /**
114
+ * Moves an item in an array field.
115
+ */
116
+ readonly moveArrayItem: (state: Form.FormState<TFields>, arrayPath: string, fromIndex: number, toIndex: number) => Form.FormState<TFields>;
117
+ }
118
+ /**
119
+ * Creates the complete form atoms infrastructure.
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * import * as FormAtoms from "@lucas-barake/effect-form/FormAtoms"
124
+ * import * as Form from "@lucas-barake/effect-form"
125
+ * import * as Atom from "@effect-atom/atom/Atom"
126
+ * import * as Layer from "effect/Layer"
127
+ *
128
+ * const runtime = Atom.runtime(Layer.empty)
129
+ *
130
+ * const loginForm = Form.empty
131
+ * .addField(Form.makeField("email", Schema.String))
132
+ * .addField(Form.makeField("password", Schema.String))
133
+ *
134
+ * const atoms = FormAtoms.make({
135
+ * runtime,
136
+ * formBuilder: loginForm,
137
+ * parsedMode: { validation: "onChange", debounce: 300, autoSubmit: false }
138
+ * })
139
+ * ```
140
+ *
141
+ * @since 1.0.0
142
+ * @category Constructors
143
+ */
144
+ export declare const make: <TFields extends Form.FieldsRecord, R>(config: FormAtomsConfig<TFields, R>) => FormAtoms<TFields, R>;
145
+ //# sourceMappingURL=FormAtoms.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormAtoms.d.ts","sourceRoot":"","sources":["../../src/FormAtoms.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Form validation mode configuration.
3
+ *
4
+ * @since 1.0.0
5
+ */
6
+ import * as Duration from "effect/Duration";
7
+ /**
8
+ * Controls when field validation is triggered and whether form auto-submits.
9
+ *
10
+ * Simple modes (string):
11
+ * - `"onSubmit"`: Validation only runs when the form is submitted (default)
12
+ * - `"onBlur"`: Validation runs when a field loses focus
13
+ * - `"onChange"`: Validation runs on every value change (sync)
14
+ *
15
+ * Object modes (with options):
16
+ * - `{ onChange: { debounce, autoSubmit? } }`: Debounced validation, optional auto-submit
17
+ * - `{ onBlur: { autoSubmit: true } }`: Validate on blur, auto-submit when valid
18
+ *
19
+ * @since 1.0.0
20
+ * @category Models
21
+ */
22
+ export type FormMode = "onSubmit" | "onBlur" | "onChange" | {
23
+ readonly onChange: {
24
+ readonly debounce: Duration.DurationInput;
25
+ readonly autoSubmit?: false;
26
+ };
27
+ } | {
28
+ readonly onBlur: {
29
+ readonly autoSubmit: true;
30
+ };
31
+ } | {
32
+ readonly onChange: {
33
+ readonly debounce: Duration.DurationInput;
34
+ readonly autoSubmit: true;
35
+ };
36
+ };
37
+ /**
38
+ * Parsed form mode with resolved values.
39
+ *
40
+ * @since 1.0.0
41
+ * @category Models
42
+ */
43
+ export interface ParsedMode {
44
+ readonly validation: "onSubmit" | "onBlur" | "onChange";
45
+ readonly debounce: number | null;
46
+ readonly autoSubmit: boolean;
47
+ }
48
+ /**
49
+ * Parses a FormMode into a normalized ParsedMode.
50
+ *
51
+ * @since 1.0.0
52
+ * @category Parsing
53
+ */
54
+ export declare const parse: (mode?: FormMode) => ParsedMode;
55
+ //# sourceMappingURL=Mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Mode.d.ts","sourceRoot":"","sources":["../../src/Mode.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAE3C;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,QAAQ,GAChB,UAAU,GACV,QAAQ,GACR,UAAU,GACV;IAAE,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC;QAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,CAAA;KAAE,CAAA;CAAE,GACjG;IAAE,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;KAAE,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAA;KAAE,CAAA;CAAE,CAAA;AAEnG;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAA;IACvD,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;CAC7B;AAED;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAAI,OAAM,QAAqB,KAAG,UAUnD,CAAA"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Validation utilities for form error handling.
3
+ *
4
+ * @since 1.0.0
5
+ */
6
+ import * as Option from "effect/Option";
7
+ import * as ParseResult from "effect/ParseResult";
8
+ /**
9
+ * Extracts the first error message from a ParseError.
10
+ *
11
+ * @since 1.0.0
12
+ * @category Error Handling
13
+ */
14
+ export declare const extractFirstError: (error: ParseResult.ParseError) => Option.Option<string>;
15
+ /**
16
+ * Routes validation errors from a ParseError to a map of field paths to error messages.
17
+ * Used for cross-field validation where schema errors need to be displayed on specific fields.
18
+ *
19
+ * @since 1.0.0
20
+ * @category Error Handling
21
+ */
22
+ export declare const routeErrors: (error: ParseResult.ParseError) => Map<string, string>;
23
+ //# sourceMappingURL=Validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Validation.d.ts","sourceRoot":"","sources":["../../src/Validation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAGjD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,WAAW,CAAC,UAAU,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAMrF,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,WAAW,CAAC,UAAU,KAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAY7E,CAAA"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @since 1.0.0
3
+ */
4
+ export * as Form from "./Form.js";
5
+ /**
6
+ * Atom infrastructure for form state management.
7
+ *
8
+ * This module provides the core atom infrastructure that framework adapters
9
+ * (React, Vue, Svelte, Solid) can use to build reactive form components.
10
+ *
11
+ * @since 1.0.0
12
+ */
13
+ export * as FormAtoms from "./FormAtoms.js";
14
+ /**
15
+ * Form validation mode configuration.
16
+ *
17
+ * @since 1.0.0
18
+ */
19
+ export * as Mode from "./Mode.js";
20
+ /**
21
+ * Validation utilities for form error handling.
22
+ *
23
+ * @since 1.0.0
24
+ */
25
+ export * as Validation from "./Validation.js";
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAEjC;;;;;;;GAOG;AACH,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAE3C;;;;GAIG;AACH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAEjC;;;;GAIG;AACH,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Recalculates dirty fields for an array after mutation.
3
+ * Clears all paths under the array and re-evaluates each item.
4
+ */
5
+ export declare const recalculateDirtyFieldsForArray: (dirtyFields: ReadonlySet<string>, initialValues: unknown, arrayPath: string, newItems: ReadonlyArray<unknown>) => ReadonlySet<string>;
6
+ /**
7
+ * Recalculates dirty fields for a subtree after value change.
8
+ * Clears the rootPath and all children, then re-evaluates recursively.
9
+ *
10
+ * @param rootPath - Empty string for full form, or a specific path for targeted update
11
+ */
12
+ export declare const recalculateDirtySubtree: (currentDirty: ReadonlySet<string>, allInitial: unknown, allValues: unknown, rootPath?: string) => ReadonlySet<string>;
13
+ //# sourceMappingURL=dirty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dirty.d.ts","sourceRoot":"","sources":["../../../src/internal/dirty.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,eAAO,MAAM,8BAA8B,GACzC,aAAa,WAAW,CAAC,MAAM,CAAC,EAChC,eAAe,OAAO,EACtB,WAAW,MAAM,EACjB,UAAU,aAAa,CAAC,OAAO,CAAC,KAC/B,WAAW,CAAC,MAAM,CA4BpB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,cAAc,WAAW,CAAC,MAAM,CAAC,EACjC,YAAY,OAAO,EACnB,WAAW,OAAO,EAClB,WAAU,MAAW,KACpB,WAAW,CAAC,MAAM,CAoCpB,CAAA"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Internal path utilities for form field operations.
3
+ *
4
+ * @internal
5
+ */
6
+ /**
7
+ * Converts a schema path array to a dot/bracket notation string.
8
+ *
9
+ * @example
10
+ * schemaPathToFieldPath(["items", 0, "name"]) // "items[0].name"
11
+ */
12
+ export declare const schemaPathToFieldPath: (path: ReadonlyArray<PropertyKey>) => string;
13
+ /**
14
+ * Checks if a field path or any of its parent paths are in the dirty set.
15
+ */
16
+ export declare const isPathOrParentDirty: (dirtyFields: ReadonlySet<string>, path: string) => boolean;
17
+ /**
18
+ * Gets a nested value from an object using dot/bracket notation path.
19
+ *
20
+ * @example
21
+ * getNestedValue({ items: [{ name: "A" }] }, "items[0].name") // "A"
22
+ */
23
+ export declare const getNestedValue: (obj: unknown, path: string) => unknown;
24
+ /**
25
+ * Sets a nested value in an object immutably using dot/bracket notation path.
26
+ *
27
+ * @example
28
+ * setNestedValue({ items: [{ name: "A" }] }, "items[0].name", "B")
29
+ * // { items: [{ name: "B" }] }
30
+ */
31
+ export declare const setNestedValue: <T>(obj: T, path: string, value: unknown) => T;
32
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../src/internal/path.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,MAAM,aAAa,CAAC,WAAW,CAAC,KAAG,MAaxE,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,aAAa,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,KAAG,OAgBpF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,KAAK,OAAO,EAAE,MAAM,MAAM,KAAG,OAS3D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,MAAM,EAAE,OAAO,OAAO,KAAG,CAkBxE,CAAA"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Internal WeakRef-based registry for caching atoms.
3
+ *
4
+ * @internal
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=weak-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weak-registry.d.ts","sourceRoot":"","sources":["../../../src/internal/weak-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}