@conform-to/dom
Version:
A set of opinionated helpers built on top of the Constraint Validation API
204 lines • 7.71 kB
TypeScript
/**
* Construct a form data with the submitter value.
* It utilizes the submitter argument on the FormData constructor from modern browsers
* with fallback to append the submitter value in case it is not unsupported.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/FormData/FormData#parameters
*/
export declare function getFormData(form: HTMLFormElement, submitter?: HTMLInputElement | HTMLButtonElement | null): FormData;
/**
* Returns the paths from a name based on the JS syntax convention
* @example
* ```js
* const paths = getPaths('todos[0].content'); // ['todos', 0, 'content']
* ```
*/
export declare function getPaths(name: string | undefined): Array<string | number>;
/**
* Returns a formatted name from the paths based on the JS syntax convention
* @example
* ```js
* const name = formatPaths(['todos', 0, 'content']); // "todos[0].content"
* ```
*/
export declare function formatPaths(paths: Array<string | number>): string;
/**
* Format based on a prefix and a path
*/
export declare function formatName(prefix: string | undefined, path?: string | number): string;
/**
* Check if a name match the prefix paths
*/
export declare function isPrefix(name: string, prefix: string): boolean;
/**
* Compare the parent and child paths to get the relative paths
* Returns null if the child paths do not start with the parent paths
*/
export declare function getChildPaths(parentNameOrPaths: string | Array<string | number>, childName: string): (string | number)[] | null;
/**
* Assign a value to a target object by following the paths
*/
export declare function setValue(target: Record<string, any>, name: string, valueFn: (currentValue?: unknown) => unknown): void;
/**
* Retrive the value from a target object by following the paths
*/
export declare function getValue(target: unknown, name: string): unknown;
/**
* Check if the value is a plain object
*/
export declare function isPlainObject(obj: unknown): obj is Record<string | number | symbol, unknown>;
type GlobalConstructors = {
[]: (typeof globalThis)[K] extends new (...args: any) => any ? K : never;
}[keyof typeof globalThis];
export declare function isGlobalInstance<ClassName extends GlobalConstructors>(obj: unknown, className: ClassName): obj is InstanceType<(typeof globalThis)[ClassName]>;
/**
* Normalize value by removing empty object or array, empty string and null values
*/
export declare function normalize<Type extends Record<string, unknown>>(value: Type, acceptFile?: boolean): Type | undefined;
export declare function normalize<Type extends Array<unknown>>(value: Type, acceptFile?: boolean): Type | undefined;
export declare function normalize(value: unknown, acceptFile?: boolean): unknown | undefined;
/**
* Flatten a tree into a dictionary
*/
export declare function flatten(data: unknown, options?: {
resolve?: (data: unknown) => unknown;
prefix?: string;
}): Record<string, unknown>;
export declare function deepEqual(left: unknown, right: unknown): boolean;
export type JsonPrimitive = string | number | boolean | null;
/**
* The form value of a submission. This is usually constructed from a FormData or URLSearchParams.
* It may contains JSON primitives if the value is updated based on a form intent.
*/
export type FormValue<Type extends JsonPrimitive | FormDataEntryValue = JsonPrimitive | FormDataEntryValue> = Type | FormValue<Type | null>[] | {
[]: FormValue<Type>;
};
/**
* The data of a form submission.
*/
export type Submission<ValueType extends FormDataEntryValue = FormDataEntryValue> = {
/**
* The form value structured following the naming convention.
*/
value: Record<string, FormValue<ValueType>>;
/**
* The field names that are included in the FormData or URLSearchParams.
*/
fields: string[];
/**
* The intent of the submission. This is usally included by specifying a name and value on a submit button.
*/
intent: string | null;
};
/**
* Parse `FormData` or `URLSearchParams` into a submission object.
* This function structures the form values based on the naming convention.
* It also includes all the field names and the intent if the `intentName` option is provided.
*
* @example
* ```ts
* const formData = new FormData();
*
* formData.append('email', 'test@example.com');
* formData.append('password', 'secret');
*
* parseSubmission(formData)
* // {
* // value: { email: 'test@example.com', password: 'secret' },
* // fields: ['email', 'password'],
* // intent: null,
* // }
*
* // If you have an intent field
* formData.append('intent', 'login');
* parseSubmission(formData, { intentName: 'intent' })
* // {
* // value: { email: 'test@example.com', password: 'secret' },
* // fields: ['email', 'password'],
* // intent: 'login',
* // }
* ```
*/
export declare function parseSubmission(formData: FormData | URLSearchParams, options?: {
/**
* The name of the submit button that triggered the form submission.
* Used to extract the submission's intent.
*/
intentName?: string;
/**
* A filter function that excludes specific entries from being parsed.
* Return `true` to skip the entry.
*/
skipEntry?: (name: string) => boolean;
}): Submission;
export type ParseSubmissionOptions = Required<Parameters<typeof parseSubmission>>[1];
export declare function defaultSerialize(value: unknown): FormDataEntryValue | undefined;
/**
* A utility function that checks whether the current form data differs from the default values.
*
* @see https://conform.guide/api/react/future/isDirty
* @example Enable a submit button only if the form is dirty
*
* ```tsx
* const dirty = useFormData(
* formRef,
* (formData) => isDirty(formData, { defaultValue }) ?? false,
* );
*
* return (
* <button type="submit" disabled={!dirty}>
* Save changes
* </button>
* );
* ```
*/
export declare function isDirty(
/**
* The current form data to compare. It can be:
*
* - A `FormData` object
* - A `URLSearchParams` object
* - A plain object that was parsed from form data (i.e. `submission.payload`)
*/
formData: FormData | URLSearchParams | FormValue<FormDataEntryValue> | null, options?: {
/**
* An object representing the default values of the form to compare against.
* Defaults to an empty object if not provided.
*/
defaultValue?: unknown;
/**
* The name of the submit button that triggered the submission.
* It will be excluded from the dirty comparison.
*/
intentName?: string;
/**
* A function to serialize values in defaultValue before comparing them to the form data.
* If not provided, a default serializer is used that behaves as follows:
*
* - string / File:
* - Returned as-is
* - boolean:
* - true → 'on'
* - false → undefined
* - number / bigint:
* - Converted to string using `.toString()`
* - Date:
* - Converted to ISO string using `.toISOString()`
*/
serialize?: (value: unknown, defaultSerialize: (value: unknown) => FormDataEntryValue | undefined) => FormDataEntryValue | undefined;
/**
* A function to exclude specific fields from the comparison.
* Useful for ignoring hidden inputs like CSRF tokens or internal fields added by frameworks
* (e.g. Next.js uses hidden inputs to support server actions).
*
* @example
* ```ts
* isDirty(formData, {
* skipEntry: (name) => name === 'csrf-token',
* });
* ```
*/
skipEntry?: (name: string) => boolean;
}): boolean | undefined;
export {};
//# sourceMappingURL=formdata.d.ts.map