import { query, Synnax as Client } from '@synnaxlabs/client'; import { CrudeTimeSpan, destructor } from '@synnaxlabs/x'; import { z } from 'zod'; import { Result } from './result'; import { RetrieveParams } from './suspend'; import { UpdateParams } from './update'; import { Form } from '../form'; export interface FormUpdateParams> extends Omit>, "data" | "onChange" | "onOptimisticComplete">, Omit, "setStatus"> { } /** Client and query handles for a form operation. */ interface FormClientParams { client: Client; query: Query | null; } export interface CreateFormParams> { name: string; schema: Schema; initialValues: z.infer; /** * Fetches the record's form values. Omit for a form that never reads. The * hook suspends on this, so the form is built from real values rather than * from a placeholder the fetch overwrites. */ retrieve?: (params: RetrieveParams) => Promise>; /** * Projects the record's form values out of the domain client's cache. * A hit resolves the read synchronously, with no fetch and no suspension. */ getCached?: (params: RetrieveParams) => z.infer | undefined; update: (params: FormUpdateParams) => Promise; mountListeners?: (params: FormMountListenersParams) => destructor.Destructor | destructor.Destructor[]; /** * Canonicalizes the caller's query before anything reads it: `retrieve`, * `mountListeners`, and `getCached` all receive the one normalized, * identity-stable object. Merge defaults here instead of at each callback, * where a per-call spread would mint a fresh object and miss the client's * query memos. Must preserve fields it does not set. */ normalizeQuery?: (query: Q) => Q; } export type UseFormReturn> = Omit>, "data"> & { form: Form.UseReturn; save: (opts?: query.FetchOptions) => void; /** Like save, but resolves true once the update has been persisted. */ saveAsync: (opts?: query.FetchOptions) => Promise; }; export interface FormBeforeSaveParams> extends Form.UseReturn, FormClientParams { } interface FormMountListenersParams> extends Form.UseReturn, Omit, "query"> { query: Query; /** * Drops the pending autosave, aborts one already running, and stops further ones. * Call when the record no longer exists: a save queued before a delete would * otherwise write it back. */ abandon: () => void; } export interface AfterSaveParams> extends FormBeforeSaveParams { } export interface BeforeValidateParams> extends FormBeforeSaveParams { } export interface UseFormParams> extends Pick, "sync" | "onHasTouched" | "mode"> { initialValues?: z.infer; autoSave?: boolean; /** * How long to wait after a change before autosaving. Raise it for a form with a * continuous input, such as a drag handle or a color picker, where one gesture * emits a burst of changes. Zero saves on every change. */ autoSaveDebounce?: CrudeTimeSpan; /** The record to edit, or null for a form with nothing to read. */ query: Query | null; beforeValidate?: (params: BeforeValidateParams) => boolean | void; beforeSave?: (params: FormBeforeSaveParams) => Promise; afterSave?: (params: AfterSaveParams) => void; } export interface UseForm> { (params: UseFormParams): UseFormReturn; } export declare const createForm: >({ name, schema, retrieve, getCached, mountListeners, update, initialValues: baseInitialValues, normalizeQuery, }: CreateFormParams) => UseForm; export {}; //# sourceMappingURL=form.d.ts.map