@conform-to/react 1.19.3 → 1.20.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/README.md +1 -1
- package/dist/context.d.ts +2 -2
- package/dist/future/dom.d.ts +2 -2
- package/dist/future/dom.js +9 -4
- package/dist/future/dom.mjs +9 -4
- package/dist/future/forms.d.ts +62 -21
- package/dist/future/forms.js +59 -11
- package/dist/future/forms.mjs +56 -9
- package/dist/future/hooks.d.ts +9 -4
- package/dist/future/hooks.js +67 -35
- package/dist/future/hooks.mjs +70 -38
- package/dist/future/index.d.ts +4 -2
- package/dist/future/index.js +5 -0
- package/dist/future/index.mjs +3 -1
- package/dist/future/intent.d.ts +27 -21
- package/dist/future/intent.js +369 -371
- package/dist/future/intent.mjs +361 -372
- package/dist/future/state.d.ts +48 -21
- package/dist/future/state.js +344 -43
- package/dist/future/state.mjs +339 -46
- package/dist/future/types.d.ts +158 -149
- package/dist/future/util.d.ts +4 -8
- package/dist/future/util.js +25 -60
- package/dist/future/util.mjs +26 -59
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.js +2 -2
- package/dist/helpers.mjs +2 -2
- package/dist/hooks.d.ts +1 -1
- package/dist/vitest.config.d.ts +0 -1
- package/package.json +2 -2
package/dist/future/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CustomSerialize, FieldName, FormError, FormValue, Serialize, SubmissionResult, ValidationAttributes } from '@conform-to/dom/future';
|
|
1
|
+
import type { CustomSerialize, FieldName, FormError, FormValue, Serialize, Submission, SubmissionResult, ValidationAttributes } from '@conform-to/dom/future';
|
|
2
2
|
import type { StandardSchemaV1 } from './standard-schema';
|
|
3
3
|
export type Prettify<T> = {
|
|
4
4
|
[K in keyof T]: T[K];
|
|
@@ -139,7 +139,7 @@ export type UseFormDataOptions<Value = undefined> = {
|
|
|
139
139
|
export type DefaultValue<Shape> = Shape extends Record<string, any> ? {
|
|
140
140
|
[Key in keyof Shape]?: DefaultValue<Shape[Key]>;
|
|
141
141
|
} | null | undefined : Shape extends Array<infer Item> ? Array<DefaultValue<Item>> | null | undefined : Shape extends File | File[] ? null | undefined : Shape | string | null | undefined;
|
|
142
|
-
export type FormState<ErrorShape = any> = {
|
|
142
|
+
export type FormState<ErrorShape = any, CustomState extends Record<string, unknown> = {}> = {
|
|
143
143
|
/** Unique identifier that changes on form reset to trigger reset side effects */
|
|
144
144
|
resetKey: string;
|
|
145
145
|
/** Initial form values */
|
|
@@ -156,10 +156,13 @@ export type FormState<ErrorShape = any> = {
|
|
|
156
156
|
touchedFields: string[];
|
|
157
157
|
/** Mapping of array field names to their item keys for React list rendering */
|
|
158
158
|
listKeys: Record<string, string[]>;
|
|
159
|
+
/** Current custom state for the form */
|
|
160
|
+
customState: CustomState;
|
|
159
161
|
};
|
|
160
|
-
export type FormAction<ErrorShape = any, Intent extends UnknownIntent
|
|
161
|
-
type: 'initialize' | 'server' | 'client';
|
|
162
|
+
export type FormAction<ErrorShape = any, Intent extends UnknownIntent = UnknownIntent, Context = {}> = {
|
|
163
|
+
type: 'initialize' | 'server' | 'client' | 'client:async';
|
|
162
164
|
intent: Intent;
|
|
165
|
+
result: SubmissionResult<ErrorShape>;
|
|
163
166
|
ctx: Context;
|
|
164
167
|
};
|
|
165
168
|
/**
|
|
@@ -239,7 +242,7 @@ export type ExtractFieldConditions<T extends Record<string, FieldShapeGuard<any>
|
|
|
239
242
|
* Resolved configuration from configureForms factory.
|
|
240
243
|
* Properties with defaults are required, others remain optional.
|
|
241
244
|
*/
|
|
242
|
-
export type FormsConfig<BaseErrorShape, BaseSchema, SchemaErrorShape, CustomFormMetadata extends Record<string, unknown>, CustomFieldMetadata extends Record<string, unknown
|
|
245
|
+
export type FormsConfig<BaseErrorShape, BaseSchema, SchemaErrorShape, CustomFormMetadata extends Record<string, unknown>, CustomFieldMetadata extends Record<string, unknown>, CustomIntentHandlers extends Record<string, IntentHandler<any, any>>, CustomStateHandlers extends Record<string, CustomStateHandler<any, any, BaseErrorShape>>> = {
|
|
243
246
|
/**
|
|
244
247
|
* The name of the submit button field that indicates the submission intent.
|
|
245
248
|
* @default "__intent__"
|
|
@@ -249,6 +252,14 @@ export type FormsConfig<BaseErrorShape, BaseSchema, SchemaErrorShape, CustomForm
|
|
|
249
252
|
* A custom serializer for converting form values.
|
|
250
253
|
*/
|
|
251
254
|
serialize?: CustomSerialize | undefined;
|
|
255
|
+
/**
|
|
256
|
+
* Intent handlers available to every form created by this factory.
|
|
257
|
+
*/
|
|
258
|
+
intents?: CustomIntentHandlers;
|
|
259
|
+
/**
|
|
260
|
+
* Custom state available to every form created by this factory.
|
|
261
|
+
*/
|
|
262
|
+
customState?: CustomStateDefinition<CustomStateHandlers, CustomIntentHandlers>;
|
|
252
263
|
/**
|
|
253
264
|
* Determines when validation should run for the first time on a field.
|
|
254
265
|
* @default "onSubmit"
|
|
@@ -298,13 +309,13 @@ export type FormsConfig<BaseErrorShape, BaseSchema, SchemaErrorShape, CustomForm
|
|
|
298
309
|
/**
|
|
299
310
|
* Extends form metadata with custom properties.
|
|
300
311
|
*/
|
|
301
|
-
extendFormMetadata?: <ErrorShape extends BaseErrorShape>(metadata: BaseFormMetadata<ErrorShape
|
|
312
|
+
extendFormMetadata?: <ErrorShape extends BaseErrorShape>(metadata: BaseFormMetadata<ErrorShape, FormCustomState<CustomStateHandlers>>) => CustomFormMetadata;
|
|
302
313
|
/**
|
|
303
314
|
* Extends field metadata with custom properties.
|
|
304
315
|
* Use `when` for properties that depend on the field shape.
|
|
305
316
|
*/
|
|
306
317
|
extendFieldMetadata?: <FieldShape, ErrorShape extends BaseErrorShape>(metadata: BaseFieldMetadata<FieldShape, ErrorShape>, ctx: {
|
|
307
|
-
form: BaseFormMetadata<ErrorShape
|
|
318
|
+
form: BaseFormMetadata<ErrorShape, FormCustomState<CustomStateHandlers>>;
|
|
308
319
|
when: DefineConditionalField;
|
|
309
320
|
}) => CustomFieldMetadata;
|
|
310
321
|
};
|
|
@@ -332,7 +343,7 @@ export type InferFormShape<Schema> = InferInput<Schema> extends Record<string, a
|
|
|
332
343
|
export type InferOutput<Schema> = Schema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<Schema> : CustomSchemaTypes<Schema> extends {
|
|
333
344
|
output: infer T;
|
|
334
345
|
} ? T : undefined;
|
|
335
|
-
export type FormOptions<FormShape extends Record<string, any> = Record<string, any>, ErrorShape = any, Value = undefined, Schema = unknown, SchemaErrorShape = ErrorShape> = {
|
|
346
|
+
export type FormOptions<FormShape extends Record<string, any> = Record<string, any>, ErrorShape = any, Value = undefined, Schema = unknown, SchemaErrorShape = ErrorShape, CustomIntentHandlers extends Record<string, IntentHandler<any, any>> = {}, GlobalIntentHandlers extends Record<string, IntentHandler<any, any>> = {}, CustomStateHandlers extends Record<string, CustomStateHandler<any, any, any>> = {}> = {
|
|
336
347
|
/** Optional form identifier. If not provided, a unique ID is automatically generated. */
|
|
337
348
|
id?: string | undefined;
|
|
338
349
|
/** Optional key for form state reset. When the key changes, the form resets to its initial state. */
|
|
@@ -348,6 +359,14 @@ export type FormOptions<FormShape extends Record<string, any> = Record<string, a
|
|
|
348
359
|
* to the configured global serializer.
|
|
349
360
|
*/
|
|
350
361
|
serialize?: CustomSerialize | undefined;
|
|
362
|
+
/**
|
|
363
|
+
* Custom intent handlers available only to this form instance.
|
|
364
|
+
*/
|
|
365
|
+
intents?: CustomIntentHandlers | undefined;
|
|
366
|
+
/**
|
|
367
|
+
* Custom state available only to this form instance.
|
|
368
|
+
*/
|
|
369
|
+
customState?: CustomStateDefinition<CustomStateHandlers, GlobalIntentHandlers & CustomIntentHandlers> | undefined;
|
|
351
370
|
/** HTML validation attributes for fields (required, minLength, pattern, etc.). */
|
|
352
371
|
constraint?: Record<string, ValidationAttributes> | undefined;
|
|
353
372
|
/**
|
|
@@ -376,25 +395,25 @@ export type FormOptions<FormShape extends Record<string, any> = Record<string, a
|
|
|
376
395
|
/** Blur event handler for custom focus handling logic. */
|
|
377
396
|
onBlur?: BlurHandler | undefined;
|
|
378
397
|
/** Custom validation handler. Can be skipped when a schema is passed as the first argument, or combined with schema validation to customize errors. */
|
|
379
|
-
onValidate?: ValidateHandler<ErrorShape, Value, InferOutput<Schema>, SchemaErrorShape> | undefined;
|
|
398
|
+
onValidate?: ValidateHandler<ErrorShape, Value, InferOutput<Schema>, SchemaErrorShape, FormIntent<FormShape, DefaultIntentHandlers & GlobalIntentHandlers & CustomIntentHandlers> | undefined> | undefined;
|
|
380
399
|
};
|
|
381
400
|
/**
|
|
382
401
|
* The object returned by `useForm()`, containing form-level metadata,
|
|
383
402
|
* typed field metadata, and the intent dispatcher for programmatic updates.
|
|
384
403
|
*/
|
|
385
|
-
export type FormHandle<FormShape extends Record<string, any>, ErrorShape, CustomFormMetadata extends Record<string, unknown> = {}, CustomFieldMetadata extends Record<string, unknown> = {}> = {
|
|
404
|
+
export type FormHandle<FormShape extends Record<string, any>, ErrorShape, CustomFormMetadata extends Record<string, unknown> = {}, CustomFieldMetadata extends Record<string, unknown> = {}, CustomIntentHandlers extends Record<string, IntentHandler<any, any>> = {}, CustomState extends Record<string, unknown> = {}> = {
|
|
386
405
|
/** Form-level metadata and helpers. */
|
|
387
|
-
form: FormMetadata<ErrorShape, CustomFormMetadata, CustomFieldMetadata>;
|
|
406
|
+
form: FormMetadata<ErrorShape, CustomFormMetadata, CustomFieldMetadata, CustomState>;
|
|
388
407
|
/** Field metadata mapped from the form shape. */
|
|
389
408
|
fields: Fieldset<FormShape, ErrorShape, CustomFieldMetadata>;
|
|
390
409
|
/** Intent dispatcher for validate, reset, insert, remove, reorder, and update actions. */
|
|
391
|
-
intent: IntentDispatcher<FormShape>;
|
|
410
|
+
intent: IntentDispatcher<FormShape, CustomIntentHandlers>;
|
|
392
411
|
};
|
|
393
|
-
export interface FormContext<ErrorShape = any> {
|
|
412
|
+
export interface FormContext<ErrorShape = any, CustomState extends Record<string, unknown> = {}> {
|
|
394
413
|
/** The form's unique identifier */
|
|
395
414
|
formId: string;
|
|
396
415
|
/** Internal form state with validation results and field data */
|
|
397
|
-
state: FormState<ErrorShape>;
|
|
416
|
+
state: FormState<ErrorShape, CustomState>;
|
|
398
417
|
/** Serializer used to derive field defaults and sync values for this form. */
|
|
399
418
|
serialize: Serialize;
|
|
400
419
|
/** HTML validation attributes for fields */
|
|
@@ -408,153 +427,134 @@ export interface FormContext<ErrorShape = any> {
|
|
|
408
427
|
}
|
|
409
428
|
export type UnknownIntent = {
|
|
410
429
|
type: string;
|
|
411
|
-
payload
|
|
430
|
+
payload: unknown;
|
|
431
|
+
};
|
|
432
|
+
export type TransportIntent = {
|
|
433
|
+
type: string;
|
|
434
|
+
args: unknown[];
|
|
412
435
|
};
|
|
413
436
|
export type UnknownArgs<Args extends any[]> = {
|
|
414
437
|
[Key in keyof Args]: unknown;
|
|
415
438
|
};
|
|
416
|
-
export interface
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
* intent.reset({ defaultValue: null })
|
|
433
|
-
*
|
|
434
|
-
* // Restore to a specific snapshot
|
|
435
|
-
* intent.reset({ defaultValue: snapshotValue })
|
|
436
|
-
* ```
|
|
437
|
-
*/
|
|
438
|
-
reset(options?: {
|
|
439
|
-
/**
|
|
440
|
-
* The value to reset the form to. If not provided, resets to the default value from `useForm`. Pass `null` to clear all fields instead.
|
|
441
|
-
*/
|
|
439
|
+
export interface TypedIntentDefinition {
|
|
440
|
+
readonly FormShape: unknown;
|
|
441
|
+
dispatch(...args: any[]): void;
|
|
442
|
+
}
|
|
443
|
+
export type IntentDefinition = ((...args: any[]) => void) | TypedIntentDefinition;
|
|
444
|
+
export type ExtractDispatchSignature<Intent extends IntentDefinition, FormShape extends Record<string, any>> = Intent extends (...args: any[]) => void ? Intent : Intent extends TypedIntentDefinition ? (Intent & {
|
|
445
|
+
readonly FormShape: FormShape;
|
|
446
|
+
})['dispatch'] : never;
|
|
447
|
+
export type IntentPayload<Intent extends IntentDefinition, FormShape extends Record<string, any> = Record<string, any>> = Parameters<ExtractDispatchSignature<Intent, FormShape>> extends [] ? undefined : Parameters<ExtractDispatchSignature<Intent, FormShape>>[0];
|
|
448
|
+
export type NormalizeIntentType<T> = T extends IntentDefinition ? T : (payload: T) => void;
|
|
449
|
+
export type ApplyStatus = 'applied' | 'reverted' | 'modified';
|
|
450
|
+
export type IntentDispatch<Intent extends IntentDefinition, FormShape extends Record<string, any> = Record<string, any>> = ExtractDispatchSignature<NormalizeIntentType<Intent>, FormShape>;
|
|
451
|
+
export type IntentHandlerPayload<Dispatch extends IntentDefinition, Payload, FormShape extends Record<string, any>> = [Payload] extends [never] ? IntentPayload<NormalizeIntentType<Dispatch>, FormShape> : Payload;
|
|
452
|
+
export type SubmitIntent = () => void;
|
|
453
|
+
export interface ResetIntent extends TypedIntentDefinition {
|
|
454
|
+
dispatch<FormShape extends Record<string, any> = this['FormShape'] extends Record<string, any> ? this['FormShape'] : never>(options?: {
|
|
442
455
|
defaultValue?: DefaultValue<FormShape>;
|
|
443
456
|
}): void;
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
457
|
+
}
|
|
458
|
+
export type ValidateIntent = (name?: string) => void;
|
|
459
|
+
export type IsUntypedFormShape<FormShape> = unknown extends FormShape ? true : string extends keyof FormShape ? true : false;
|
|
460
|
+
export interface UpdateIntent extends TypedIntentDefinition {
|
|
461
|
+
dispatch<FieldShape = this['FormShape']>(options: IsUntypedFormShape<this['FormShape']> extends true ? {
|
|
462
|
+
name?: string | undefined;
|
|
463
|
+
index?: number | undefined;
|
|
464
|
+
value: unknown;
|
|
465
|
+
} : {
|
|
452
466
|
name?: FieldName<FieldShape>;
|
|
453
|
-
/**
|
|
454
|
-
* Specify the index of the item to update if the field is an array.
|
|
455
|
-
*/
|
|
456
467
|
index?: undefined;
|
|
457
|
-
/**
|
|
458
|
-
* The new value for the field or fieldset.
|
|
459
|
-
*/
|
|
460
468
|
value: DefaultValue<FieldShape>;
|
|
461
469
|
} | {
|
|
462
|
-
|
|
463
|
-
* The name of the field. If you provide a fieldset name, it will update all fields within that fieldset.
|
|
464
|
-
*/
|
|
465
|
-
name: FieldName<FieldShape>;
|
|
466
|
-
/**
|
|
467
|
-
* Specify the index of the item to update if the field is an array.
|
|
468
|
-
*/
|
|
470
|
+
name: FieldName<FieldShape extends Array<any> | null | undefined ? FieldShape : never>;
|
|
469
471
|
index: number;
|
|
470
|
-
|
|
471
|
-
* The new value for the field or fieldset.
|
|
472
|
-
* When index is specified, this should be the item type, not the array type.
|
|
473
|
-
*/
|
|
474
|
-
value: unknown extends FieldShape ? any : FieldShape extends Array<infer ItemShape> ? ItemShape : any;
|
|
472
|
+
value: NonNullable<FieldShape> extends Array<infer ItemShape> ? DefaultValue<ItemShape> : never;
|
|
475
473
|
}): void;
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
insert<FieldShape extends Array<any> | null | undefined>(options: {
|
|
480
|
-
/**
|
|
481
|
-
* The name of the array field to insert into.
|
|
482
|
-
*/
|
|
474
|
+
}
|
|
475
|
+
export interface InsertIntent extends TypedIntentDefinition {
|
|
476
|
+
dispatch<FieldShape extends Array<any> | null | undefined>(options: {
|
|
483
477
|
name: FieldName<FieldShape>;
|
|
484
|
-
/**
|
|
485
|
-
* The index at which to insert the new item.
|
|
486
|
-
* If not provided, it will be added to the end of the array.
|
|
487
|
-
*/
|
|
488
478
|
index?: number;
|
|
489
|
-
/**
|
|
490
|
-
* The default value for the new item.
|
|
491
|
-
*/
|
|
492
479
|
defaultValue?: NonNullable<FieldShape> extends Array<infer ItemShape> ? DefaultValue<ItemShape> : never;
|
|
493
|
-
/**
|
|
494
|
-
* The name of a field to read the value from.
|
|
495
|
-
* When specified, the value is read from this field, validated,
|
|
496
|
-
* and if valid, inserted into the array and the source field is cleared.
|
|
497
|
-
* If validation fails, the error is shown on the source field instead.
|
|
498
|
-
* Requires the validation error to be available synchronously.
|
|
499
|
-
*/
|
|
500
480
|
from?: string;
|
|
501
|
-
/**
|
|
502
|
-
* What to do when the insert causes a validation error on the array.
|
|
503
|
-
* - 'revert': Don't insert, keep original array state.
|
|
504
|
-
* Requires the validation error to be available synchronously.
|
|
505
|
-
*/
|
|
506
481
|
onInvalid?: 'revert';
|
|
507
482
|
}): void;
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
remove<FieldShape extends Array<any> | null | undefined>(options: {
|
|
512
|
-
/**
|
|
513
|
-
* The name of the array field to remove from.
|
|
514
|
-
*/
|
|
483
|
+
}
|
|
484
|
+
export interface RemoveIntent extends TypedIntentDefinition {
|
|
485
|
+
dispatch<FieldShape extends Array<any> | null | undefined>(options: {
|
|
515
486
|
name: FieldName<FieldShape>;
|
|
516
|
-
/**
|
|
517
|
-
* The index of the item to remove.
|
|
518
|
-
*/
|
|
519
487
|
index: number;
|
|
520
|
-
/**
|
|
521
|
-
* What to do when the remove causes a validation error on the array.
|
|
522
|
-
* - 'revert': Don't remove, keep original item as-is.
|
|
523
|
-
* - 'insert': Remove the item but insert a new blank item at the end.
|
|
524
|
-
* Requires the validation error to be available synchronously.
|
|
525
|
-
*/
|
|
526
488
|
onInvalid?: 'revert' | 'insert';
|
|
527
|
-
/**
|
|
528
|
-
* The default value for the new item when onInvalid is 'insert'.
|
|
529
|
-
*/
|
|
530
489
|
defaultValue?: NonNullable<FieldShape> extends Array<infer ItemShape> ? DefaultValue<ItemShape> : never;
|
|
531
490
|
}): void;
|
|
532
|
-
/**
|
|
533
|
-
* Reorder items in an array field.
|
|
534
|
-
*/
|
|
535
|
-
reorder(options: {
|
|
536
|
-
name: FieldName<Array<any>>;
|
|
537
|
-
from: number;
|
|
538
|
-
to: number;
|
|
539
|
-
}): void;
|
|
540
491
|
}
|
|
541
|
-
export type
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
492
|
+
export type ReorderIntent = (options: {
|
|
493
|
+
name: FieldName<Array<any>>;
|
|
494
|
+
from: number;
|
|
495
|
+
to: number;
|
|
496
|
+
}) => void;
|
|
497
|
+
export type DefaultIntentHandlers = {
|
|
498
|
+
submit: IntentHandler<SubmitIntent>;
|
|
499
|
+
reset: IntentHandler<ResetIntent>;
|
|
500
|
+
validate: IntentHandler<ValidateIntent>;
|
|
501
|
+
update: IntentHandler<UpdateIntent>;
|
|
502
|
+
insert: IntentHandler<InsertIntent>;
|
|
503
|
+
remove: IntentHandler<RemoveIntent>;
|
|
504
|
+
reorder: IntentHandler<ReorderIntent>;
|
|
505
|
+
};
|
|
506
|
+
export type IntentDispatcher<FormShape extends Record<string, any>, CustomIntentHandlers extends Record<string, IntentHandler<any, any>> = {}> = {
|
|
507
|
+
[Type in keyof (DefaultIntentHandlers & ([CustomIntentHandlers] extends [never] ? {} : CustomIntentHandlers))]: (DefaultIntentHandlers & ([CustomIntentHandlers] extends [never] ? {} : CustomIntentHandlers))[Type] extends IntentHandler<infer Dispatch, any> ? IntentDispatch<Dispatch, FormShape> : never;
|
|
508
|
+
};
|
|
509
|
+
export type FormIntent<FormShape extends Record<string, any>, Handlers extends Record<string, IntentHandler<any, any>>> = {
|
|
510
|
+
[K in keyof ([Handlers] extends [never] ? {} : Handlers)]: ([
|
|
511
|
+
Handlers
|
|
512
|
+
] extends [never] ? {} : Handlers)[K] extends IntentHandler<infer Dispatch, infer Payload> ? {
|
|
513
|
+
type: K & string;
|
|
514
|
+
payload: IntentHandlerPayload<Dispatch, Payload, FormShape>;
|
|
545
515
|
} : never;
|
|
546
|
-
}[keyof
|
|
547
|
-
export type IntentHandler<
|
|
548
|
-
|
|
549
|
-
resolve
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
516
|
+
}[keyof ([Handlers] extends [never] ? {} : Handlers)];
|
|
517
|
+
export type IntentHandler<Dispatch extends IntentDefinition = (payload: any) => void, Payload = never> = {
|
|
518
|
+
parse<FormShape extends Record<string, any>>(...args: Parameters<IntentDispatch<Dispatch, FormShape>>): IntentHandlerPayload<Dispatch, Payload, FormShape>;
|
|
519
|
+
resolve?<FormShape extends Record<string, any>>(ctx: {
|
|
520
|
+
value: Record<string, FormValue>;
|
|
521
|
+
payload: IntentHandlerPayload<Dispatch, Payload, FormShape>;
|
|
522
|
+
}): Record<string, FormValue> | undefined;
|
|
523
|
+
apply?<FormShape extends Record<string, any>, ErrorShape>(ctx: {
|
|
524
|
+
result: SubmissionResult<ErrorShape>;
|
|
525
|
+
payload: IntentHandlerPayload<Dispatch, Payload, FormShape>;
|
|
526
|
+
}): SubmissionResult<ErrorShape>;
|
|
527
|
+
touch?<FormShape extends Record<string, any>>(ctx: {
|
|
528
|
+
name: string;
|
|
529
|
+
payload: IntentHandlerPayload<Dispatch, Payload, FormShape>;
|
|
530
|
+
}): boolean;
|
|
531
|
+
move?<FormShape extends Record<string, any>>(ctx: {
|
|
532
|
+
name: string;
|
|
533
|
+
status: ApplyStatus;
|
|
534
|
+
targetValue: Record<string, FormValue> | undefined;
|
|
535
|
+
payload: IntentHandlerPayload<Dispatch, Payload, FormShape>;
|
|
536
|
+
}): string | null;
|
|
537
|
+
};
|
|
538
|
+
export type CustomStateHandler<State, CustomIntentHandlers extends Record<string, IntentHandler<any, any>> = {}, ErrorShape = any> = {
|
|
539
|
+
initialize(): State;
|
|
540
|
+
reset?: boolean | ((state: State, ctx: {
|
|
541
|
+
result: SubmissionResult<ErrorShape> | undefined;
|
|
542
|
+
}) => State);
|
|
543
|
+
handleIntent?(state: State, ctx: {
|
|
544
|
+
intent: FormIntent<any, DefaultIntentHandlers & CustomIntentHandlers>;
|
|
545
|
+
submission: Submission;
|
|
546
|
+
}): State;
|
|
547
|
+
handleResult?(state: State, ctx: {
|
|
548
|
+
intent: FormIntent<any, DefaultIntentHandlers & CustomIntentHandlers>;
|
|
549
|
+
result: SubmissionResult<ErrorShape>;
|
|
550
|
+
phase: 'client' | 'server';
|
|
551
|
+
}): State;
|
|
552
|
+
};
|
|
553
|
+
export type FormCustomState<Handlers extends Record<string, CustomStateHandler<any, any, any>>> = {
|
|
554
|
+
[Key in keyof Handlers]: Handlers[Key] extends CustomStateHandler<infer State, any, any> ? State : never;
|
|
555
|
+
};
|
|
556
|
+
type CustomStateDefinition<CustomStateHandlers extends Record<string, CustomStateHandler<any, any, any>>, IntentHandlers extends Record<string, IntentHandler<any, any>>> = {
|
|
557
|
+
[Key in keyof CustomStateHandlers]: CustomStateHandlers[Key] extends CustomStateHandler<any, infer RequiredIntents, any> ? Exclude<keyof RequiredIntents, keyof IntentHandlers> extends never ? RequiredIntents extends Pick<IntentHandlers, Extract<keyof RequiredIntents, keyof IntentHandlers>> ? CustomStateHandlers[Key] : never : never : never;
|
|
558
558
|
};
|
|
559
559
|
type BaseCombine<T, K extends PropertyKey = T extends unknown ? keyof T : never> = T extends unknown ? T & Partial<Record<Exclude<K, keyof T>, never>> : never;
|
|
560
560
|
export type Combine<T> = {
|
|
@@ -635,7 +635,7 @@ export type Fieldset<FieldShape, ErrorShape = any, CustomFieldMetadata extends R
|
|
|
635
635
|
[Key in keyof Combine<FieldShape>]-?: FieldMetadata<Combine<FieldShape>[Key], ErrorShape, CustomFieldMetadata>;
|
|
636
636
|
};
|
|
637
637
|
/** Form-level metadata and state object containing validation status, errors, and field access methods. */
|
|
638
|
-
export type FormMetadata<ErrorShape = any, CustomFormMetadata extends Record<string, unknown> = {}, CustomFieldMetadata extends Record<string, unknown> = {}> = Readonly<{
|
|
638
|
+
export type FormMetadata<ErrorShape = any, CustomFormMetadata extends Record<string, unknown> = {}, CustomFieldMetadata extends Record<string, unknown> = {}, CustomState extends Record<string, unknown> = {}> = Readonly<{
|
|
639
639
|
/** Unique identifier that changes on form reset */
|
|
640
640
|
key: string;
|
|
641
641
|
/** The form's unique identifier. */
|
|
@@ -656,6 +656,8 @@ export type FormMetadata<ErrorShape = any, CustomFormMetadata extends Record<str
|
|
|
656
656
|
fieldErrors: Record<string, ErrorShape>;
|
|
657
657
|
/** The form's initial default values. */
|
|
658
658
|
defaultValue: Record<string, unknown>;
|
|
659
|
+
/** Current custom state for the form. */
|
|
660
|
+
customState: CustomState;
|
|
659
661
|
/** Form props object for spreading onto the <form> element. */
|
|
660
662
|
props: Readonly<{
|
|
661
663
|
id: string;
|
|
@@ -665,7 +667,7 @@ export type FormMetadata<ErrorShape = any, CustomFormMetadata extends Record<str
|
|
|
665
667
|
noValidate: boolean;
|
|
666
668
|
}>;
|
|
667
669
|
/** The current state of the form */
|
|
668
|
-
context: FormContext<ErrorShape>;
|
|
670
|
+
context: FormContext<ErrorShape, CustomState>;
|
|
669
671
|
/** Method to get metadata for a specific field by name. */
|
|
670
672
|
getField<FieldShape>(name: FieldName<FieldShape>): FieldMetadata<FieldShape, ErrorShape, CustomFieldMetadata>;
|
|
671
673
|
/** Method to get a fieldset object for nested object fields. */
|
|
@@ -679,12 +681,18 @@ export type FormMetadata<ErrorShape = any, CustomFormMetadata extends Record<str
|
|
|
679
681
|
* Form metadata without custom extensions. This is the type received in `extendFormMetadata`.
|
|
680
682
|
* Equivalent to `FormMetadata<ErrorShape, {}, CustomFieldMetadata>`.
|
|
681
683
|
*/
|
|
682
|
-
export type BaseFormMetadata<ErrorShape = any,
|
|
684
|
+
export type BaseFormMetadata<ErrorShape = any, CustomState extends Record<string, unknown> = {}> = FormMetadata<ErrorShape, {}, {}, CustomState>;
|
|
683
685
|
export type ValidateResult<ErrorShape, Value> = FormError<ErrorShape> | null | {
|
|
684
686
|
error: FormError<ErrorShape> | null;
|
|
685
687
|
value?: Value;
|
|
686
688
|
};
|
|
687
|
-
export type
|
|
689
|
+
export type StagedValidateResult<ErrorShape, Value> = {
|
|
690
|
+
/** The validation result available immediately. */
|
|
691
|
+
result: ValidateResult<ErrorShape, Value>;
|
|
692
|
+
/** A complete validation result that replaces the immediate result when resolved. */
|
|
693
|
+
pending: Promise<ValidateResult<ErrorShape, Value>>;
|
|
694
|
+
};
|
|
695
|
+
export type ValidateContext<SchemaValue, SchemaErrorShape, Intent extends UnknownIntent | undefined = UnknownIntent | undefined> = {
|
|
688
696
|
/**
|
|
689
697
|
* The submitted values mapped by field name.
|
|
690
698
|
* Supports nested names like `user.email` and indexed names like `items[0].id`.
|
|
@@ -698,7 +706,7 @@ export type ValidateContext<SchemaValue, SchemaErrorShape> = {
|
|
|
698
706
|
/**
|
|
699
707
|
* The submission intent derived from the button that triggered the form submission.
|
|
700
708
|
*/
|
|
701
|
-
intent:
|
|
709
|
+
intent: Intent;
|
|
702
710
|
/**
|
|
703
711
|
* The raw FormData object of the submission.
|
|
704
712
|
*/
|
|
@@ -717,10 +725,7 @@ export type ValidateContext<SchemaValue, SchemaErrorShape> = {
|
|
|
717
725
|
*/
|
|
718
726
|
schemaValue: SchemaValue;
|
|
719
727
|
};
|
|
720
|
-
export type ValidateHandler<ErrorShape, Value, SchemaValue = undefined, SchemaErrorShape = ErrorShape> = (ctx: ValidateContext<SchemaValue, SchemaErrorShape>) => ValidateResult<ErrorShape, Value> | Promise<ValidateResult<ErrorShape, Value>> |
|
|
721
|
-
ValidateResult<ErrorShape, Value> | undefined,
|
|
722
|
-
Promise<ValidateResult<ErrorShape, Value>> | undefined
|
|
723
|
-
] | undefined;
|
|
728
|
+
export type ValidateHandler<ErrorShape, Value, SchemaValue = undefined, SchemaErrorShape = ErrorShape, Intent extends UnknownIntent | undefined = UnknownIntent | undefined> = (ctx: ValidateContext<SchemaValue, SchemaErrorShape, Intent>) => ValidateResult<ErrorShape, Value> | Promise<ValidateResult<ErrorShape, Value>> | StagedValidateResult<ErrorShape, Value> | undefined;
|
|
724
729
|
export interface FormInputEvent extends React.FormEvent<HTMLFormElement> {
|
|
725
730
|
currentTarget: EventTarget & HTMLFormElement;
|
|
726
731
|
target: EventTarget & (HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement | HTMLFieldSetElement);
|
|
@@ -733,7 +738,7 @@ export interface FormFocusEvent extends React.FormEvent<HTMLFormElement> {
|
|
|
733
738
|
export type ErrorContext<ErrorShape> = {
|
|
734
739
|
formElement: HTMLFormElement;
|
|
735
740
|
error: FormError<ErrorShape>;
|
|
736
|
-
intent: UnknownIntent |
|
|
741
|
+
intent: UnknownIntent | undefined;
|
|
737
742
|
};
|
|
738
743
|
export type ErrorHandler<ErrorShape> = (ctx: ErrorContext<ErrorShape>) => void;
|
|
739
744
|
export type InputHandler = (event: FormInputEvent) => void;
|
|
@@ -757,7 +762,7 @@ export type SubmitHandler<FormShape extends Record<string, any> = Record<string,
|
|
|
757
762
|
* type ErrorShape = InferBaseErrorShape<typeof config>; // { message: string }
|
|
758
763
|
* ```
|
|
759
764
|
*/
|
|
760
|
-
export type InferBaseErrorShape<Config> = Config extends FormsConfig<infer ErrorShape, any, any, any, any> ? ErrorShape : string;
|
|
765
|
+
export type InferBaseErrorShape<Config> = Config extends FormsConfig<infer ErrorShape, any, any, any, any, any, any> ? ErrorShape : string;
|
|
761
766
|
/**
|
|
762
767
|
* Infer the custom form metadata extension from a FormsConfig.
|
|
763
768
|
* Use this to compose with FormMetadata, FieldMetadata, or Fieldset types.
|
|
@@ -774,7 +779,7 @@ export type InferBaseErrorShape<Config> = Config extends FormsConfig<infer Error
|
|
|
774
779
|
* >;
|
|
775
780
|
* ```
|
|
776
781
|
*/
|
|
777
|
-
export type InferCustomFormMetadata<Config> = Config extends FormsConfig<any, any, any, infer CustomFormMetadata, any> ? CustomFormMetadata : {};
|
|
782
|
+
export type InferCustomFormMetadata<Config> = Config extends FormsConfig<any, any, any, infer CustomFormMetadata, any, any, any> ? CustomFormMetadata : {};
|
|
778
783
|
/**
|
|
779
784
|
* Infer the custom field metadata extension from a FormsConfig.
|
|
780
785
|
* Use this to compose with FieldMetadata or Fieldset types.
|
|
@@ -788,7 +793,11 @@ export type InferCustomFormMetadata<Config> = Config extends FormsConfig<any, an
|
|
|
788
793
|
* type MyFieldset<T> = Fieldset<T, InferBaseErrorShape<typeof config>, InferCustomFieldMetadata<typeof config>>;
|
|
789
794
|
* ```
|
|
790
795
|
*/
|
|
791
|
-
export type InferCustomFieldMetadata<Config> = Config extends FormsConfig<any, any, any, any, infer CustomFieldMetadata> ? CustomFieldMetadata : {};
|
|
796
|
+
export type InferCustomFieldMetadata<Config> = Config extends FormsConfig<any, any, any, any, infer CustomFieldMetadata, any, any> ? CustomFieldMetadata : {};
|
|
797
|
+
/**
|
|
798
|
+
* Infer the configured custom-state shape from a FormsConfig.
|
|
799
|
+
*/
|
|
800
|
+
export type InferCustomState<Config> = Config extends FormsConfig<any, any, any, any, any, any, infer CustomStateHandlers> ? FormCustomState<CustomStateHandlers> : {};
|
|
792
801
|
/**
|
|
793
802
|
* Transform a type to make specific keys conditional based on FieldShape.
|
|
794
803
|
* Keys in ConditionalKeys will only be present when FieldShape extends the specified type.
|
package/dist/future/util.d.ts
CHANGED
|
@@ -13,10 +13,10 @@ export declare function getPathArray<Type>(formValue: Record<string, Type> | nul
|
|
|
13
13
|
*/
|
|
14
14
|
export declare function updatePathValue<Data>(data: Record<string, Data>, name: string, value: Data | Record<string, Data>): Record<string, Data>;
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
* Returns null to remove fields, or updated path with new index.
|
|
16
|
+
* Updates array indices in a field path.
|
|
17
|
+
* Returns null to remove fields, or the updated path with a new index.
|
|
18
18
|
*/
|
|
19
|
-
export declare function
|
|
19
|
+
export declare function updatePathIndex(name: string, listName: string, update: (index: number) => number | null): string | null;
|
|
20
20
|
export declare function resolveSerialize(customSerialize: CustomSerialize | undefined, defaultSerialize: Serialize): Serialize;
|
|
21
21
|
export declare function normalizeValidateResult<ErrorShape, Value>(result: ValidateResult<ErrorShape, Value>): {
|
|
22
22
|
error: FormError<ErrorShape> | null;
|
|
@@ -25,7 +25,7 @@ export declare function normalizeValidateResult<ErrorShape, Value>(result: Valid
|
|
|
25
25
|
/**
|
|
26
26
|
* Handles different validation result formats:
|
|
27
27
|
* - Promise: async validation only
|
|
28
|
-
* -
|
|
28
|
+
* - Staged result: immediate result with a pending result
|
|
29
29
|
* - Object: sync validation only
|
|
30
30
|
*/
|
|
31
31
|
export declare function resolveValidateResult<ErrorShape, Value>(result: ReturnType<ValidateHandler<ErrorShape, Value>>): {
|
|
@@ -59,10 +59,6 @@ export declare function transformKeys<Value>(obj: Record<string, Value>, fn: (ke
|
|
|
59
59
|
* Returns original array if item exists, new array if added.
|
|
60
60
|
*/
|
|
61
61
|
export declare function appendUniqueItem<Item>(list: Array<Item>, item: Item): Item[];
|
|
62
|
-
/**
|
|
63
|
-
* Maps over array and filters out null results.
|
|
64
|
-
*/
|
|
65
|
-
export declare function compactMap<Item>(list: Array<NonNullable<Item>>, fn: (value: Item) => Item | null): Array<Item>;
|
|
66
62
|
export declare function generateUniqueKey(): string;
|
|
67
63
|
/**
|
|
68
64
|
* Creates a type-only marker for TypeScript inference.
|