npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@parent-tobias/filesystem-component

v0.1.0

Published

A flexible, feature-rich filesystem web component with version control, multiple storage backends (IndexedDB, OPFS, File System Access API), and comprehensive theming support

Downloads

125

Readme

Filesystem Component

A flexible, feature-rich filesystem web component built with Lit.js and TypeScript. This component provides a complete file management system with version control, multiple storage backends, and a clean UI.

Features

  • Full Filesystem Operations: Create, read, update, delete files and folders
  • Version Control: Auto-save and named versions with history tracking
  • Multiple Storage Backends:
    • File System Access API - Save to real, visible files in user-chosen directories ✨ NEW
    • OPFS (Origin Private File System) - Modern browser API
    • IndexedDB - Fallback for broader compatibility
    • Automatic fallback from OPFS to IndexedDB
    • Extensible for remote storage (API, Supabase, Firebase, etc.)
  • File References: Files can exist in multiple folders (like tags/labels)
  • Folder Hierarchy: Nested folders with breadcrumb navigation
  • Fork/Clone Files: Create copies from any version
  • Custom Events: React to user interactions (file selection, saves, etc.)
  • Public API: Programmatic control via methods
  • Auto-save: Debounced auto-saving with configurable timing
  • Clean UI: Polished sidebar interface with Material Design inspired styling
  • Comprehensive Theming: Full CSS custom properties support for colors, spacing, typography, and more

Installation

npm install
npm run dev

Usage

Basic Setup

<!DOCTYPE html>
<html>
  <head>
    <script type="module" src="/src/index.ts"></script>
  </head>
  <body>
    <filesystem-component></filesystem-component>
  </body>
</html>

With TypeScript

import { FileSystemComponent } from './filesystem-component';

const fileSystem = document.querySelector('filesystem-component') as FileSystemComponent;

// Create a file
const fileId = await fileSystem.createFile('hello.txt', 'Hello, World!');

// Load a file
const result = await fileSystem.loadFile(fileId);
console.log(result?.content); // "Hello, World!"

// Save a file (auto-save)
await fileSystem.saveFile(fileId, 'Updated content', { autoSave: true });

// Save a named version
await fileSystem.saveFile(fileId, 'Version 1.0 content', {
  autoSave: false,
  versionName: 'v1.0'
});

Custom Events

// Listen for file selection
fileSystem.addEventListener('file-selected', (e: Event) => {
  const detail = (e as CustomEvent).detail;
  console.log('Selected file:', detail.fileName);
  console.log('Breadcrumb:', detail.breadcrumb);
});

// Listen for folder selection
fileSystem.addEventListener('folder-selected', (e: Event) => {
  const detail = (e as CustomEvent).detail;
  console.log('Selected folder:', detail.folderName);
  console.log('Path:', detail.folderPath);
});

// Other events
fileSystem.addEventListener('file-created', (e) => { /* ... */ });
fileSystem.addEventListener('file-saved', (e) => { /* ... */ });
fileSystem.addEventListener('file-forked', (e) => { /* ... */ });
fileSystem.addEventListener('version-restored', (e) => { /* ... */ });

Theming

The component supports comprehensive theming through CSS custom properties. You can customize colors, spacing, typography, and more to match your application's design system.

Quick Example

/* Override default theme */
filesystem-component {
  --fs-color-primary: #8b5cf6;
  --fs-color-bg-primary: #1a1a1a;
  --fs-color-text-primary: #ffffff;
  --fs-spacing-sm: 6px;
  --fs-font-family: 'Inter', sans-serif;
}

Integrate with Other Components

/* Define global theme variables */
:root {
  --app-color-primary: #0066cc;
  --app-color-bg: white;
  --app-spacing: 8px;
}

/* Apply to filesystem component */
filesystem-component {
  --fs-color-primary: var(--app-color-primary);
  --fs-color-bg-primary: var(--app-color-bg);
  --fs-spacing-sm: var(--app-spacing);
}

/* Apply to other components */
chordpro-editor,
chordpro-renderer {
  --chord-color-primary: var(--app-color-primary);
  --chord-color-bg: var(--app-color-bg);
}

Available CSS Custom Properties

The component exposes 40+ CSS custom properties covering:

  • Colors: Base backgrounds, text colors, borders, brand/action colors
  • Spacing: From extra small (4px) to extra large (32px)
  • Typography: Font family, sizes (11px-16px), weights
  • Effects: Shadows, transitions, border radius
  • Dimensions: Content max height

For complete documentation of all CSS custom properties, see THEMING.md.

For a live demo, open examples/theming-demo.html in your browser.

API Reference

File Operations

createFile(name: string, content: string, folderId?: string): Promise<string>

Creates a new file with optional folder placement.

const fileId = await fileSystem.createFile('document.txt', 'Initial content', folderId);

loadFile(fileId: string, versionId?: string): Promise<{file: FileMetadata, content: string} | null>

Loads a file's content. Optionally specify a version to load.

const result = await fileSystem.loadFile(fileId);
const oldVersion = await fileSystem.loadFile(fileId, versionId);

saveFile(fileId: string, content: string, options: SaveFileOptions): Promise<string>

Saves a file, creating a new version.

// Auto-save
await fileSystem.saveFile(fileId, content, { autoSave: true });

// Named version
await fileSystem.saveFile(fileId, content, {
  autoSave: false,
  versionName: 'Release v1.0'
});

deleteFile(fileId: string): Promise<void>

Deletes a file and all its versions.

renameFile(fileId: string, newName: string): Promise<void>

Renames a file.

forkFile(fileId: string, versionId?: string, newName?: string): Promise<string>

Creates a copy of a file from a specific version.

