Add file browser stuff

This commit is contained in:
kolaflash
2025-12-12 16:06:03 +01:00
parent c5ceebdecb
commit 448d203c74
3 changed files with 150 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
.file-browser {
background: var(--c-bg-0);
margin-left: calc(var(--sp-2) * -1);
}
.file-list {
margin: 0;
list-style: none;
padding: 0 0 0 var(--sp-2);
}
.file-item {
display: flex;
flex-flow: column nowrap;
}
.file-label {
display: flex;
justify-content: flex-start;
align-items: center;
padding: var(--sp-1);
border-radius: var(--sp-1);
cursor: pointer;
svg {
margin-right: var(--sp-1);
}
&.active,
&:hover {
background: var(--c-bg-2);
}
}
+78
View File
@@ -0,0 +1,78 @@
import "./FileBrowser.css";
import { type Component, createSignal, Index, Show } from "solid-js";
import { FileIcon, FolderIcon, FolderOpenIcon } from "./icons/index.ts";
export type BrowserFile = { path: string };
export type BrowserFolder = Map<string, BrowserFile | BrowserFolder>;
function isFolder(entry: BrowserFile | BrowserFolder): entry is BrowserFolder {
return typeof (entry as BrowserFolder).size === "number";
}
const FileEntry: Component<{ name: string; file: BrowserFile }> = ({
name,
file,
}) => {
return (
<div class="file-label" onClick={[console.log, file]}>
<FileIcon />
<span>{name}</span>
</div>
);
};
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>
</div>
<Show when={isOpen()}>
<FileList folder={folder} />
</Show>
</>
);
};
const FileList: Component<{ folder: BrowserFolder }> = ({ folder }) => {
return (
<ul class="file-list">
<Index each={[...folder.entries()]}>
{(item, index) => {
const [name, entry] = item();
return (
<li class="file-item">
{isFolder(entry) ? (
<FolderEntry
folder={entry as BrowserFolder}
name={name}
index={index}
/>
) : (
<FileEntry name={name} file={entry as BrowserFile} />
)}
</li>
);
}}
</Index>
</ul>
);
};
export const FileBrowser: Component<{ root: BrowserFolder }> = ({ root }) => {
return (
<div class="file-browser">
<FileList folder={root} />
</div>
);
};
+39
View File
@@ -5,6 +5,11 @@ 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 {
type BrowserFile,
type BrowserFolder,
FileBrowser,
} from "./FileBrowser.tsx";
import { import {
ArrowAutofitHeightIcon, ArrowAutofitHeightIcon,
ArrowAutofitWidthIcon, ArrowAutofitWidthIcon,
@@ -12,6 +17,38 @@ import {
ZoomScanIcon, ZoomScanIcon,
} from "./icons/index.ts"; } from "./icons/index.ts";
const root = new Map<string, BrowserFile | BrowserFolder>([
[
"foo",
{
path: "/foo.file",
},
],
[
"bar",
{
path: "/bar.file",
},
],
[
"folder",
new Map([
[
"fuzz",
{
path: "/fuzz.file",
},
],
[
"buzz",
{
path: "/buzz.file",
},
],
]),
],
]);
function adjustGameContainer(gameContainer: HTMLElement, width: number): void { function adjustGameContainer(gameContainer: HTMLElement, width: number): void {
gameContainer.style = `position: relative; top: 0; left: ${width}px; width: ${document.body.offsetWidth - width}px;`; gameContainer.style = `position: relative; top: 0; left: ${width}px; width: ${document.body.offsetWidth - width}px;`;
} }
@@ -90,6 +127,8 @@ const DevTools: Component<{ gameContainer: HTMLElement }> = ({
}} }}
></InputField> ></InputField>
</div> </div>
<FileBrowser root={root} />
</div> </div>
<div class="tool-bar-resize" onMouseDown={startResizing}></div> <div class="tool-bar-resize" onMouseDown={startResizing}></div>
</div> </div>