Files
artcraft/app/components/reusable/FileWrapper/FileWrapper.tsx
T
wilandwil a8d0541c31 Feature/ Sets Tab; Fixes/ Tabs Improvements (#578)
Tabs Improvements:
- refactor tabs so no more race condition revolving unneccessary signals
- clean up signals
- refactor upload modal movement to be non-signaled and generalized for
more files types
- better naming for files and components, better error handling, eslint
type any fix
- upload file screen can use less state rerenders and better error
messages

Object Uploader
- adapt the old object upload modal with 3d object preview into the
updated best version of upload modal
- preview loader code improvements, better flow and organization

Sets Tab:
- create a set tab, it currently show objects
- hide it behind a FeatureFlag

---------

Co-authored-by: wil <wil@storyteller.ai>
2024-07-07 21:19:07 -04:00

99 lines
2.6 KiB
TypeScript

import React, { ReactNode, useId, useRef, useState } from "react";
import { AssetType } from "~/enums";
import { UploadModalObject } from "~/components";
import { twMerge } from "tailwind-merge";
interface Props {
render: (parentId: string) => ReactNode;
fileTypes?: string[];
onChange?: (file?: React.ChangeEvent) => void;
onSuccess: () => void;
panelClass?: string;
type: AssetType;
}
export function FileWrapper({
render,
fileTypes = [],
onSuccess,
type,
...rest
}: Props) {
const fileRef = useRef<HTMLInputElement>(null);
const [file, setFile] = useState<File | undefined>();
const [modalOpen, setModalOpen] = useState(false);
const [resetModal, setResetModal] = useState(false);
const [dragging, setDragging] = useState(false);
const id = "file-input-" + useId();
const accept = fileTypes
.map((fileType) => `.${fileType.toLowerCase()}`)
.join(",");
const clearFile = () => {
if (fileRef.current !== null) {
fileRef.current.value = "";
setFile(undefined);
}
};
const closeModal = () => setModalOpen(false);
const fileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setResetModal(true);
event.preventDefault();
setFile(event.target?.files?.[0]);
setModalOpen(true);
};
const onDragDrop = (e: React.DragEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
};
const onDragEvent =
(onOff: boolean) =>
(event: React.DragEvent<HTMLDivElement>): void => {
setDragging(onOff);
onDragDrop(event);
};
const onDrop = (event: React.DragEvent<HTMLDivElement>): void => {
setDragging(false);
onDragDrop(event);
if (event.dataTransfer.files && event.dataTransfer.files[0]) {
setResetModal(true);
setFile(event.dataTransfer.files[0]);
setModalOpen(true);
}
};
return (
<div
className={twMerge(
"flex h-full flex-col gap-3.5 overflow-y-auto",
dragging ? "border-white/33 border bg-ui-controls-button" : "",
)}
onDragLeave={onDragEvent(false)}
onDragOver={onDragEvent(true)}
onDrop={onDrop}
>
<input
accept={accept}
className="absolute hidden h-0 w-0"
onChange={fileChange}
type="file"
id={id}
ref={fileRef}
{...rest}
/>
{render(id)}
<UploadModalObject
closeModal={closeModal}
file={file!}
isOpen={modalOpen}
onClose={clearFile}
onSuccess={onSuccess}
resetModal={resetModal}
setResetModal={setResetModal}
type={type}
/>
</div>
);
}