UNPKG

sirv-uploader-lib

Version:

Reusable React component to upload files to Sirv.com

1 lines 44.4 kB
{"version":3,"sources":["../src/components/file-upload-area.tsx","../src/components/ui/card.tsx","../src/lib/utils.ts","../src/components/ui/button.tsx","../node_modules/@radix-ui/react-slot/src/slot.tsx","../node_modules/@radix-ui/react-compose-refs/src/compose-refs.tsx","../src/components/ui/progress.tsx","../src/components/ui/alert.tsx","../src/components/file-list.tsx","../src/hooks/use-upload-file.ts","../src/lib/sirv-upload.ts","../src/components/sirv-uploader.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { useCallback } from \"react\";\r\nimport { useDropzone } from \"react-dropzone\";\r\nimport { Card, CardContent } from \"./ui/card\";\r\nimport { Upload } from \"lucide-react\";\r\n\r\ninterface FileUploadAreaProps {\r\n onFilesAdded: (files: File[]) => void;\r\n}\r\n\r\nexport function FileUploadArea({ onFilesAdded }: FileUploadAreaProps) {\r\n const onDrop = useCallback(\r\n (acceptedFiles: File[]) => {\r\n onFilesAdded(acceptedFiles);\r\n },\r\n [onFilesAdded]\r\n );\r\n\r\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\r\n onDrop,\r\n accept: {\r\n \"image/*\": [\".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\", \".svg\"],\r\n \"application/pdf\": [\".pdf\"],\r\n \"text/*\": [\".txt\", \".md\", \".csv\"],\r\n \"application/msword\": [\".doc\"],\r\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\":\r\n [\".docx\"],\r\n \"application/vnd.ms-excel\": [\".xls\"],\r\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\": [\r\n \".xlsx\",\r\n ],\r\n },\r\n });\r\n\r\n return (\r\n <Card className=\"mb-6\">\r\n <CardContent className=\"p-6\">\r\n <div\r\n {...getRootProps()}\r\n className={`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${\r\n isDragActive\r\n ? \"border-blue-500 bg-blue-50\"\r\n : \"border-gray-300 hover:border-gray-400\"\r\n }`}\r\n >\r\n <input {...getInputProps()} />\r\n <Upload className=\"mx-auto h-12 w-12 text-gray-400 mb-4\" />\r\n {isDragActive ? (\r\n <p className=\"text-blue-600 font-medium\">Drop the files here...</p>\r\n ) : (\r\n <div>\r\n <p className=\"text-gray-600 font-medium mb-2\">\r\n Drag and drop files here, or click to browse\r\n </p>\r\n <p className=\"text-sm text-gray-500\">\r\n Supports images, PDFs, documents, spreadsheets, and text files\r\n </p>\r\n </div>\r\n )}\r\n </div>\r\n </CardContent>\r\n </Card>\r\n );\r\n}\r\n","import * as React from \"react\";\r\n\r\nimport { cn } from \"../../lib/utils\";\r\n\r\nconst Card = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n className={cn(\r\n \"rounded-lg border bg-card text-card-foreground shadow-sm\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nCard.displayName = \"Card\";\r\n\r\nconst CardHeader = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n className={cn(\"flex flex-col space-y-1.5 p-6\", className)}\r\n {...props}\r\n />\r\n));\r\nCardHeader.displayName = \"CardHeader\";\r\n\r\nconst CardTitle = React.forwardRef<\r\n HTMLParagraphElement,\r\n React.HTMLAttributes<HTMLHeadingElement>\r\n>(({ className, ...props }, ref) => (\r\n <h3\r\n ref={ref}\r\n className={cn(\r\n \"text-2xl font-semibold leading-none tracking-tight\",\r\n className\r\n )}\r\n {...props}\r\n />\r\n));\r\nCardTitle.displayName = \"CardTitle\";\r\n\r\nconst CardDescription = React.forwardRef<\r\n HTMLParagraphElement,\r\n React.HTMLAttributes<HTMLParagraphElement>\r\n>(({ className, ...props }, ref) => (\r\n <p\r\n ref={ref}\r\n className={cn(\"text-sm text-muted-foreground\", className)}\r\n {...props}\r\n />\r\n));\r\nCardDescription.displayName = \"CardDescription\";\r\n\r\nconst CardContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, ...props }, ref) => (\r\n <div ref={ref} className={cn(\"p-6 pt-0\", className)} {...props} />\r\n));\r\nCardContent.displayName = \"CardContent\";\r\n\r\nconst CardFooter = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n className={cn(\"flex items-center p-6 pt-0\", className)}\r\n {...props}\r\n />\r\n));\r\nCardFooter.displayName = \"CardFooter\";\r\n\r\nexport {\r\n Card,\r\n CardHeader,\r\n CardFooter,\r\n CardTitle,\r\n CardDescription,\r\n CardContent,\r\n};\r\n","import { type ClassValue, clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n\r\nexport function formatFileSize(bytes: number): string {\r\n if (bytes === 0) return \"0 Bytes\";\r\n const k = 1024;\r\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\"];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + \" \" + sizes[i];\r\n}\r\n","import * as React from \"react\";\r\nimport { Slot } from \"@radix-ui/react-slot\";\r\nimport { cva, type VariantProps } from \"class-variance-authority\";\r\n\r\nimport { cn } from \"../../lib/utils\";\r\n\r\nconst buttonVariants = cva(\r\n \"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\r\n destructive:\r\n \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\r\n outline:\r\n \"border border-input bg-background hover:bg-accent hover:text-accent-foreground\",\r\n secondary:\r\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\r\n ghost: \"hover:bg-accent hover:text-accent-foreground\",\r\n link: \"text-primary underline-offset-4 hover:underline\",\r\n },\r\n size: {\r\n default: \"h-10 px-4 py-2\",\r\n sm: \"h-9 rounded-md px-3\",\r\n lg: \"h-11 rounded-md px-8\",\r\n icon: \"h-10 w-10\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n size: \"default\",\r\n },\r\n }\r\n);\r\n\r\nexport interface ButtonProps\r\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\r\n VariantProps<typeof buttonVariants> {\r\n asChild?: boolean;\r\n}\r\n\r\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\r\n ({ className, variant, size, asChild = false, ...props }, ref) => {\r\n const Comp = asChild ? Slot : \"button\";\r\n return (\r\n <Comp\r\n className={cn(buttonVariants({ variant, size, className }))}\r\n ref={ref}\r\n {...props}\r\n />\r\n );\r\n }\r\n);\r\nButton.displayName = \"Button\";\r\n\r\nexport { Button, buttonVariants };\r\n","import * as React from 'react';\nimport { composeRefs } from '@radix-ui/react-compose-refs';\n\n/* -------------------------------------------------------------------------------------------------\n * Slot\n * -----------------------------------------------------------------------------------------------*/\n\ninterface SlotProps extends React.HTMLAttributes<HTMLElement> {\n children?: React.ReactNode;\n}\n\n/* @__NO_SIDE_EFFECTS__ */ export function createSlot(ownerName: string) {\n const SlotClone = createSlotClone(ownerName);\n const Slot = React.forwardRef<HTMLElement, SlotProps>((props, forwardedRef) => {\n const { children, ...slotProps } = props;\n const childrenArray = React.Children.toArray(children);\n const slottable = childrenArray.find(isSlottable);\n\n if (slottable) {\n // the new element to render is the one passed as a child of `Slottable`\n const newElement = slottable.props.children;\n\n const newChildren = childrenArray.map((child) => {\n if (child === slottable) {\n // because the new element will be the one rendered, we are only interested\n // in grabbing its children (`newElement.props.children`)\n if (React.Children.count(newElement) > 1) return React.Children.only(null);\n return React.isValidElement(newElement)\n ? (newElement.props as { children: React.ReactNode }).children\n : null;\n } else {\n return child;\n }\n });\n\n return (\n <SlotClone {...slotProps} ref={forwardedRef}>\n {React.isValidElement(newElement)\n ? React.cloneElement(newElement, undefined, newChildren)\n : null}\n </SlotClone>\n );\n }\n\n return (\n <SlotClone {...slotProps} ref={forwardedRef}>\n {children}\n </SlotClone>\n );\n });\n\n Slot.displayName = `${ownerName}.Slot`;\n return Slot;\n}\n\nconst Slot = createSlot('Slot');\n\n/* -------------------------------------------------------------------------------------------------\n * SlotClone\n * -----------------------------------------------------------------------------------------------*/\n\ninterface SlotCloneProps {\n children: React.ReactNode;\n}\n\n/* @__NO_SIDE_EFFECTS__ */ function createSlotClone(ownerName: string) {\n const SlotClone = React.forwardRef<any, SlotCloneProps>((props, forwardedRef) => {\n const { children, ...slotProps } = props;\n\n if (React.isValidElement(children)) {\n const childrenRef = getElementRef(children);\n const props = mergeProps(slotProps, children.props as AnyProps);\n // do not pass ref to React.Fragment for React 19 compatibility\n if (children.type !== React.Fragment) {\n props.ref = forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef;\n }\n return React.cloneElement(children, props);\n }\n\n return React.Children.count(children) > 1 ? React.Children.only(null) : null;\n });\n\n SlotClone.displayName = `${ownerName}.SlotClone`;\n return SlotClone;\n}\n\n/* -------------------------------------------------------------------------------------------------\n * Slottable\n * -----------------------------------------------------------------------------------------------*/\n\nconst SLOTTABLE_IDENTIFIER = Symbol('radix.slottable');\n\ninterface SlottableProps {\n children: React.ReactNode;\n}\n\ninterface SlottableComponent extends React.FC<SlottableProps> {\n __radixId: symbol;\n}\n\n/* @__NO_SIDE_EFFECTS__ */ export function createSlottable(ownerName: string) {\n const Slottable: SlottableComponent = ({ children }) => {\n return <>{children}</>;\n };\n Slottable.displayName = `${ownerName}.Slottable`;\n Slottable.__radixId = SLOTTABLE_IDENTIFIER;\n return Slottable;\n}\n\nconst Slottable = createSlottable('Slottable');\n\n/* ---------------------------------------------------------------------------------------------- */\n\ntype AnyProps = Record<string, any>;\n\nfunction isSlottable(\n child: React.ReactNode\n): child is React.ReactElement<SlottableProps, typeof Slottable> {\n return (\n React.isValidElement(child) &&\n typeof child.type === 'function' &&\n '__radixId' in child.type &&\n child.type.__radixId === SLOTTABLE_IDENTIFIER\n );\n}\n\nfunction mergeProps(slotProps: AnyProps, childProps: AnyProps) {\n // all child props should override\n const overrideProps = { ...childProps };\n\n for (const propName in childProps) {\n const slotPropValue = slotProps[propName];\n const childPropValue = childProps[propName];\n\n const isHandler = /^on[A-Z]/.test(propName);\n if (isHandler) {\n // if the handler exists on both, we compose them\n if (slotPropValue && childPropValue) {\n overrideProps[propName] = (...args: unknown[]) => {\n const result = childPropValue(...args);\n slotPropValue(...args);\n return result;\n };\n }\n // but if it exists only on the slot, we use only this one\n else if (slotPropValue) {\n overrideProps[propName] = slotPropValue;\n }\n }\n // if it's `style`, we merge them\n else if (propName === 'style') {\n overrideProps[propName] = { ...slotPropValue, ...childPropValue };\n } else if (propName === 'className') {\n overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(' ');\n }\n }\n\n return { ...slotProps, ...overrideProps };\n}\n\n// Before React 19 accessing `element.props.ref` will throw a warning and suggest using `element.ref`\n// After React 19 accessing `element.ref` does the opposite.\n// https://github.com/facebook/react/pull/28348\n//\n// Access the ref using the method that doesn't yield a warning.\nfunction getElementRef(element: React.ReactElement) {\n // React <=18 in DEV\n let getter = Object.getOwnPropertyDescriptor(element.props, 'ref')?.get;\n let mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;\n if (mayWarn) {\n return (element as any).ref;\n }\n\n // React 19 in DEV\n getter = Object.getOwnPropertyDescriptor(element, 'ref')?.get;\n mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;\n if (mayWarn) {\n return (element.props as { ref?: React.Ref<unknown> }).ref;\n }\n\n // Not DEV\n return (element.props as { ref?: React.Ref<unknown> }).ref || (element as any).ref;\n}\n\nexport {\n Slot,\n Slottable,\n //\n Slot as Root,\n};\nexport type { SlotProps };\n","import * as React from 'react';\n\ntype PossibleRef<T> = React.Ref<T> | undefined;\n\n/**\n * Set a given ref to a given value\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nfunction setRef<T>(ref: PossibleRef<T>, value: T) {\n if (typeof ref === 'function') {\n return ref(value);\n } else if (ref !== null && ref !== undefined) {\n ref.current = value;\n }\n}\n\n/**\n * A utility to compose multiple refs together\n * Accepts callback refs and RefObject(s)\n */\nfunction composeRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n return (node) => {\n let hasCleanup = false;\n const cleanups = refs.map((ref) => {\n const cleanup = setRef(ref, node);\n if (!hasCleanup && typeof cleanup == 'function') {\n hasCleanup = true;\n }\n return cleanup;\n });\n\n // React <19 will log an error to the console if a callback ref returns a\n // value. We don't use ref cleanups internally so this will only happen if a\n // user's ref callback returns a value, which we only expect if they are\n // using the cleanup functionality added in React 19.\n if (hasCleanup) {\n return () => {\n for (let i = 0; i < cleanups.length; i++) {\n const cleanup = cleanups[i];\n if (typeof cleanup == 'function') {\n cleanup();\n } else {\n setRef(refs[i], null);\n }\n }\n };\n }\n };\n}\n\n/**\n * A custom hook that composes multiple refs\n * Accepts callback refs and RefObject(s)\n */\nfunction useComposedRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return React.useCallback(composeRefs(...refs), refs);\n}\n\nexport { composeRefs, useComposedRefs };\n","import * as React from \"react\";\r\nimport * as ProgressPrimitive from \"@radix-ui/react-progress\";\r\n\r\nimport { cn } from \"../../lib/utils\";\r\n\r\nconst Progress = React.forwardRef<\r\n React.ElementRef<typeof ProgressPrimitive.Root>,\r\n React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\r\n>(({ className, value, ...props }, ref) => (\r\n <ProgressPrimitive.Root\r\n ref={ref}\r\n className={cn(\r\n \"relative h-4 w-full overflow-hidden rounded-full bg-secondary\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <ProgressPrimitive.Indicator\r\n className=\"h-full w-full flex-1 bg-primary transition-all\"\r\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\r\n />\r\n </ProgressPrimitive.Root>\r\n));\r\nProgress.displayName = ProgressPrimitive.Root.displayName;\r\n\r\nexport { Progress };\r\n","import * as React from \"react\";\r\nimport { cva, type VariantProps } from \"class-variance-authority\";\r\n\r\nimport { cn } from \"../../lib/utils\";\r\n\r\nconst alertVariants = cva(\r\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"bg-background text-foreground\",\r\n destructive:\r\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n }\r\n);\r\n\r\nconst Alert = React.forwardRef<\r\n HTMLDivElement,\r\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\r\n>(({ className, variant, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n role=\"alert\"\r\n className={cn(alertVariants({ variant }), className)}\r\n {...props}\r\n />\r\n));\r\nAlert.displayName = \"Alert\";\r\n\r\nconst AlertTitle = React.forwardRef<\r\n HTMLParagraphElement,\r\n React.HTMLAttributes<HTMLHeadingElement>\r\n>(({ className, ...props }, ref) => (\r\n <h5\r\n ref={ref}\r\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\r\n {...props}\r\n />\r\n));\r\nAlertTitle.displayName = \"AlertTitle\";\r\n\r\nconst AlertDescription = React.forwardRef<\r\n HTMLParagraphElement,\r\n React.HTMLAttributes<HTMLParagraphElement>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\r\n {...props}\r\n />\r\n));\r\nAlertDescription.displayName = \"AlertDescription\";\r\n\r\nexport { Alert, AlertTitle, AlertDescription };\r\n","\"use client\";\r\n\r\nimport { Button } from \"./ui/button\";\r\nimport {\r\n Card,\r\n CardContent,\r\n CardDescription,\r\n CardHeader,\r\n CardTitle,\r\n} from \"./ui/card\";\r\nimport { Progress } from \"./ui/progress\";\r\nimport { Alert, AlertDescription } from \"./ui/alert\";\r\nimport { Upload, File, CheckCircle, XCircle, Loader2 } from \"lucide-react\";\r\nimport { UploadFile } from \"../types/upload\";\r\nimport { formatFileSize } from \"../lib/utils\";\r\n\r\ninterface FileListProps {\r\n files: UploadFile[];\r\n onUploadFile: (file: UploadFile) => void;\r\n onUploadAll: () => void;\r\n onRemoveFile: (id: string) => void;\r\n onClearAll: () => void;\r\n}\r\n\r\nexport function FileList({\r\n files,\r\n onUploadFile,\r\n onUploadAll,\r\n onRemoveFile,\r\n onClearAll,\r\n}: FileListProps) {\r\n const getStatusIcon = (status: UploadFile[\"status\"]) => {\r\n switch (status) {\r\n case \"uploading\":\r\n return <Loader2 className=\"h-4 w-4 animate-spin text-blue-500\" />;\r\n case \"deleting\":\r\n return <Loader2 className=\"h-4 w-4 animate-spin text-red-500\" />;\r\n case \"success\":\r\n return <CheckCircle className=\"h-4 w-4 text-green-500\" />;\r\n case \"error\":\r\n return <XCircle className=\"h-4 w-4 text-red-500\" />;\r\n default:\r\n return <File className=\"h-4 w-4 text-gray-500\" />;\r\n }\r\n };\r\n\r\n const pendingFiles = files.filter((f) => f.status === \"pending\");\r\n\r\n return (\r\n <Card className=\"mb-6\">\r\n <CardHeader className=\"flex flex-row items-center justify-between\">\r\n <div>\r\n <CardTitle>Files to Upload ({files.length})</CardTitle>\r\n <CardDescription>\r\n Review and upload your selected files\r\n </CardDescription>\r\n </div>\r\n <div className=\"flex gap-2\">\r\n <Button\r\n onClick={onUploadAll}\r\n disabled={pendingFiles.length === 0}\r\n className=\"flex items-center gap-2\"\r\n >\r\n <Upload className=\"h-4 w-4\" />\r\n Upload All ({pendingFiles.length})\r\n </Button>\r\n <Button variant=\"outline\" onClick={onClearAll}>\r\n Clear All\r\n </Button>\r\n </div>\r\n </CardHeader>\r\n <CardContent>\r\n <div className=\"space-y-3\">\r\n {files.map((uploadFile) => (\r\n <div\r\n key={uploadFile.id}\r\n className=\"flex items-center gap-3 p-3 border rounded-lg\"\r\n >\r\n {getStatusIcon(uploadFile.status)}\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"text-sm font-medium text-gray-900 truncate\">\r\n {uploadFile.file.name}\r\n </p>\r\n <p className=\"text-xs text-gray-500\">\r\n {formatFileSize(uploadFile.file.size)} •{\" \"}\r\n {uploadFile.file.type || \"Unknown type\"}\r\n </p>\r\n {uploadFile.status === \"uploading\" && (\r\n <Progress value={uploadFile.progress} className=\"mt-2 h-2\" />\r\n )}\r\n {uploadFile.status === \"error\" && uploadFile.error && (\r\n <Alert className=\"mt-2\">\r\n <XCircle className=\"h-4 w-4\" />\r\n <AlertDescription className=\"text-xs\">\r\n {uploadFile.error}\r\n </AlertDescription>\r\n </Alert>\r\n )}\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n {uploadFile.status === \"pending\" && (\r\n <Button size=\"sm\" onClick={() => onUploadFile(uploadFile)}>\r\n Upload\r\n </Button>\r\n )}\r\n <Button\r\n size=\"sm\"\r\n variant=\"outline\"\r\n disabled={\r\n uploadFile.status === \"deleting\" ||\r\n uploadFile.status === \"uploading\"\r\n }\r\n onClick={() => onRemoveFile(uploadFile.id)}\r\n >\r\n {uploadFile.status === \"deleting\" ? \"Removing...\" : \"Remove\"}\r\n </Button>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </CardContent>\r\n </Card>\r\n );\r\n}\r\n","\"use client\";\r\n\r\nimport { useState, useCallback } from \"react\";\r\nimport { UploadFile } from \"../types/upload\";\r\nimport { uploadToSirvWithProgress, deleteFromSirv } from \"../lib/sirv-upload\";\r\n\r\ninterface UseFileUploadParams {\r\n uploadPath: string;\r\n clientId: string;\r\n clientSecret: string;\r\n}\r\n\r\nexport function useFileUpload({\r\n uploadPath,\r\n clientId,\r\n clientSecret,\r\n}: UseFileUploadParams) {\r\n const [files, setFiles] = useState<UploadFile[]>([]);\r\n\r\n const addFiles = useCallback((newFiles: File[]) => {\r\n const uploadFiles: UploadFile[] = newFiles.map((file) => ({\r\n file,\r\n id: Math.random().toString(36).substr(2, 9),\r\n status: \"pending\",\r\n progress: 0,\r\n }));\r\n setFiles((prev) => [...prev, ...uploadFiles]);\r\n }, []);\r\n\r\n const uploadFile = useCallback(\r\n async (uploadFile: UploadFile) => {\r\n setFiles((prev) =>\r\n prev.map((f) =>\r\n f.id === uploadFile.id\r\n ? { ...f, status: \"uploading\", progress: 0 }\r\n : f\r\n )\r\n );\r\n\r\n try {\r\n await uploadToSirvWithProgress(\r\n uploadFile.file,\r\n uploadPath,\r\n (progress) => {\r\n setFiles((prev) =>\r\n prev.map((f) => (f.id === uploadFile.id ? { ...f, progress } : f))\r\n );\r\n },\r\n clientId,\r\n clientSecret\r\n );\r\n\r\n setFiles((prev) =>\r\n prev.map((f) =>\r\n f.id === uploadFile.id\r\n ? { ...f, status: \"success\", progress: 100 }\r\n : f\r\n )\r\n );\r\n } catch (error) {\r\n setFiles((prev) =>\r\n prev.map((f) =>\r\n f.id === uploadFile.id\r\n ? {\r\n ...f,\r\n status: \"error\",\r\n error:\r\n error instanceof Error ? error.message : \"Upload failed\",\r\n }\r\n : f\r\n )\r\n );\r\n }\r\n },\r\n [uploadPath, clientId, clientSecret]\r\n );\r\n\r\n const uploadAllFiles = useCallback(() => {\r\n files.filter((f) => f.status === \"pending\").forEach(uploadFile);\r\n }, [files, uploadFile]);\r\n\r\n const removeFile = useCallback(\r\n async (id: string) => {\r\n const target = files.find((f) => f.id === id);\r\n if (!target) return;\r\n\r\n if (target.status !== \"success\") {\r\n setFiles((prev) => prev.filter((f) => f.id !== id));\r\n return;\r\n }\r\n\r\n setFiles((prev) =>\r\n prev.map((f) => (f.id === id ? { ...f, status: \"deleting\" } : f))\r\n );\r\n\r\n try {\r\n await deleteFromSirv(\r\n uploadPath,\r\n target.file.name,\r\n clientId,\r\n clientSecret\r\n );\r\n setFiles((prev) => prev.filter((f) => f.id !== id));\r\n } catch (e) {\r\n const msg = e instanceof Error ? e.message : \"Delete failed\";\r\n setFiles((prev) =>\r\n prev.map((f) =>\r\n f.id === id ? { ...f, status: \"error\", error: msg } : f\r\n )\r\n );\r\n }\r\n },\r\n [files, uploadPath, clientId, clientSecret]\r\n );\r\n\r\n const clearAllFiles = useCallback(() => {\r\n setFiles([]);\r\n }, []);\r\n\r\n return {\r\n files,\r\n addFiles,\r\n uploadFile,\r\n uploadAllFiles,\r\n removeFile,\r\n clearAllFiles,\r\n };\r\n}\r\n","export async function uploadToSirvWithProgress(\r\n file: File,\r\n uploadPath: string,\r\n onProgress: (progress: number) => void,\r\n clientId: string,\r\n clientSecret: string\r\n) {\r\n const authRes = await fetch(\"https://api.sirv.com/v2/token\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\", Accept: \"application/json\" },\r\n body: JSON.stringify({ clientId, clientSecret }),\r\n });\r\n if (!authRes.ok) {\r\n throw new Error(\r\n `Token request failed (${authRes.status}): ${await authRes.text()}`\r\n );\r\n }\r\n\r\n const { token } = await authRes.json();\r\n if (!token) throw new Error(\"Sirv did not return a token.\");\r\n\r\n const safePath = uploadPath.endsWith(\"/\") ? uploadPath : `${uploadPath}/`;\r\n const url = `https://api.sirv.com/v2/files/upload?filename=${encodeURIComponent(\r\n `${safePath}${file.name}`\r\n )}`;\r\n\r\n const xhr = new XMLHttpRequest();\r\n const promise = new Promise<void>((resolve, reject) => {\r\n xhr.upload.onprogress = (e) => {\r\n if (e.lengthComputable && e.total > 0)\r\n onProgress(Math.round((e.loaded / e.total) * 100));\r\n };\r\n xhr.onload = () =>\r\n xhr.status >= 200 && xhr.status < 300\r\n ? (onProgress(100), resolve())\r\n : reject(\r\n new Error(`Upload failed (${xhr.status}): ${xhr.responseText}`)\r\n );\r\n xhr.onerror = () => reject(new Error(\"Network error during upload\"));\r\n });\r\n\r\n xhr.open(\"POST\", url);\r\n xhr.setRequestHeader(\"Authorization\", `Bearer ${token}`);\r\n // Optional: xhr.setRequestHeader(\"Content-Type\", file.type || \"application/octet-stream\");\r\n xhr.send(file);\r\n\r\n return promise;\r\n}\r\n\r\nexport async function deleteFromSirv(\r\n uploadPath: string,\r\n fileName: string,\r\n clientId: string,\r\n clientSecret: string\r\n): Promise<void> {\r\n const authRes = await fetch(\"https://api.sirv.com/v2/token\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\", Accept: \"application/json\" },\r\n body: JSON.stringify({ clientId, clientSecret }),\r\n });\r\n if (!authRes.ok) {\r\n throw new Error(\r\n `Token request failed (${authRes.status}): ${await authRes.text()}`\r\n );\r\n }\r\n const { token } = await authRes.json();\r\n if (!token) throw new Error(\"Sirv did not return a token.\");\r\n\r\n const safePath = uploadPath.endsWith(\"/\") ? uploadPath : `${uploadPath}/`;\r\n const encoded = encodeURIComponent(`${safePath}${fileName}`);\r\n\r\n const delRes = await fetch(\r\n `https://api.sirv.com/v2/files/delete?filename=${encoded}`,\r\n {\r\n method: \"POST\",\r\n headers: {\r\n \"content-type\": \"application/json\",\r\n authorization: `Bearer ${token}`,\r\n },\r\n }\r\n );\r\n\r\n if (!delRes.ok) {\r\n const text = await delRes.text();\r\n throw new Error(\r\n `Delete failed (${delRes.status}): ${text || \"Unknown error\"}`\r\n );\r\n }\r\n}\r\n","\"use client\";\r\n\r\nimport { FileUploadArea } from \"./file-upload-area\";\r\nimport { FileList } from \"./file-list\";\r\nimport { useFileUpload } from \"../hooks/use-upload-file\";\r\n\r\ninterface SirvUploaderProps {\r\n uploadPath: string;\r\n clientId: string;\r\n clientSecret: string;\r\n}\r\n\r\nexport default function SirvUploader({\r\n uploadPath,\r\n clientId,\r\n clientSecret,\r\n}: SirvUploaderProps) {\r\n const {\r\n files,\r\n addFiles,\r\n uploadFile,\r\n uploadAllFiles,\r\n removeFile,\r\n clearAllFiles,\r\n } = useFileUpload({ uploadPath, clientId, clientSecret });\r\n\r\n return (\r\n <div className=\"min-h-screen bg-gray-50 py-8\">\r\n <div className=\"container mx-auto px-4 max-w-4xl\">\r\n <FileUploadArea onFilesAdded={addFiles} />\r\n {files.length > 0 && (\r\n <FileList\r\n files={files}\r\n onUploadFile={uploadFile}\r\n onUploadAll={uploadAllFiles}\r\n onRemoveFile={removeFile}\r\n onClearAll={clearAllFiles}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n"],"mappings":"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","names":["jsx","React","React","React","Fragment","jsx","Slot","props","jsx","React","jsx","React","cva","jsx","cva","Upload","jsx","jsxs","Upload","useCallback","useCallback","uploadFile","jsx","jsxs"]}