@jeryfan/finder-ui
v0.6.7
Published
A macOS Finder-style file browser component for React
Maintainers
Readme
@jeryfan/finder-ui
A macOS Finder-style file browser component for React. Designed for Agent sandbox environments — providing secure, isolated file browsing and operations for AI agents to efficiently manage files in restricted environments.
Install
npm install @jeryfan/finder-uiIf you install directly from GitHub:
npm install github:jeryfan/finder-uiQuick Start
import { Finder } from '@jeryfan/finder-ui'
function App() {
return (
<Finder
style={{ height: '100vh' }}
tabs={[
{ key: 'files', label: 'Files', rootPath: '/' },
]}
onFetchFiles={async (path) => {
const res = await fetch(`/api/files?path=${path}`)
return (await res.json()).files
}}
/>
)
}Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| tabs | SidebarTab[] | Yes | Tab configuration for sidebar navigation |
| onFetchFiles | (path: string) => Promise<FileEntry[]> | Yes | Fetch files for a directory path |
| defaultTab | string | No | Key of the initially active tab |
| onOpenFile | (file: FileEntry) => Promise<string \| void> | No | Handle file open; return content string to show in preview |
| onDownload | (file: FileEntry) => Promise<void> \| void | No | Handle single file download |
| onBatchDownload | (files: FileEntry[]) => Promise<void> \| void | No | Handle batch file download |
| onUpload | (files: File[], targetPath?: string) => Promise<void> | No | Handle file upload |
| onSave | (path: string, content: string) => Promise<void> | No | Handle save of edited file content |
| onRename | (file: FileEntry, newName: string) => Promise<void> | No | Handle file/folder rename |
| onDelete | (files: FileEntry[]) => Promise<void> | No | Handle file/folder deletion |
| onConfirmDelete | (files: FileEntry[], message: string) => Promise<boolean> \| boolean | No | Confirm file/folder deletion; return false to cancel |
| onCreateFolder | (parentPath: string, name: string) => Promise<void> | No | Handle new folder creation |
| editable | boolean | No | Enable file editing in preview panel |
| renderMarkdown | (content: string) => ReactNode | No | Custom markdown renderer |
| locale | Partial<FinderLocale> | No | Localization strings (defaults to English) |
| className | string | No | Additional CSS class for root element |
| style | CSSProperties | No | Inline styles for root element (e.g. dimensions) |
| theme | 'default' \| 'graphite' \| 'minimal' | No | Theme variant (default: 'default') |
Keyboard Shortcuts
| Key | Action |
|-----|--------|
| ↑ / ↓ | Navigate file list |
| Enter | Open file or enter folder |
| Backspace | Go to parent directory |
| ⌘/Ctrl + A | Select all files |
| Delete | Delete selected files when onDelete is provided |
| Escape | Clear selection |
Sizing
The component fills its parent by default (width: 100%; height: 100%). Use the style or className prop to set explicit dimensions:
// Full viewport
<Finder style={{ height: '100vh' }} ... />
// Fixed height
<Finder style={{ height: 600 }} ... />
// Fill parent (parent must have explicit height)
<Finder ... />Multiple Instances
Each <Finder> creates an isolated store — multiple instances on the same page work independently with no shared state.
Examples
Run the API server and the examples workbench, then open http://127.0.0.1:5273/:
pnpm dev:api
pnpm dev| Example | Description | |---------|-------------| | Basic | Minimal setup — one tab, file listing only (~10 lines) | | With Preview | File preview for Markdown, code, CSV, images, audio, video, and PDF | | File Operations | Upload, save, and download callbacks wired to the local API | | Internationalization | Dynamic locale switching (English, Chinese, Japanese) | | Custom Theme | Theme switching (default/graphite/minimal) and CSS variable overrides | | Multiple Instances | Two independent Finder instances side by side | | Kitchen Sink | Multi-tab browsing, preview, editing, i18n, themes, upload, save, and download |
The bundled examples call the local /api endpoints through the Vite dev server proxy.
Peer Dependencies
{
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0",
"zustand": "^5.0.0",
"marked": "^17.0.0",
"@codemirror/lang-json": "^6.0.0",
"@codemirror/theme-one-dark": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@uiw/react-codemirror": "^4.20.0"
}