Revert "INCOMPLETE: refactor signature pad and input into a single component"

This reverts commit e17e4566cd.
This commit is contained in:
Ephraim Atta-Duncan
2024-01-16 01:17:11 +00:00
parent 0b8e84b6b7
commit 27e5ef0a51
4 changed files with 28 additions and 145 deletions

View File

@ -1,24 +1,19 @@
import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session'; import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session';
import { SigningProvider } from '~/app/(signing)/sign/[token]/provider';
import { ProfileForm } from '~/components/forms/profile'; import { ProfileForm } from '~/components/forms/profile';
export default async function ProfileSettingsPage() { export default async function ProfileSettingsPage() {
const { user } = await getRequiredServerComponentSession(); const { user } = await getRequiredServerComponentSession();
return ( return (
<SigningProvider email={user.email} fullName={user.name} signature={user.signature}> <div>
<div> <h3 className="text-2xl font-semibold">Profile</h3>
<h3 className="text-2xl font-semibold">Profile</h3>
<p className="text-muted-foreground mt-2 text-sm"> <p className="text-muted-foreground mt-2 text-sm">Here you can edit your personal details.</p>
Here you can edit your personal details.
</p>
<hr className="my-4" /> <hr className="my-4" />
<ProfileForm user={user} className="max-w-xl" /> <ProfileForm user={user} className="max-w-xl" />
</div> </div>
</SigningProvider>
); );
} }

View File

