Skip to main content

Interactive file system navigation and selection UI components for FastHTML applications with extensible provider support.

Project description

cjm-fasthtml-file-browser

Install

pip install cjm_fasthtml_file_browser

Project Structure

nbs/
├── components/ (4)
│   ├── browser.ipynb   # Main file browser component with virtualized collection rendering.
│   ├── item.ipynb      # File type icons, cell render callback for virtual collection, and empty/error state components.
│   ├── path_bar.ipynb  # Path display, breadcrumbs navigation, and optional path input for the file browser.
│   └── utils.ipynb     # Sorting and filtering utilities for file listings.
├── core/ (4)
│   ├── config.ipynb     # Configuration dataclasses and enums for the file browser.
│   ├── html_ids.ipynb   # HTML ID constants for HTMX targeting in the file browser.
│   ├── models.ipynb     # Core data models for the file browser including DirectoryListing, BrowserSelection, and BrowserState.
│   └── protocols.ipynb  # Protocol definitions for extensible file system providers.
├── providers/ (1)
│   └── local.ipynb  # Local file system provider for interactive directory navigation.
└── routes/ (1)
    └── handlers.ipynb  # Route handlers, router initialization, and virtual collection wiring for the file browser.

Total: 10 notebooks across 5 directories

Module Dependencies

graph LR
    components_browser[components.browser<br/>Browser]
    components_item[components.item<br/>Item]
    components_path_bar[components.path_bar<br/>Path Bar]
    components_utils[components.utils<br/>Utils]
    core_config[core.config<br/>Config]
    core_html_ids[core.html_ids<br/>HTML IDs]
    core_models[core.models<br/>Models]
    core_protocols[core.protocols<br/>Protocols]
    providers_local[providers.local<br/>Local Provider]
    routes_handlers[routes.handlers<br/>Handlers]

    components_browser --> core_config
    components_browser --> components_path_bar
    components_browser --> core_html_ids
    components_browser --> core_models
    components_browser --> components_item
    components_item --> core_config
    components_item --> core_models
    components_path_bar --> core_config
    components_path_bar --> components_item
    components_path_bar --> core_html_ids
    components_utils --> core_config
    core_protocols --> core_models
    providers_local --> core_models
    providers_local --> core_protocols
    routes_handlers --> core_config
    routes_handlers --> components_utils
    routes_handlers --> providers_local
    routes_handlers --> components_item
    routes_handlers --> core_models
    routes_handlers --> core_protocols
    routes_handlers --> components_browser

21 cross-module dependencies detected

CLI Reference

No CLI commands found in this project.

Module Overview

Detailed documentation for each module in the project:

Browser (browser.ipynb)

Main file browser component with virtualized collection rendering.

Import

from cjm_fasthtml_file_browser.components.browser import (
    render_file_browser
)

Functions

def render_file_browser(
    items: list,                                # Current filtered/sorted FileInfo list
    config: FileBrowserConfig,                  # Browser configuration
    state: BrowserState,                        # Browser state (path, selection)
    listing: DirectoryListing,                  # Raw directory listing (for path bar)
    vc_config: VirtualCollectionConfig,         # Virtual collection config
    vc_state: VirtualCollectionState,           # Virtual collection state
    vc_ids: VirtualCollectionHtmlIds,           # Virtual collection HTML IDs
    vc_btn_ids: VirtualCollectionButtonIds,     # Virtual collection button IDs
    urls: VirtualCollectionUrls,                # Virtual collection URL bundle
    render_cell: Callable,                      # Cell render callback
    navigate_url: str,                          # URL for directory navigation
    refresh_url: str,                           # URL for refresh
    path_input_url: str = "",                   # URL for path input (optional)
    home_path: str = "",                        # Home directory path
    hx_target: Optional[str] = None,            # Override HTMX target (default: container_id)
) -> Any:  # Complete file browser component
    "Render the complete file browser with virtualized collection."

Variables

_FB_GO_PARENT_CALLBACK = 'fbGoParentDir'

Config (config.ipynb)

Configuration dataclasses and enums for the file browser.

Import

