mirror of
https://github.com/hanzoai/sign.git
synced 2026-10-21 01:21:51 +00:00
The same @hookform/resolvers 5 change, in the dialogs, settings forms, the envelope editor and embedded authoring: `useForm<T>` pinned a form to its schema's output, the resolver no longer matches that, so each form lets the resolver type it, and whatever takes its control or context says input and output — Control<Input, unknown, Output>, UseFormReturn likewise. What the input exposed: - zod 4 types z.preprocess's input as unknown unless the function names it. The distribute dialog's and the settings dialog's emailReplyTo hold a string or nothing, and now say so, as the two flow steps do. - Combobox and ColorPicker already render an unset value as their placeholder and default; their props now allow one. - The embed's signature types and the editor's signers' actionAuth may be unset in the form. The multiselect reads `?? []` and the signer check `?? []`, the schemas' own defaults; every writer sets both, so nothing reachable changes. Co-authored-by: Hanzo Dev <[email protected]>
109 lines
3.4 KiB
TypeScript
109 lines
3.4 KiB
TypeScript
import { useId } from 'react';
|
|
|
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
import { DocumentSigningOrder, type Recipient, RecipientRole } from '@prisma/client';
|
|
import type { UseFormReturn } from 'react-hook-form';
|
|
import { useForm } from 'react-hook-form';
|
|
import { prop, sortBy } from 'remeda';
|
|
import { z } from 'zod';
|
|
|
|
import {
|
|
ZRecipientActionAuthTypesSchema,
|
|
ZRecipientAuthOptionsSchema,
|
|
} from '@hanzo/esign-lib/types/document-auth';
|
|
import type { TEditorEnvelope } from '@hanzo/esign-lib/types/envelope-editor';
|
|
import { ZRecipientEmailSchema } from '@hanzo/esign-lib/types/recipient';
|
|
|
|
const LocalRecipientSchema = z.object({
|
|
formId: z.string().min(1),
|
|
id: z.number().optional(),
|
|
email: ZRecipientEmailSchema,
|
|
name: z.string(),
|
|
role: z.nativeEnum(RecipientRole),
|
|
signingOrder: z.number().optional(),
|
|
actionAuth: z.array(ZRecipientActionAuthTypesSchema).optional().default([]),
|
|
});
|
|
|
|
type TLocalRecipient = z.infer<typeof LocalRecipientSchema>;
|
|
|
|
export const ZEditorRecipientsFormSchema = z.object({
|
|
signers: z.array(LocalRecipientSchema),
|
|
signingOrder: z.nativeEnum(DocumentSigningOrder),
|
|
allowDictateNextSigner: z.boolean().default(false),
|
|
});
|
|
|
|
export type TEditorRecipientsFormSchema = z.infer<typeof ZEditorRecipientsFormSchema>;
|
|
|
|
// What the form holds while it is edited, before the schema fills in its defaults.
|
|
export type TEditorRecipientsFormInput = z.input<typeof ZEditorRecipientsFormSchema>;
|
|
|
|
type EditorRecipientsProps = {
|
|
envelope: TEditorEnvelope;
|
|
};
|
|
|
|
type ResetFormOptions = {
|
|
recipients?: Recipient[];
|
|
documentMeta?: TEditorEnvelope['documentMeta'];
|
|
};
|
|
|
|
type UseEditorRecipientsResponse = {
|
|
form: UseFormReturn<TEditorRecipientsFormInput, unknown, TEditorRecipientsFormSchema>;
|
|
resetForm: (options?: ResetFormOptions) => void;
|
|
};
|
|
|
|
export const useEditorRecipients = ({
|
|
envelope,
|
|
}: EditorRecipientsProps): UseEditorRecipientsResponse => {
|
|
const initialId = useId();
|
|
|
|
const generateDefaultValues = (options?: ResetFormOptions) => {
|
|
const { recipients, documentMeta } = options ?? {};
|
|
|
|
const formRecipients = (recipients || envelope.recipients).map((recipient, index) => ({
|
|
id: recipient.id,
|
|
formId: String(recipient.id),
|
|
name: recipient.name,
|
|
email: recipient.email,
|
|
role: recipient.role,
|
|
signingOrder: recipient.signingOrder ?? index + 1,
|
|
actionAuth: ZRecipientAuthOptionsSchema.parse(recipient.authOptions)?.actionAuth ?? undefined,
|
|
}));
|
|
|
|
const signers: TLocalRecipient[] =
|
|
formRecipients.length > 0
|
|
? sortBy(formRecipients, [prop('signingOrder'), 'asc'], [prop('id'), 'asc'])
|
|
: [
|
|
{
|
|
formId: initialId,
|
|
name: '',
|
|
email: '',
|
|
role: RecipientRole.SIGNER,
|
|
signingOrder: 1,
|
|
actionAuth: [],
|
|
},
|
|
];
|
|
|
|
return {
|
|
signers,
|
|
signingOrder: documentMeta?.signingOrder ?? envelope.documentMeta.signingOrder,
|
|
allowDictateNextSigner:
|
|
documentMeta?.allowDictateNextSigner ?? envelope.documentMeta.allowDictateNextSigner,
|
|
};
|
|
};
|
|
|
|
const form = useForm({
|
|
defaultValues: generateDefaultValues(),
|
|
resolver: zodResolver(ZEditorRecipientsFormSchema),
|
|
mode: 'onChange', // Used for autosave purposes, maybe can try onBlur instead?
|
|
});
|
|
|
|
const resetForm = (options?: ResetFormOptions) => {
|
|
form.reset(generateDefaultValues(options));
|
|
};
|
|
|
|
return {
|
|
form,
|
|
resetForm,
|
|
};
|
|
};
|