mirror of
https://github.com/documenso/documenso.git
synced 2025-11-10 20:42:34 +10:00
Revert "INCOMPLETE: refactor signature pad and input into a single component"
This reverts commit e17e4566cd.
This commit is contained in:
@ -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>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -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 || '';
|
||||||
|
|||||||
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user