from cjm_fasthtml_file_browser.core.config import (
    SelectionMode,
    FileColumn,
    ViewConfig,
    FilterConfig,
    FileBrowserCallbacks,
    FileBrowserConfig
)

Classes

class SelectionMode(str, Enum):
    "File selection modes."
class FileColumn(str, Enum):
    "Available columns for list view."
@dataclass
class ViewConfig:
    "View display configuration."
    
    columns: List[FileColumn] = field(...)
    default_sort: FileColumn = FileColumn.NAME  # Default sort column
    sort_folders_first: bool = True  # Sort folders before files
    allow_sort_toggle: bool = True  # Allow user to change sort
@dataclass
class FilterConfig:
    "Filtering configuration."
    
    allowed_extensions: Optional[List[str]]  # Include only these extensions (None = all)
    show_directories: bool = True  # Show directories
    show_hidden: bool = False  # Show hidden files/directories
    show_system_files: bool = False  # Show system files
    custom_filter: Optional[Callable[[FileInfo], bool]]  # Custom filter function
    
    def matches(
            self,
            file_info: FileInfo  # File to check against filter
        ) -> bool:  # True if file passes filter
        "Check if a file matches the filter criteria."
@dataclass
class FileBrowserCallbacks:
    "Event callbacks for customization."
    
    on_navigate: Optional[Callable[[str], None]]  # Called when directory changes
    on_select: Optional[Callable[[str], None]]  # Called when file selected
    on_selection_change: Optional[Callable[[List[str]], None]]  # Called when selection changes
    on_open: Optional[Callable[[str], None]]  # Called on file double-click/enter
    validate_selection: Optional[Callable[[str], Tuple[bool, str]]]  # Validate before select
    validate_navigation: Optional[Callable[[str], Tuple[bool, str]]]  # Validate before navigate
@dataclass
class FileBrowserConfig:
    "Main configuration for file browser."
    
    provider: Optional[Any]  # FileSystemProvider, defaults to local
    start_path: Optional[str]  # Initial path (defaults to home)
    selection_mode: SelectionMode = SelectionMode.SINGLE
    selectable_types: Literal['files', 'directories', 'both'] = 'files'
    max_selections: Optional[int]  # For MULTIPLE mode
    view: ViewConfig = field(...)
    filter: FilterConfig = field(...)
    show_path_bar: bool = True
    show_path_input: bool = False  # Direct path entry field
    show_breadcrumbs: bool = True
    bookmarks: Optional[List[Tuple[str, str]]]  # [(label, path), ...]
    show_bookmarks: bool = False
    container_id: str = 'file-browser'
    content_id: str = 'file-browser-content'
    path_bar_id: str = 'file-browser-path'
    listing_id: str = 'file-browser-listing'
    vc_prefix: str = ''  # Prefix for virtual collection IDs (auto-generated if empty)
    
    def can_select(
            self,
            file_info: FileInfo  # File to check
        ) -> bool:  # True if file can be selected
        "Check if a file/directory can be selected based on config."

Handlers (handlers.ipynb)

Route handlers, router initialization, and virtual collection wiring for the file browser.

Import

from cjm_fasthtml_file_browser.routes.handlers import (
    FileBrowserRouters,
    init_router
)

Functions

def _handle_navigate(
    provider: FileSystemProvider,           # File system provider
    state_getter: Callable[[], BrowserState],  # Function to get current state
    state_setter: Callable[[BrowserState], None],  # Function to save state
    callbacks: Optional[FileBrowserCallbacks],  # Optional callbacks
    path: str,                              # Path to navigate to
    render_fn: Callable[[BrowserState], Any],  # Function to render browser
) -> Any:  # Rendered browser component
    "Handle navigation to a new directory."
def _handle_path_input(
    provider: FileSystemProvider,           # File system provider
    state_getter: Callable[[], BrowserState],  # Function to get current state
    state_setter: Callable[[BrowserState], None],  # Function to save state
    callbacks: Optional[FileBrowserCallbacks],  # Optional callbacks
    path: str,                              # Path input by user
    render_fn: Callable[[BrowserState], Any],  # Function to render browser
    navigate_fn: Callable[[str], Any],      # Function to handle navigation
) -> Any:  # Rendered browser component
    "Handle direct path input."