const newFileId = await fileSystem.forkFile(fileId, versionId, 'Forked Document');

Folder Operations

createFolder(name: string, parentId?: string): Promise<string>

Creates a new folder.

const folderId = await fileSystem.createFolder('My Projects');
const subfolderId = await fileSystem.createFolder('Client Work', folderId);

deleteFolder(folderId: string): Promise<void>

Deletes a folder (files are unlinked, not deleted).

renameFolder(folderId: string, newName: string): Promise<void>

Renames a folder.

moveFileToFolder(fileId: string, folderId: string): Promise<void>

Links a file to a folder (file can exist in multiple folders).

Version Control

getVersionHistory(fileId: string): Promise<VersionInfo[]>

Gets all versions of a file.

const history = await fileSystem.getVersionHistory(fileId);
history.forEach(v => {
  console.log(v.name, v.timestamp, v.isAuto);
});

restoreVersion(fileId: string, versionId: string): Promise<string>

Restores an old version (creates a new version with old content).

await fileSystem.restoreVersion(fileId, oldVersionId);

pruneVersions(fileId: string, options: PruneOptions): Promise<void>

Removes old auto-save versions.

await fileSystem.pruneVersions(fileId, {
  keepLast: 10,
  keepNamed: true
});

Query Operations

getAllFiles(): Promise<FileMetadata[]>

Gets all files in the system.

getAllFolders(): Promise<FolderMetadata[]>

Gets all folders in the system.

refresh(): Promise<void>

Refreshes the UI from storage.

Storage Architecture

Storage Options

The component supports three storage backends:

  1. OPFS (Origin Private File System) - Modern, sandboxed browser storage
  2. IndexedDB - Fallback for broader compatibility
  3. File System Access API - Save to user-chosen folders as real files ✨ NEW

Automatic Fallback

By default, the component tries OPFS first, then falls back to IndexedDB if OPFS is unavailable.

Storage Types

// Default: auto-fallback (OPFS → IndexedDB)
<filesystem-component></filesystem-component>

// Force IndexedDB
<filesystem-component storage-type="indexeddb"></filesystem-component>

// Force OPFS
<filesystem-component storage-type="opfs"></filesystem-component>

// Force File System Access (user picks directory)
<filesystem-component storage-type="filesystemaccess"></filesystem-component>

File System Access API

What makes it special:

  • ✅ Files saved as real, visible files in your chosen directory
  • ✅ Access files outside the browser (using any text editor)
  • ✅ Folder structure matches real directories
  • ✅ Choose where to save your data
  • ⚠️ Requires user permission (browser will prompt)
  • ⚠️ Chrome/Edge 86+, not available in Firefox/Safari yet

How to use:

  1. Click the "📁 Pick Folder" button in the component header
  2. Choose a directory on your computer
  3. Grant read/write permission
  4. Files are now saved as real files!

✨ Persistence:

  • Your directory selection is automatically saved to IndexedDB
  • On page reload, the directory auto-restores if permission is still granted
  • No need to pick the folder again after refreshing!
  • See PERSISTENCE.md for details

What gets created:

your-chosen-folder/
├── .fs-meta/              # Hidden metadata directory
│   ├── files.json         # File metadata
│   ├── folders.json       # Folder structure
│   └── versions/          # Version history
│       ├── v1.json
│       └── v2.json
├── My Documents/          # Your actual folders
│   ├── report.txt         # Your actual files!
│   └── notes.txt
└── Projects/
    └── todo.md

Programmatic usage:

const fileSystem = document.querySelector('filesystem-component');

// Switch to File System Access storage
await fileSystem.service.switchToFileSystemAccess();
// This prompts user to pick a directory

// Now all operations save to real files
await fileSystem.createFile('document.txt', 'Hello!');

Custom Storage Adapter

Implement the StorageAdapter interface for custom backends:

import { StorageAdapter } from './storage/storage-adapter';

class RemoteStorageAdapter implements StorageAdapter {
  async getFile(id: string) { /* API call */ }
  async saveFile(file: FileMetadata) { /* API call */ }
  // ... implement all methods
}

Version Control Strategy

Auto-Save Versions

  • Created automatically after 2 seconds of inactivity
  • Timestamped: v_20231213_143022
  • Old versions auto-pruned (keeps last 10)

Named Versions

  • Created manually by user
  • Custom names: "v1.0", "First Draft", etc.
  • Never auto-pruned
  • Permanent record of important states

File Forking

Clone any version into a new file for experimentation.

Events Reference

| Event | Detail | Description | |-------|--------|-------------| | file-selected | FileSelectedDetail | User clicked a file | | folder-selected | FolderSelectedDetail | User clicked a folder | | file-created | { fileName: string } | New file created | | file-saved | { fileId, versionId, isAutoSave } | File saved | | file-deleted | { fileId } | File deleted | | file-forked | { originalFileId, newFileId } | File forked | | folder-created | { folderName } | Folder created | | folder-deleted | { folderId } | Folder deleted | | version-restored | { fileId, versionId, newVersionId } | Version restored |

Development

# Install dependencies
npm install

# Run dev server
npm run dev

# Build
npm run build

# Preview build
npm run preview

Browser Support

  • File System Access API: Chrome 86+, Edge 86+ (real files in user directories)
  • OPFS: Chrome 86+, Edge 86+, Opera 72+ (sandboxed browser storage)
  • IndexedDB: All modern browsers (fallback)

License

MIT

Future Enhancements

  • Remote storage adapters (Supabase, Firebase, custom API)
  • Search functionality
  • File tagging
  • Drag-and-drop file organization
  • Export/import functionality
  • Collaborative editing support
  • Conflict resolution for concurrent edits