@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.
- package/Form/package.json +6 -0
- package/FormAtoms/package.json +6 -0
- package/LICENSE +21 -0
- package/Mode/package.json +6 -0
- package/README.md +5 -0
- package/Validation/package.json +6 -0
- package/dist/cjs/Form.js +299 -0
- package/dist/cjs/Form.js.map +1 -0
- package/dist/cjs/FormAtoms.js +266 -0
- package/dist/cjs/FormAtoms.js.map +1 -0
- package/dist/cjs/Mode.js +64 -0
- package/dist/cjs/Mode.js.map +1 -0
- package/dist/cjs/Validation.js +69 -0
- package/dist/cjs/Validation.js.map +1 -0
- package/dist/cjs/index.js +35 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/internal/dirty.js +101 -0
- package/dist/cjs/internal/dirty.js.map +1 -0
- package/dist/cjs/internal/path.js +96 -0
- package/dist/cjs/internal/path.js.map +1 -0
- package/dist/cjs/internal/weak-registry.js +52 -0
- package/dist/cjs/internal/weak-registry.js.map +1 -0
- package/dist/dts/Form.d.ts +317 -0
- package/dist/dts/Form.d.ts.map +1 -0
- package/dist/dts/FormAtoms.d.ts +145 -0
- package/dist/dts/FormAtoms.d.ts.map +1 -0
- package/dist/dts/Mode.d.ts +55 -0
- package/dist/dts/Mode.d.ts.map +1 -0
- package/dist/dts/Validation.d.ts +23 -0
- package/dist/dts/Validation.d.ts.map +1 -0
- package/dist/dts/index.d.ts +26 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/internal/dirty.d.ts +13 -0
- package/dist/dts/internal/dirty.d.ts.map +1 -0
- package/dist/dts/internal/path.d.ts +32 -0
- package/dist/dts/internal/path.d.ts.map +1 -0
- package/dist/dts/internal/weak-registry.d.ts +7 -0
- package/dist/dts/internal/weak-registry.d.ts.map +1 -0
- package/dist/esm/Form.js +263 -0
- package/dist/esm/Form.js.map +1 -0
- package/dist/esm/FormAtoms.js +238 -0
- package/dist/esm/FormAtoms.js.map +1 -0
- package/dist/esm/Mode.js +36 -0
- package/dist/esm/Mode.js.map +1 -0
- package/dist/esm/Validation.js +40 -0
- package/dist/esm/Validation.js.map +1 -0
- package/dist/esm/index.js +26 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/dirty.js +72 -0
- package/dist/esm/internal/dirty.js.map +1 -0
- package/dist/esm/internal/path.js +86 -0
- package/dist/esm/internal/path.js.map +1 -0
- package/dist/esm/internal/weak-registry.js +45 -0
- package/dist/esm/internal/weak-registry.js.map +1 -0
- package/dist/esm/package.json +4 -0
- package/package.json +64 -0
- package/src/Form.ts +522 -0
- package/src/FormAtoms.ts +485 -0
- package/src/Mode.ts +59 -0
- package/src/Validation.ts +43 -0
- package/src/index.ts +28 -0
- package/src/internal/dirty.ts +96 -0
- package/src/internal/path.ts +93 -0
- 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 @@
|
|
|
1
|
+
{"version":3,"file":"weak-registry.d.ts","sourceRoot":"","sources":["../../../src/internal/weak-registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|