import { Accessor, Component, createContext, createSignal, For, JSX, Show, useContext } from "solid-js"; import { AiFillFile, AiFillFolder, AiFillFolderOpen } from "solid-icons/ai"; import { SelectionProvider, selectable } from "~/features/selectable"; import css from "./filetree.module.css"; export interface FileEntry { name: string; kind: 'file'; meta: File; } export interface FolderEntry { name: string; kind: 'folder'; entries: Entry[]; } export type Entry = FileEntry | FolderEntry; export const emptyFolder: FolderEntry = { name: '', kind: 'folder', entries: [] } as const; export async function* walk(directory: FileSystemDirectoryHandle, filters: RegExp[] = [], depth = 0): AsyncGenerator { if (depth === 10) { return; } for await (const handle of directory.values()) { if (filters.some(f => f.test(handle.name))) { continue; } if (handle.kind === 'file') { yield { name: handle.name, kind: 'file', meta: await handle.getFile() }; } else { yield { name: handle.name, kind: 'folder', entries: await Array.fromAsync(walk(handle, filters, depth + 1)) }; } } } interface TreeContextType { open(file: File): void; } const TreeContext = createContext(); export const Tree: Component<{ entries: Entry[], children: (file: Accessor) => JSX.Element, open?: TreeContextType['open'] }> = (props) => { const [selection, setSelection] = createSignal([]); // createEffect(() => { // console.log(selection()); // }); const context = { open: props.open ?? (() => { }), // open(file: File) { // console.log(`open ${file.name}`) // }, }; return
<_Tree entries={props.entries} children={props.children} />
; } const _Tree: Component<{ entries: Entry[], children: (file: Accessor) => JSX.Element }> = (props) => { const context = useContext(TreeContext); return { entry => <> { folder => } { file => context?.open(file().meta)}> {props.children(file)} } } } const Folder: Component<{ folder: FolderEntry, children: (file: Accessor) => JSX.Element }> = (props) => { const [open, setOpen] = createSignal(false); return
setOpen(o => !o)}> }> {props.folder.name} <_Tree entries={props.folder.entries} children={props.children} />
; }; const sort_by = (key: string) => (objA: Record, objB: Record) => { const a = objA[key]; const b = objB[key]; return Number(a < b) - Number(b < a); };