@ -17,8 +17,6 @@ import { Label } from '@documenso/ui/primitives/label';
import { SignaturePad } from '@documenso/ui/primitives/signature-pad'; import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
import { useToast } from '@documenso/ui/primitives/use-toast'; import { useToast } from '@documenso/ui/primitives/use-toast';
import { useRequiredSigningContext } from '~/app/(signing)/sign/[token]/provider';
import { FormErrorMessage } from '../form/form-error-message'; import { FormErrorMessage } from '../form/form-error-message';
export const ZProfileFormSchema = z.object({ export const ZProfileFormSchema = z.object({
@ -38,8 +36,6 @@ export const ProfileForm = ({ className, user }: ProfileFormProps) => {
const { toast } = useToast(); const { toast } = useToast();
const { signature, setSignature } = useRequiredSigningContext();
const { const {
register, register,
control, control,
@ -125,8 +121,6 @@ export const ProfileForm = ({ className, user }: ProfileFormProps) => {
containerClassName="rounded-lg border bg-background" containerClassName="rounded-lg border bg-background"
defaultValue={user.signature ?? undefined} defaultValue={user.signature ?? undefined}
onChange={(v) => onChange(v ?? '')} onChange={(v) => onChange(v ?? '')}
signature={signature}
setSignature={setSignature}
/> />
)} )}
/> />

View File

@ -40,19 +40,10 @@ export const insertFieldInPDF = async (pdf: PDFDocument, field: FieldWithSignatu
const fieldX = pageWidth * (Number(field.positionX) / 100); const fieldX = pageWidth * (Number(field.positionX) / 100);
const fieldY = pageHeight * (Number(field.positionY) / 100); const fieldY = pageHeight * (Number(field.positionY) / 100);
// const url = const font = await pdf.embedFont(isSignatureField ? fontCaveat : StandardFonts.Helvetica);
// 'https://fonts.gstatic.com/s/dancingscript/v25/If2cXTr6YS-zF4S-kcSWSVi_sxjsohD9F50Ruu7BMSoHTQ.ttf';
const url = 'https://fonts.gstatic.com/s/caveat/v18/WnznHAc5bAfYB2QRah7pcpNvOx-pjfJ9SII.ttf';
const googleFont = await fetch(url).then(async (res) => res.arrayBuffer());
const font = await pdf.embedFont(isSignatureField ? googleFont : StandardFonts.Helvetica, {
subset: true,
features: { liga: false },
});
if (field.type === FieldType.SIGNATURE || field.type === FieldType.FREE_SIGNATURE) { if (field.type === FieldType.SIGNATURE || field.type === FieldType.FREE_SIGNATURE) {
await pdf.embedFont(googleFont, { subset: true, features: { liga: false } }); await pdf.embedFont(fontCaveat);
} }
const CUSTOM_TEXT = field.customText || field.Signature?.typedSignature || ''; const CUSTOM_TEXT = field.customText || field.Signature?.typedSignature || '';

View File

@ -3,50 +3,27 @@
import type { HTMLAttributes, MouseEvent, PointerEvent, TouchEvent } from 'react'; import type { HTMLAttributes, MouseEvent, PointerEvent, TouchEvent } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react'; import { useEffect, useMemo, useRef, useState } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import type { StrokeOptions } from 'perfect-freehand'; import type { StrokeOptions } from 'perfect-freehand';
import { getStroke } from 'perfect-freehand'; import { getStroke } from 'perfect-freehand';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { cn } from '../../lib/utils'; import { cn } from '../../lib/utils';
import { Input } from '../input';
import { getSvgPathFromStroke } from './helper'; import { getSvgPathFromStroke } from './helper';
import { Point } from './point'; import { Point } from './point';
const DPI = 2; const DPI = 2;
export type SignaturePadProps = Omit<HTMLAttributes<HTMLCanvasElement>, 'onChange'> & { export type SignaturePadProps = Omit<HTMLAttributes<HTMLCanvasElement>, 'onChange'> & {
signature: string | null;
setSignature: (_value: string | null) => void;
onChange?: (_signatureDataUrl: string | null) => void; onChange?: (_signatureDataUrl: string | null) => void;
containerClassName?: string; containerClassName?: string;
clearSignatureClassName?: string; clearSignatureClassName?: string;
onFormSubmit?: (_data: TSigningpadSchema) => void;
}; };
const ZSigningpadSchema = z.union([
z.object({
signatureDataUrl: z.string().min(1),
signatureText: z.null().or(z.string().max(0)),
}),
z.object({
signatureDataUrl: z.null().or(z.string().max(0)),
signatureText: z.string().trim().min(1),
}),
]);
export type TSigningpadSchema = z.infer<typeof ZSigningpadSchema>;
export const SignaturePad = ({ export const SignaturePad = ({
className, className,
containerClassName, containerClassName,
defaultValue, defaultValue,
clearSignatureClassName, clearSignatureClassName,
onFormSubmit,
onChange, onChange,
signature,
setSignature,
...props ...props
}: SignaturePadProps) => { }: SignaturePadProps) => {
const $el = useRef<HTMLCanvasElement>(null); const $el = useRef<HTMLCanvasElement>(null);
@ -54,24 +31,6 @@ export const SignaturePad = ({
const [isPressed, setIsPressed] = useState(false); const [isPressed, setIsPressed] = useState(false);
const [points, setPoints] = useState<Point[]>([]); const [points, setPoints] = useState<Point[]>([]);
const {
register,
handleSubmit,
setValue,
watch,
formState: { isSubmitting },
} = useForm<TSigningpadSchema>({
mode: 'onChange',
defaultValues: {
signatureDataUrl: signature || null,
signatureText: '',
},
resolver: zodResolver(ZSigningpadSchema),
});
// const signatureDataUrl = watch('signatureDataUrl');
const signatureText = watch('signatureText');
const perfectFreehandOptions = useMemo(() => { const perfectFreehandOptions = useMemo(() => {
const size = $el.current ? Math.min($el.current.height, $el.current.width) * 0.03 : 10; const size = $el.current ? Math.min($el.current.height, $el.current.width) * 0.03 : 10;
@ -247,84 +206,28 @@ export const SignaturePad = ({
}, [defaultValue]); }, [defaultValue]);
return ( return (
<form onSubmit={handleSubmit(onFormSubmit ?? (() => undefined))}> <div className={cn('relative block', containerClassName)}>
<div className={cn('relative block', containerClassName)}> <canvas
<div className="flex h-44 items-center justify-center pb-6"> ref={$el}
{!signatureText && signature && ( className={cn('relative block dark:invert', className)}
<canvas style={{ touchAction: 'none' }}
ref={$el} onPointerMove={(event) => onMouseMove(event)}
className={cn('relative block dark:invert', className)} onPointerDown={(event) => onMouseDown(event)}
style={{ touchAction: 'none' }} onPointerUp={(event) => onMouseUp(event)}
onPointerMove={(event) => onMouseMove(event)} onPointerLeave={(event) => onMouseLeave(event)}
onPointerDown={(event) => onMouseDown(event)} onPointerEnter={(event) => onMouseEnter(event)}
onPointerUp={(event) => onMouseUp(event)} {...props}
onPointerLeave={(event) => onMouseLeave(event)} />
onPointerEnter={(event) => onMouseEnter(event)}
{...props}
/>
)}
{signatureText && ( <div className={cn('absolute bottom-4 right-4', clearSignatureClassName)}>
<p <button
className={cn( type="button"
'text-foreground text-4xl font-semibold [font-family:var(--font-caveat)]', className="focus-visible:ring-ring ring-offset-background text-muted-foreground rounded-full p-0 text-xs focus-visible:outline-none focus-visible:ring-2"
)} onClick={() => onClearClick()}
>
{signatureText}
</p>
)}
</div>
<div
className="absolute inset-x-0 bottom-0 flex cursor-auto items-end justify-between px-4 pb-1 pt-2"
onClick={(e) => e.stopPropagation()}
> >
<Input Clear Signature
id="signatureText" </button>
className="text-foreground placeholder:text-muted-foreground border-none bg-transparent p-0 text-sm focus-visible:bg-transparent focus-visible:outline-none focus-visible:ring-0"
placeholder="Draw or type name here"
// disabled={isSubmitting || signature !== null}
disabled={isSubmitting}
{...register('signatureText', {
onChange: (e) => {
if (e.target.value !== '') {
setValue('signatureDataUrl', null);
}
setValue('signatureText', e.target.value);
},
onBlur: (e) => {
if (e.target.value === '') {
return setValue('signatureText', '');
}
setSignature(e.target.value.trimStart());
},
})}
/>
{/* <div className="absolute bottom-3 right-4">
<button
type="button"
className="focus-visible:ring-ring ring-offset-background text-muted-foreground rounded-full p-0 text-xs focus-visible:outline-none focus-visible:ring-2"
onClick={() => console.log('clear')}
>
Clear Signature
</button>
</div> */}
</div>
<div className={cn('absolute bottom-4 right-4', clearSignatureClassName)}>
<button
type="button"
className="focus-visible:ring-ring ring-offset-background text-muted-foreground rounded-full p-0 text-xs focus-visible:outline-none focus-visible:ring-2"
onClick={() => onClearClick()}
>
Clear Signature
</button>
</div>
</div> </div>
</form> </div>
); );
}; };