mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-12 07:09:59 +00:00
feat(studio): full IDE-like file management (#147)
## Summary - **API**: POST (create), DELETE (delete), PATCH (rename/move), POST duplicate endpoints with null-byte sanitization - **FileTree**: right-click context menu with New File, New Folder, Rename, Duplicate, Delete - **Drag-and-drop**: move files between folders with visual feedback and subtree guard - **Inline editing**: rename/create inputs with filename validation - **Header actions**: quick New File / New Folder buttons in the FILES header Stacks on top of `feat/studio-code-quality`. ## Test plan - [x] Right-click file → Rename, Delete, Duplicate all work - [x] Right-click folder → New File, New Folder, Delete work - [x] Drag file from one folder to another - [x] Create file with invalid name (`../foo`, `a/b`) → rejected client-side - [x] Delete currently-edited file → editor clears - [x] Studio build succeeds
This commit is contained in:
@@ -26,6 +26,12 @@ interface LeftSidebarProps {
|
||||
fileTree?: string[];
|
||||
editingFile?: { path: string; content: string | null } | null;
|
||||
onSelectFile?: (path: string) => void;
|
||||
onCreateFile?: (path: string) => void;
|
||||
onCreateFolder?: (path: string) => void;
|
||||
onDeleteFile?: (path: string) => void;
|
||||
onRenameFile?: (oldPath: string, newPath: string) => void;
|
||||
onDuplicateFile?: (path: string) => void;
|
||||
onMoveFile?: (oldPath: string, newPath: string) => void;
|
||||
codeChildren?: ReactNode;
|
||||
onLint?: () => void;
|
||||
linting?: boolean;
|
||||
@@ -42,6 +48,12 @@ export const LeftSidebar = memo(function LeftSidebar({
|
||||
fileTree: fileProp,
|
||||
editingFile,
|
||||
onSelectFile,
|
||||
onCreateFile,
|
||||
onCreateFolder,
|
||||
onDeleteFile,
|
||||
onRenameFile,
|
||||
onDuplicateFile,
|
||||
onMoveFile,
|
||||
codeChildren,
|
||||
onLint,
|
||||
linting,
|
||||
@@ -122,16 +134,28 @@ export const LeftSidebar = memo(function LeftSidebar({
|
||||
/>
|
||||
)}
|
||||
{tab === "assets" && (
|
||||
<AssetsTab projectId={projectId} assets={assets} onImport={onImportFiles} />
|
||||
<AssetsTab
|
||||
projectId={projectId}
|
||||
assets={assets}
|
||||
onImport={onImportFiles}
|
||||
onDelete={onDeleteFile}
|
||||
onRename={onRenameFile}
|
||||
/>
|
||||
)}
|
||||
{tab === "code" && (
|
||||
<div className="flex flex-1 min-h-0">
|
||||
{(fileProp?.length ?? 0) > 0 && (
|
||||
<div className="w-[140px] flex-shrink-0 border-r border-neutral-800 overflow-y-auto">
|
||||
<div className="w-[160px] flex-shrink-0 border-r border-neutral-800 overflow-y-auto">
|
||||
<FileTree
|
||||
files={fileProp ?? []}
|
||||
activeFile={editingFile?.path ?? null}
|
||||
onSelectFile={onSelectFile ?? (() => {})}
|
||||
onCreateFile={onCreateFile}
|
||||
onCreateFolder={onCreateFolder}
|
||||
onDeleteFile={onDeleteFile}
|
||||
onRenameFile={onRenameFile}
|
||||
onDuplicateFile={onDuplicateFile}
|
||||
onMoveFile={onMoveFile}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user