def _handle_select(
    config: FileBrowserConfig,              # Browser configuration
    state_getter: Callable[[], BrowserState],  # Function to get current state
    state_setter: Callable[[BrowserState], None],  # Function to save state
    callbacks: Optional[FileBrowserCallbacks],  # Optional callbacks
    path: str,                              # Path to select/deselect
    render_fn: Callable[[BrowserState], Any],  # Function to render browser
) -> Any:  # Rendered browser component
    "Handle file selection."
def _handle_refresh(
    state_getter: Callable[[], BrowserState],  # Function to get current state
    render_fn: Callable[[BrowserState], Any],  # Function to render browser
) -> Any:  # Rendered browser component
    "Handle refresh (re-render with current state)."
def _build_columns(
    config: FileBrowserConfig,  # Browser config
) -> Tuple[ColumnDef, ...]:  # Column definitions for virtual collection
    "Build ColumnDef tuple from browser config, conditionally including checkbox column."
def _rebuild_items(
    provider: FileSystemProvider,  # File system provider
    state: BrowserState,           # Browser state with current_path
    config: FileBrowserConfig,     # Browser config (for filter/sort)
) -> List[FileInfo]:  # Filtered and sorted item list
    "List, filter, and sort directory contents."
def init_router(
    config: FileBrowserConfig,                              # Browser configuration
    provider: FileSystemProvider,                           # File system provider
    state_getter: Callable[[], BrowserState],               # Function to get current state
    state_setter: Callable[[BrowserState], None],           # Function to save state
    route_prefix: str = "/browser",                         # Route prefix for browser routes
    vc_route_prefix: str = "",                              # Route prefix for VC routes (auto: {route_prefix}/vc)
    callbacks: Optional[FileBrowserCallbacks] = None,       # Optional callbacks
    home_path: Optional[str] = None,                        # Home directory (defaults to provider)
) -> FileBrowserRouters:  # Browser + collection routers and URL bundle
    "Initialize file browser and virtual collection routers."

Classes

@dataclass
class FileBrowserRouters:
    "Return value from init_router — both routers, URL bundle, and render function."
    
    browser: APIRouter  # File-specific routes (navigate, select, refresh, path_input)
    collection: APIRouter  # Virtual collection routes (nav, focus, activate, sort, viewport)
    urls: VirtualCollectionUrls  # URL bundle for rendering
    render: Callable  # () -> Any, renders the full file browser component

HTML IDs (html_ids.ipynb)

HTML ID constants for HTMX targeting in the file browser.

Import

from cjm_fasthtml_file_browser.core.html_ids import (
    FileBrowserHtmlIds
)

Classes

class FileBrowserHtmlIds:
    "Default HTML IDs for file browser components."
    
    def item_id(
            cls,
            index: int  # Item index in the listing
        ) -> str:  # HTML ID for the item
        "Generate item ID for a specific index."
    
    def as_selector(
            cls,
            html_id: str  # HTML ID
        ) -> str:  # CSS selector for the ID
        "Convert HTML ID to CSS selector."

Item (item.ipynb)

File type icons, cell render callback for virtual collection, and empty/error state components.

Import

from cjm_fasthtml_file_browser.components.item import (
    FILE_TYPE_ICONS,
    BROWSER_ICONS,
    create_file_cell_renderer,
    render_empty_state,
    render_error_state
)

Functions

def _get_file_icon(
    file_info: FileInfo,  # File to get icon for
    size: int = 4         # Icon size (Tailwind scale)
) -> Any:  # Lucide icon component
    "Get the appropriate icon for a file based on its type."
def create_file_cell_renderer(
    config: FileBrowserConfig,  # Browser config (for selection state access)
    get_selection: Callable,    # () -> BrowserSelection, returns current selection
    select_url: str = "",       # URL for checkbox click selection route
) -> Callable:  # render_cell(item: FileInfo, ctx: CellRenderContext) -> Any
    """
    Create a render_cell callback for the virtual collection.
    
    Returns a closure that renders cell content based on column key.
    """
