mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-03 17:08:13 +00:00
supress error for process env, added vscode setting to gitignore segrgate enums (#369) Co-authored-by: Christopher Oliphant <RALifeCoach@users.noreply.github.com> Refactor storybook (#370) Co-authored-by: Christopher Oliphant <RALifeCoach@users.noreply.github.com> button dropdown docs (#372) storybook doc for button dropdown component refactor side panel tabs (#371) Co-authored-by: Christopher Oliphant <RALifeCoach@users.noreply.github.com> fix enums (#373) Co-authored-by: Christopher Oliphant <RALifeCoach@users.noreply.github.com> Refactoring Auth Context to Signals (#374) - file restructure, store -> signals - rewrite AuthContext to signals, and get rid of AuthContext - modify all files that need to use AuthContext to use the authentication Signal - the complex login persistency logic is now just a persistLogin function ran at root! - fetchers uses the auth signal directly to get the sessionToken - components no longer useSignals for these fetchers, hence decoupled from the auth signals !! components and fetchers that are definitely subjected to refactor does not receive the useSignal decoupling treatment Co-authored-by: wil <wil@storyteller.ai> Refactoring Toaster Context to a Toaster Component + Signal (#378) - Created the Toaster Component - Created the Toasts Signal - Now no useContext is needed for Toast Poping, nor passing AddToast around - Simply import addToast from the Signals and you can pop a toast from anywhere in the codebase Co-authored-by: wil <wil@storyteller.ai> Refactoring AppUi Context (partial: delete unused, editorLoader becomes signal) (#379) - dialogueTTS is unused, hence deleted - view side-by-side mode is unused, hence deleted - timeline height in this context was already made into signal, hence deleted - editorLoader in this context is now made into a page level signal, hence deleted - components and dispatcher of the editorLoader are modified to use signal instead - app level reducer is no longer used, tugged into context folder to avoid confusion, will be deleted when all attributes in AppUi context is refactored into signals Co-authored-by: wil <wil@storyteller.ai> Refactor control panel (#391) - control panel - simplified and improved - Please also test it. It operates slightly differently. For example, if the user types an invalid character, the character is ignored. --------- Co-authored-by: Christopher Oliphant <RALifeCoach@users.noreply.github.com> Refactoring App Level Components - Components that are in the /app/component folder are split into reusable and signaled - reusable are in theory signal independent - signaled are dependent on signals (and maybe a use-once component) - some app level components has page level enums or signals, those are bumped to app level now - all components in the module directory are moved into the component directories depending on whether it's reusable or signaled - code changes in are mostly just import changes to get re-target to get the correct files - discovered a small bug in FilterButtons and is fixed - whether a component need more work, it is commented on the index file that import them into the grand collection of components Refactor - Signals Part 2 - store is renamed to signals in PageEditor for clarity - ObjectControlPanel now uses a Signal instead of the AppUiContext - Moved EditorContext to Page Level, all context are page level only now - editor is modified to read and use signals directly (for now), this includes: -- the ObjectPanel signal -- the Scene signal -- the Authentication signal - and hence, editor now has a constructor doesn't require any arguments - editor also has a simple initialization - AppUiContext is retired completely and deleted --------- Co-authored-by: wil <wil@storyteller.ai> Co-authored-by: Christopher Oliphant <RALifeCoach@users.noreply.github.com>
98 lines
2.5 KiB
TypeScript
98 lines
2.5 KiB
TypeScript
import React, { ReactNode, useId, useRef, useState } from "react";
|
|
import { AssetType } from "~/enums";
|
|
import { UploadModal } 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]) {
|
|
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)}
|
|
<UploadModal
|
|
closeModal={closeModal}
|
|
file={file!}
|
|
isOpen={modalOpen}
|
|
onClose={clearFile}
|
|
onSuccess={onSuccess}
|
|
resetModal={resetModal}
|
|
setResetModal={setResetModal}
|
|
type={type}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|