master
1---
2import { fileIcon } from '@utils/file-icon';
3import { Icon } from 'astro-icon/components';
4
5type FileNode =
6 | {
7 name: string;
8 children?: FileNode[];
9 }
10 | string;
11
12interface Props {
13 files: FileNode[];
14 open?: boolean;
15}
16
17const { files, open } = Astro.props;
18---
19
20<ul class="menu menu-sm rounded-box border-base-content/25 w-full border">
21 {
22 (() => {
23 function renderer(node: FileNode) {
24 if (typeof node === 'string') {
25 return (
26 <li>
27 <span class="cursor-auto">
28 <Icon name={fileIcon(node)} />
29 {node}
30 </span>
31 </li>
32 );
33 } else {
34 return (
35 <li>
36 <details {...(open ? { open: true } : {})}>
37 <summary>
38 <Icon name="mdi:folder" />
39 {node.name}
40 </summary>
41 {node.children && <ul>{node.children.map((child) => renderer(child))}</ul>}
42 </details>
43 </li>
44 );
45 }
46 }
47 return files.map((node) => renderer(node));
48 })()
49 }
50</ul>