def render_empty_state(
    message: str = "No files found",  # Message to display
    icon_name: str = "folder-open"    # Lucide icon name
) -> Any:  # Empty state component
    "Render empty state for when a directory has no matching items."
def render_error_state(
    error_message: str  # Error message to display
) -> Any:  # Error state component
    "Render error state for when directory access fails."

Variables

FILE_TYPE_ICONS: Dict[FileType, str]
BROWSER_ICONS: Dict[str, str]

Local Provider (local.ipynb)

Local file system provider for interactive directory navigation.

Import

from cjm_fasthtml_file_browser.providers.local import (
    LocalFileSystemProvider
)

Classes

class LocalFileSystemProvider:
    def __init__(
        self,
        extension_mapping: Optional[ExtensionMapping] = None  # For file type detection
    )
    "Local file system provider for interactive navigation."
    
    def __init__(
            self,
            extension_mapping: Optional[ExtensionMapping] = None  # For file type detection
        )
        "Initialize with optional extension mapping."
    
    def name(self) -> str:  # Provider identifier
            """Provider identifier."""
            return "local"
    
        @property
        def root_path(self) -> str:  # Root path (filesystem root)
        "Provider identifier."
    
    def root_path(self) -> str:  # Root path (filesystem root)
            """Root path for this provider."""
            return "/"
    
        @property
        def path_separator(self) -> str:  # Path separator
        "Root path for this provider."
    
    def path_separator(self) -> str:  # Path separator
            """Path separator character."""
            return os.sep
        
        def _get_file_info(
            self,
            path: Path  # Path object
        ) -> Optional[FileInfo]:  # FileInfo or None on error
        "Path separator character."
    
    def list_directory(
            self,
            path: str  # Directory path to list
        ) -> DirectoryListing:  # Directory contents
        "List contents of a directory."
    
    async def list_directory_async(
            self,
            path: str  # Directory path to list
        ) -> DirectoryListing:  # Directory contents
        "Async list contents of a directory."
    
    def get_file_info(
            self,
            path: str  # Path to file/directory
        ) -> Optional[FileInfo]:  # FileInfo or None if not found
        "Get metadata for a single file/directory."
    
    def get_parent_path(
            self,
            path: str  # Current path
        ) -> Optional[str]:  # Parent path, or None if at root
        "Get parent directory path."
    
    def join_path(
            self,
            base: str,   # Base path
            *parts: str  # Path parts to join
        ) -> str:  # Joined path
        "Join path components."
    
    def normalize_path(
            self,
            path: str  # Path to normalize
        ) -> str:  # Normalized/resolved path
        "Normalize/resolve a path."
    
    def is_valid_path(
            self,
            path: str  # Path to validate
        ) -> Tuple[bool, Optional[str]]:  # (valid, error_message)
        "Validate path."
    
    def path_exists(
            self,
            path: str  # Path to check
        ) -> bool:  # True if path exists
        "Check if path exists."
    
    def is_directory(
            self,
            path: str  # Path to check
        ) -> bool:  # True if path is a directory
        "Check if path is a directory."
    
    def get_home_path(self) -> str:  # User's home directory
        "Get the user's home directory."

Models (models.ipynb)

Core data models for the file browser including DirectoryListing, BrowserSelection, and BrowserState.

Import

from cjm_fasthtml_file_browser.core.models import (
    DirectoryListing,
    BrowserSelection,
    BrowserState
)

Classes

@dataclass
class DirectoryListing:
    "Result of listing a directory."
    
    path: str  # Current directory path
    items: List[FileInfo]  # Directory contents
    parent_path: Optional[str]  # Parent directory (None if at root)
    provider_name: str = 'local'  # Source provider
    total_items: int = 0  # Total count (for pagination)
    error: Optional[str]  # Error message if listing failed
    
