Improve file browser thing

This commit is contained in:
kolaflash
2025-12-15 23:36:56 +01:00
parent 448d203c74
commit 897c414b44
2 changed files with 76 additions and 87 deletions
+56 -57
View File
@@ -2,74 +2,73 @@ import "./FileBrowser.css";
import { type Component, createSignal, Index, Show } from "solid-js"; import { type Component, createSignal, Index, Show } from "solid-js";
import { FileIcon, FolderIcon, FolderOpenIcon } from "./icons/index.ts"; import { FileIcon, FolderIcon, FolderOpenIcon } from "./icons/index.ts";
export type BrowserFile = { path: string }; export type BrowserFolder = Map<string, string | BrowserFolder>;
export type BrowserFolder = Map<string, BrowserFile | BrowserFolder>; export type FileHandler = (path: string) => void;
function isFolder(entry: BrowserFile | BrowserFolder): entry is BrowserFolder { function isFolder(entry: string | BrowserFolder): entry is BrowserFolder {
return typeof (entry as BrowserFolder).size === "number"; return typeof (entry as BrowserFolder).size === "number";
} }
const FileEntry: Component<{ name: string; file: BrowserFile }> = ({ export const FileBrowser: Component<{
name, root: BrowserFolder;
file, handler: FileHandler;
}) => { }> = ({ root, handler }) => {
return ( const FileEntry: Component<{
<div class="file-label" onClick={[console.log, file]}> name: string;
<FileIcon /> path: string;
<span>{name}</span> }> = ({ name, path }) => {
</div> return (
); <div class="file-label" onClick={[handler, path]}>
}; <FileIcon />
const FolderEntry: Component<{
folder: BrowserFolder;
name: string;
index: number;
}> = ({ folder, name, index }) => {
const [isOpen, setIsOpen] = createSignal(index < 1);
return (
<>
<div class="file-label" onClick={() => setIsOpen(!isOpen())}>
{isOpen() ? <FolderOpenIcon /> : <FolderIcon />}
<span>{name}</span> <span>{name}</span>
</div> </div>
);
};
<Show when={isOpen()}> const FolderEntry: Component<{
<FileList folder={folder} /> folder: BrowserFolder;
</Show> name: string;
</> open: boolean;
); }> = ({ folder, name, open }) => {
}; const [isOpen, setIsOpen] = createSignal(open);
const FileList: Component<{ folder: BrowserFolder }> = ({ folder }) => { return (
return ( <>
<ul class="file-list"> <div class="file-label" onClick={() => setIsOpen(!isOpen())}>
<Index each={[...folder.entries()]}> {isOpen() ? <FolderOpenIcon /> : <FolderIcon />}
{(item, index) => { <span>{name}</span>
const [name, entry] = item(); </div>
return ( <Show when={isOpen()}>
<li class="file-item"> <FileList folder={folder} />
{isFolder(entry) ? ( </Show>
<FolderEntry </>
folder={entry as BrowserFolder} );
name={name} };
index={index}
/> const FileList: Component<{ folder: BrowserFolder }> = ({ folder }) => {
) : ( return (
<FileEntry name={name} file={entry as BrowserFile} /> <ul class="file-list">
)} <Index each={[...folder.entries()]}>
</li> {(item, index) => {
); const [name, entry] = item();
}}
</Index> return (
</ul> <li class="file-item">
); {isFolder(entry) ? (
}; <FolderEntry folder={entry} name={name} open={index < 1} />
) : (
<FileEntry name={name} path={entry} />
)}
</li>
);
}}
</Index>
</ul>
);
};
export const FileBrowser: Component<{ root: BrowserFolder }> = ({ root }) => {
return ( return (
<div class="file-browser"> <div class="file-browser">
<FileList folder={root} /> <FileList folder={root} />
+20 -30
View File
@@ -5,11 +5,7 @@ import { currentScene } from "#/engine/Scene.ts";
import { setScale, viewport } from "#/engine/Viewport.ts"; import { setScale, viewport } from "#/engine/Viewport.ts";
import { InputField } from "#/tools/controls/InputField.tsx"; import { InputField } from "#/tools/controls/InputField.tsx";
import { RangeSlider } from "#/tools/controls/RangeSlider.tsx"; import { RangeSlider } from "#/tools/controls/RangeSlider.tsx";
import { import { type BrowserFolder, FileBrowser } from "./FileBrowser.tsx";
type BrowserFile,
type BrowserFolder,
FileBrowser,
} from "./FileBrowser.tsx";
import { import {
ArrowAutofitHeightIcon, ArrowAutofitHeightIcon,
ArrowAutofitWidthIcon, ArrowAutofitWidthIcon,
@@ -17,36 +13,30 @@ import {
ZoomScanIcon, ZoomScanIcon,
} from "./icons/index.ts"; } from "./icons/index.ts";
const root = new Map<string, BrowserFile | BrowserFolder>([ const root = new Map<string, string | BrowserFolder>([
[ [
"foo", "Brrr",
{ new Map<string, string | BrowserFolder>([
path: "/foo.file", [
}, "folder",
], new Map<string, string | BrowserFolder>([
[ ["fuzz", "/fuzz.file"],
"bar", ["buzz", "/buzz.file"],
{ ]),
path: "/bar.file", ],
}, ["dnd:", "/dnd.file"],
["bla", "/bla.file"],
]),
], ],
[ [
"folder", "folder",
new Map([ new Map<string, string | BrowserFolder>([
[ ["fuzz", "/fuzz.file"],
"fuzz", ["buzz", "/buzz.file"],
{
path: "/fuzz.file",
},
],
[
"buzz",
{
path: "/buzz.file",
},
],
]), ]),
], ],
["foo", "/foo.file"],
["bar", "/bar.file"],
]); ]);
function adjustGameContainer(gameContainer: HTMLElement, width: number): void { function adjustGameContainer(gameContainer: HTMLElement, width: number): void {
@@ -128,7 +118,7 @@ const DevTools: Component<{ gameContainer: HTMLElement }> = ({
></InputField> ></InputField>
</div> </div>
<FileBrowser root={root} /> <FileBrowser root={root} handler={console.log} />
</div> </div>
<div class="tool-bar-resize" onMouseDown={startResizing}></div> <div class="tool-bar-resize" onMouseDown={startResizing}></div>
</div> </div>