Files
sign/packages/ui/primitives/document-dropzone.tsx

185 lines
5.3 KiB
TypeScript
Raw Normal View History

2023-06-09 18:21:18 +10:00
'use client';
import type { Variants } from 'framer-motion';
import { motion } from 'framer-motion';
2023-06-09 18:21:18 +10:00
import { Plus } from 'lucide-react';
import { useDropzone } from 'react-dropzone';
import { megabytesToBytes } from '@documenso/lib/universal/unit-convertions';
import { cn } from '../lib/utils';
import { Card, CardContent } from './card';
2023-06-09 18:21:18 +10:00
const DocumentDropzoneContainerVariants: Variants = {
initial: {
scale: 1,
},
animate: {
scale: 1,
},
hover: {
transition: {
staggerChildren: 0.05,
},
},
};
const DocumentDropzoneCardLeftVariants: Variants = {
initial: {
x: 40,
y: -10,
rotate: -14,
},
animate: {
x: 40,
y: -10,
rotate: -14,
},
hover: {
x: -25,
y: -25,
rotate: -22,
},
};
const DocumentDropzoneCardRightVariants: Variants = {
initial: {
x: -40,
y: -10,
rotate: 14,
},
animate: {
x: -40,
y: -10,
rotate: 14,
},
hover: {
x: 25,
y: -25,
rotate: 22,
},
};
const DocumentDropzoneCardCenterVariants: Variants = {
initial: {
x: 0,
y: 0,
},
animate: {
x: 0,
y: 0,
},
hover: {
x: 0,
y: -25,
},
};
2023-10-06 22:54:24 +00:00
const DocumentDescription = {
document: {
headline: 'Add a document',
},
template: {
headline: 'Upload Template Document',
},
};
2023-06-09 18:21:18 +10:00
export type DocumentDropzoneProps = {
2023-09-20 13:48:30 +10:00
className?: string;
2023-10-15 20:26:32 +11:00
disabled?: boolean;
disabledMessage?: string;
2023-06-09 18:21:18 +10:00
onDrop?: (_file: File) => void | Promise<void>;
2023-10-06 22:54:24 +00:00
type?: 'document' | 'template';
2023-06-09 18:21:18 +10:00
[key: string]: unknown;
};
2023-10-15 20:26:32 +11:00
export const DocumentDropzone = ({
className,
onDrop,
disabled,
disabledMessage = 'You cannot upload documents at this time.',
2023-10-06 22:54:24 +00:00
type = 'document',
2023-10-15 20:26:32 +11:00
...props
}: DocumentDropzoneProps) => {
2023-06-09 18:21:18 +10:00
const { getRootProps, getInputProps } = useDropzone({
accept: {
'application/pdf': ['.pdf'],
},
multiple: false,
2023-10-15 20:26:32 +11:00
disabled,
2023-06-09 18:21:18 +10:00
onDrop: ([acceptedFile]) => {
if (acceptedFile && onDrop) {
2023-08-29 13:01:19 +10:00
void onDrop(acceptedFile);
2023-06-09 18:21:18 +10:00
}
},
maxSize: megabytesToBytes(50),
2023-06-09 18:21:18 +10:00
});
return (
<motion.div
className={cn('flex aria-disabled:cursor-not-allowed', className)}
2023-06-09 18:21:18 +10:00
variants={DocumentDropzoneContainerVariants}
initial="initial"
animate="animate"
whileHover="hover"
aria-disabled={disabled}
2023-06-09 18:21:18 +10:00
>
<Card
role="button"
2023-06-11 01:50:19 -04:00
className={cn(
2023-10-15 20:26:32 +11:00
'focus-visible:ring-ring ring-offset-background flex flex-1 cursor-pointer flex-col items-center justify-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 aria-disabled:pointer-events-none aria-disabled:opacity-60',
2023-06-11 01:50:19 -04:00
className,
)}
2023-06-09 18:21:18 +10:00
gradient={true}
degrees={120}
2023-10-15 20:26:32 +11:00
aria-disabled={disabled}
2023-06-09 18:21:18 +10:00
{...getRootProps()}
{...props}
>
2023-08-01 17:34:17 +10:00
<CardContent className="text-muted-foreground/40 flex flex-col items-center justify-center p-6">
2023-06-09 18:21:18 +10:00
{/* <FilePlus strokeWidth="1px" className="h-16 w-16"/> */}
<div className="flex">
<motion.div
className="border-muted-foreground/20 group-hover:border-documenso/80 dark:bg-muted/80 a z-10 flex aspect-[3/4] w-24 origin-top-right -rotate-[22deg] flex-col gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
variants={!disabled ? DocumentDropzoneCardLeftVariants : undefined}
2023-06-09 18:21:18 +10:00
>
2023-06-11 01:50:19 -04:00
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-5/6 rounded-[2px]" />
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
2023-06-09 18:21:18 +10:00
</motion.div>
<motion.div
2023-08-01 17:34:17 +10:00
className="border-muted-foreground/20 group-hover:border-documenso/80 dark:bg-muted/80 z-20 flex aspect-[3/4] w-24 flex-col items-center justify-center gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
variants={!disabled ? DocumentDropzoneCardCenterVariants : undefined}
2023-06-09 18:21:18 +10:00
>
<Plus
strokeWidth="2px"
2023-06-11 01:50:19 -04:00
className="text-muted-foreground/20 group-hover:text-documenso h-12 w-12"
2023-06-09 18:21:18 +10:00
/>
</motion.div>
<motion.div
2023-08-01 17:34:17 +10:00
className="border-muted-foreground/20 group-hover:border-documenso/80 dark:bg-muted/80 z-10 flex aspect-[3/4] w-24 origin-top-left rotate-[22deg] flex-col gap-y-1 rounded-lg border bg-white/80 px-2 py-4 backdrop-blur-sm"
variants={!disabled ? DocumentDropzoneCardRightVariants : undefined}
2023-06-09 18:21:18 +10:00
>
2023-06-11 01:50:19 -04:00
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-5/6 rounded-[2px]" />
<div className="bg-muted-foreground/20 group-hover:bg-documenso h-2 w-full rounded-[2px]" />
2023-06-09 18:21:18 +10:00
</motion.div>
</div>
<input {...getInputProps()} />
2023-06-11 01:50:19 -04:00
<p className="group-hover:text-foreground text-muted-foreground mt-8 font-medium">
2023-10-06 22:54:24 +00:00
{DocumentDescription[type].headline}
2023-06-11 01:50:19 -04:00
</p>
2023-06-09 18:21:18 +10:00
<p className="text-muted-foreground/80 mt-1 text-sm">
{disabled ? disabledMessage : 'Drag & drop your document here.'}
</p>
2023-06-09 18:21:18 +10:00
</CardContent>
</Card>
</motion.div>
);
};