@dataclass
class BrowserSelection:
    "Current selection state."
    
    selected_paths: List[str] = field(...)  # Selected file paths
    last_selected: Optional[str]  # Most recently selected (for shift-click)
    
    def add(
            self,
            path: str  # Path to add to selection
        ) -> None:  # Modifies selection in place
        "Add a path to the selection."
    
    def remove(
            self,
            path: str  # Path to remove from selection
        ) -> None:  # Modifies selection in place
        "Remove a path from the selection."
    
    def clear(self) -> None:  # Modifies selection in place
            """Clear all selections."""
            self.selected_paths.clear()
            self.last_selected = None
    
        def toggle(
            self,
            path: str  # Path to toggle
        ) -> None:  # Modifies selection in place
        "Clear all selections."
    
    def toggle(
            self,
            path: str  # Path to toggle
        ) -> None:  # Modifies selection in place
        "Toggle selection of a path."
    
    def is_selected(
            self,
            path: str  # Path to check
        ) -> bool:  # True if path is selected
        "Check if a path is selected."
    
    def set_single(
            self,
            path: str  # Path to set as single selection
        ) -> None:  # Modifies selection in place
        "Set a single path as the only selection (for single-select mode)."
@dataclass
class BrowserState:
    "Complete browser state for persistence/restore."
    
    current_path: str  # Current directory path
    selection: BrowserSelection = field(...)  # Selection state
    sort_by: str = 'name'  # Sort field
    sort_descending: bool = False  # Sort direction
    filter_extensions: Optional[List[str]]  # Active extension filter
    
    def to_dict(self) -> Dict[str, Any]:  # Serializable dictionary
            """Convert state to a serializable dictionary."""
            return {
                "current_path": self.current_path,
        "Convert state to a serializable dictionary."
    
    def from_dict(
            cls,
            data: Dict[str, Any]  # Dictionary with state data
        ) -> "BrowserState":  # Restored BrowserState instance
        "Create a BrowserState from a dictionary."

Path Bar (path_bar.ipynb)

Path display, breadcrumbs navigation, and optional path input for the file browser.

Import

from cjm_fasthtml_file_browser.components.path_bar import (
    parse_path_segments,
    render_breadcrumbs,
    render_path_input,
    render_nav_buttons,
    render_path_bar
)

Functions

def parse_path_segments(
    path: str,                    # Full path to parse
    separator: str = "/"          # Path separator
) -> List[Tuple[str, str]]:  # List of (name, full_path) tuples
    "Parse a path into breadcrumb segments."
def render_breadcrumbs(
    current_path: str,                      # Current directory path
    navigate_url: str,                      # URL for navigation
    hx_target: Optional[str] = None,        # HTMX target for swaps
    max_segments: int = 5,                  # Max segments to show (0 = all)
    breadcrumbs_id: Optional[str] = None,   # HTML ID for breadcrumbs
) -> Any:  # Breadcrumbs component
    "Render path as breadcrumb navigation."
def render_path_input(
    current_path: str,                      # Current path to display
    navigate_url: str,                      # URL for navigation
    hx_target: Optional[str] = None,        # HTMX target for swaps
    input_id: Optional[str] = None,         # HTML ID for input
) -> Any:  # Path input component
    "Render a text input for direct path entry."
def render_nav_buttons(
    parent_path: Optional[str],             # Parent directory path (None if at root)
    home_path: str,                         # Home directory path
    navigate_url: str,                      # URL for navigation
    refresh_url: Optional[str] = None,      # URL for refresh (if different)
    hx_target: Optional[str] = None,        # HTMX target for swaps
) -> Any:  # Navigation buttons component
    "Render quick navigation buttons."
def render_path_bar(
    current_path: str,                      # Current directory path
    parent_path: Optional[str],             # Parent directory path
    home_path: str,                         # Home directory path
    config: FileBrowserConfig,              # Browser configuration
    navigate_url: str,                      # URL for navigation
    refresh_url: Optional[str] = None,      # URL for refresh
    hx_target: Optional[str] = None,        # HTMX target for swaps
    path_bar_id: Optional[str] = None,      # HTML ID for path bar
) -> Any:  # Path bar component
    "Render the complete path bar."

Protocols (protocols.ipynb)

Protocol definitions for extensible file system providers.

Import

from cjm_fasthtml_file_browser.core.protocols import (
    FileSystemProvider
)

Classes

@runtime_checkable
class FileSystemProvider(Protocol):
    "Protocol for file system access backends."
    
    def name(self) -> str:  # Provider identifier (e.g., 'local', 's3', 'gdrive')
            """Provider identifier."""
            ...
    
        @property
        def root_path(self) -> str:  # Root path for this provider
        "Provider identifier."
    
    def root_path(self) -> str:  # Root path for this provider
            """Root path for this provider."""
            ...
    
        @property
        def path_separator(self) -> str:  # Path separator character
        "Root path for this provider."
    
    def path_separator(self) -> str:  # Path separator character
            """Path separator character."""
            ...
    
        def list_directory(
            self,
            path: str  # Directory path to list
        ) -> DirectoryListing:  # Directory contents and metadata
        "Path separator character."
    
    def list_directory(
            self,
            path: str  # Directory path to list
        ) -> DirectoryListing:  # Directory contents and metadata
        "List contents of a directory."
    
    async def list_directory_async(
            self,
            path: str  # Directory path to list
        ) -> DirectoryListing:  # Directory contents and metadata
        "Async list contents of a directory."
    
    def get_file_info(
            self,
            path: str  # Path to file/directory
        ) -> Optional[FileInfo]:  # FileInfo or None if not found
        "Get metadata for a single file/directory."
    
    def get_parent_path(
            self,
            path: str  # Current path
        ) -> Optional[str]:  # Parent path, or None if at root
        "Get parent directory path."
    
    def join_path(
            self,
            base: str,   # Base path
            *parts: str  # Path parts to join
        ) -> str:  # Joined path
        "Join path components."
    
    def normalize_path(
            self,
            path: str  # Path to normalize
        ) -> str:  # Normalized/resolved path
        "Normalize/resolve a path."
    
    def is_valid_path(
            self,
            path: str  # Path to validate
        ) -> Tuple[bool, Optional[str]]:  # (valid, error_message)
        "Validate path, return (valid, error_message)."
    
    def path_exists(
            self,
            path: str  # Path to check
        ) -> bool:  # True if path exists
        "Check if path exists."
    
    def is_directory(
            self,
            path: str  # Path to check
        ) -> bool:  # True if path is a directory
        "Check if path is a directory."

Utils (utils.ipynb)

Sorting and filtering utilities for file listings.

Import

from cjm_fasthtml_file_browser.components.utils import (
    sort_files,
    filter_files
)

Functions

def sort_files(
    files: List[FileInfo],           # Files to sort
    sort_by: str = "name",           # Sort field
    descending: bool = False,        # Sort direction
    folders_first: bool = True       # Sort folders before files
) -> List[FileInfo]:  # Sorted file list
    "Sort files by the specified field."
def filter_files(
    files: List[FileInfo],           # Files to filter
    filter_config: FilterConfig      # Filter configuration
) -> List[FileInfo]:  # Filtered file list
    "Filter files based on configuration."

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cjm_fasthtml_file_browser-0.0.10.tar.gz (35.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cjm_fasthtml_file_browser-0.0.10-py3-none-any.whl (34.6 kB view details)

Uploaded Python 3

File details

Details for the file cjm_fasthtml_file_browser-0.0.10.tar.gz.

File metadata

File hashes

Hashes for cjm_fasthtml_file_browser-0.0.10.tar.gz
Algorithm Hash digest
SHA256 f097c2a2bd9133d5af7435413e148426e3de82e2d7803ef3f0d29f9d4f7a9976
MD5 2d436afedfa630de148e2072b005d489
BLAKE2b-256 30e1d3a613b6dab9af212dd7539e4a045fe7ba8df52d01d7dcef7dd775a79f1e

See more details on using hashes here.

File details

Details for the file cjm_fasthtml_file_browser-0.0.10-py3-none-any.whl.

File metadata

File hashes

Hashes for cjm_fasthtml_file_browser-0.0.10-py3-none-any.whl
Algorithm Hash digest
SHA256 4ee72d86bdd1da1552045ab438f1b665a2eda0d0b80bc2f307298b7de729af78
MD5 520d3dc3c615979afb35d8db1ee63f75
BLAKE2b-256 ce8726670738a3679920dda1fab84eb9611e675fb1904570f6a646be67f6248c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page