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

@knurdz/jack-file-tree

v0.2.1

Published

A feature-rich React file tree component with drag-and-drop, inline editing, Monaco editor support, and filesystem adapter for Electron and web apps

Downloads

90

Readme

Jack File Tree

Reusable React file tree sidebar extracted from Sonar Code Editor. It ships as a ready-made explorer panel out of the box, but also exposes the hooks you need to restyle or replace the shell pieces in Electron apps, web sandboxes, IDEs, or any host that can implement the file operations.

Features

  • Ready-to-use sidebar container with header, empty state, and tree content
  • Left/right sidebar placement styling with sensible defaults
  • Configurable panel width, min width, and max width
  • Top full-width open-folder CTA out of the box
  • Bring-your-own open-folder button and empty-state UI hooks
  • Bring-your-own header and footer UI hooks
  • Theme tokens for colors, fonts, borders, and top/titlebar offsets
  • Built-in context menus with per-action enable/disable controls
  • Bring-your-own context menu renderer
  • Nested file and folder explorer
  • Inline create and rename
  • Drag and drop move
  • Cut, copy, and paste
  • Soft delete with undo (Cmd/Ctrl+Z)
  • Monaco-safe input shield for rename/create inputs
  • TypeScript types and library build config ready for npm publishing

Install

npm install @knurdz/jack-file-tree

Peer dependencies:

  • react
  • react-dom

Basic usage

import "@knurdz/jack-file-tree/keyboard-shield";

import { FileTree, type FileTreeFsAdapter } from "@knurdz/jack-file-tree";

const fsAdapter: FileTreeFsAdapter = window.electronAPI.fs;

export function Explorer() {
  return (
    <FileTree
      fs={fsAdapter}
      workspaceRoot={workspaceRoot}
      sidebarPosition="left"
      width={300}
      activeFilePath={activeFilePath}
      onOpenFolder={openFolder}
      onFileClick={(path, name) => openFile(path, name)}
      onFileOpened={(path, name) => openFile(path, name)}
      onFileDeleted={handleFileDeleted}
      onFileRenamed={handleFileRenamed}
      onFileCreated={handleFileCreated}
      onFolderCreated={handleFolderCreated}
      onFileCopied={handleFileCopied}
      onFileMoved={handleFileMoved}
      refreshTrigger={refreshKey}
      newFileTrigger={newFileTrigger}
    />
  );
}

@knurdz/jack-file-tree now auto-injects its built-in styles when you import the package entry, so the extra stylesheet import is optional. If you want explicit stylesheet control for ordering or overrides, you can still import @knurdz/jack-file-tree/styles.css manually.

Customization

The default component is a full sidebar panel, but you can still swap in your own UI for key pieces while keeping the built-in tree behavior.

<FileTree
  fs={fsAdapter}
  workspaceRoot={workspaceRoot}
  onOpenFolder={openFolder}
  onFileClick={openFile}
  sidebarPosition="right"
  width={320}
  theme={{
    backgroundSecondary: "#0f172a",
    backgroundHover: "rgba(56, 189, 248, 0.12)",
    accent: "#38bdf8",
    panelTopPadding: 12,
  }}
  renderHeader={({ title, defaultActions, className, titleClassName, actionsClassName }) => (
    <div className={className}>
      <span className={titleClassName}>{title}</span>
      <div className={actionsClassName}>{defaultActions}</div>
    </div>
  )}
  footer={<div>Project Explorer</div>}
  renderOpenFolderButton={({ className, label, onClick }) => (
    <button className={className} onClick={onClick}>
      {label}
    </button>
  )}
  contextMenu={{
    actions: {
      cut: false,
      delete: false,
    },
  }}
/>

Useful props:

  • sidebarPosition: "left" or "right" styling for the built-in sidebar shell
  • width, minWidth, maxWidth: size the built-in sidebar without extra wrapper CSS
  • showHeader: toggle the built-in header row
  • showHeaderActions: toggle the built-in create-file/create-folder action buttons
  • renderHeader: replace the built-in header while still receiving default actions and labels
  • contentClassName, contentStyle: style the scrollable tree content area
  • footer / renderFooter: append a built-in footer area at the bottom of the sidebar
  • showOpenFolderButton: toggle the built-in open-folder CTA
  • openFolderButtonPosition: "top" or "center" in the empty state
  • renderOpenFolderButton: render your own open-folder button while keeping library behavior
  • renderEmptyState: replace the full empty-state UI
  • theme: set colors, fonts, borders, and inset offsets without overriding the stylesheet
  • contextMenu.enabled: enable or disable library context menus
  • contextMenu.actions: hide individual built-in menu actions
  • contextMenu.renderMenu: render your own context menu UI

Useful CSS variables:

  • --sft-bg-primary, --sft-bg-secondary, --sft-bg-hover
  • --sft-text-primary, --sft-text-secondary, --sft-text-muted
  • --sft-accent, --sft-accent-transparent, --sft-danger
  • --sft-sidebar-border
  • --sft-panel-top-padding: adds top inset for custom titlebar layouts
  • --sft-header-title-offset-y: nudges the header title vertically
  • --sft-header-actions-offset-y: nudges the header action buttons vertically
  • --sft-open-folder-btn-bg, --sft-open-folder-btn-text, --sft-open-folder-btn-border: style the built-in open-folder CTA
  • --sft-menu-bg, --sft-menu-border, --sft-menu-hover, --sft-menu-text: style the built-in context menu

The theme prop writes those same CSS variables for you, so hosts can choose between inline theme tokens or plain stylesheet overrides.

Monaco integration

If your host app uses Monaco, import jack-file-tree/keyboard-shield before Monaco is loaded. This prevents Monaco capture listeners from swallowing keystrokes in the tree's inline rename/create inputs.

import "@knurdz/jack-file-tree/keyboard-shield";
import "monaco-editor";

If you do not use Monaco, you can skip that import.

Filesystem adapter

The component is intentionally decoupled from Electron. Provide an adapter that matches this shape:

interface FileTreeFsAdapter {
  readDirectory(path: string): Promise<FileTreeNode[]>;
  readFile?(path: string): Promise<string>;
  createFile(path: string): Promise<string | void>;
  createFolder(path: string): Promise<string | void>;
  renameItem(oldPath: string, newPath: string): Promise<string | void>;
  copyItem(oldPath: string, newPath: string): Promise<string | void>;
}

Publishing checklist

  1. Move the file-tree/ folder into its own repository.
  2. Update the package name, repository, and author fields if needed.
  3. Run npm install.
  4. Run npm run build.
  5. Publish with npm publish.

An Electron wiring example is included in examples/electron-usage.tsx.