# cjm-fasthtml-file-browser


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

## Install

``` bash
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

``` mermaid
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_models
    components_browser --> components_path_bar
    components_browser --> components_item
    components_browser --> core_html_ids
    components_browser --> core_config
    components_item --> core_config
    components_item --> core_models
    components_path_bar --> components_item
    components_path_bar --> core_html_ids
    components_path_bar --> core_config
    components_utils --> core_config
    core_protocols --> core_models
    providers_local --> core_models
    providers_local --> core_protocols
    routes_handlers --> components_browser
    routes_handlers --> core_config
    routes_handlers --> providers_local
    routes_handlers --> core_protocols
    routes_handlers --> components_utils
    routes_handlers --> components_item
    routes_handlers --> core_models
```

*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

``` python
from cjm_fasthtml_file_browser.components.browser import (
    render_file_browser
)
```

#### Functions

``` python
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

``` python
_FB_GO_PARENT_CALLBACK = 'fbGoParentDir'
```

### Config (`config.ipynb`)

> Configuration dataclasses and enums for the file browser.

#### Import

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

#### Classes

``` python
class SelectionMode(str, Enum):
    "File selection modes."
```

``` python
class FileColumn(str, Enum):
    "Available columns for list view."
```

``` python
@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
```

``` python
@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."
```

``` python
@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
```

``` python
@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

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

#### Functions

``` python
def _no_selection_oobs(changed_paths: List[str]) -> Tuple:
    """Default no-op for render_selection_oobs."""
    return ()

def _no_update_selection_oobs(selected_paths: List[str], changed_paths: List[str]) -> Tuple
    "Default no-op for render_selection_oobs."
```

``` python
def _no_update_selection_oobs(selected_paths: List[str], changed_paths: List[str]) -> Tuple:
    """Default no-op for update_selection_oobs."""
    return ()

def _no_current_path() -> str
    "Default no-op for update_selection_oobs."
```

``` python
def _no_current_path() -> str:
    """Default no-op for current_path."""
    return ""

def _no_sync_items() -> None
    "Default no-op for current_path."
```

``` python
def _no_sync_items() -> None:
    """Default no-op for sync_items."""
    pass

@dataclass
class FileBrowserRouters
    "Default no-op for sync_items."
```

``` python
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."
```

``` python
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."
```

``` python
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."
```

``` python
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)."
```

``` python
def _handle_toggle_select(
    item: FileInfo,                            # File item to toggle
    row_index: int,                            # Row index in VC items list
    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
    sel_change_accepts_request: bool,          # Whether on_selection_change accepts request param
    columns: Tuple[ColumnDef, ...],            # VC column definitions
    vc_state: VirtualCollectionState,          # VC state (for total_items, cursor)
    vc_ids: VirtualCollectionHtmlIds,          # VC HTML IDs
    render_cell: Callable,                     # Cell renderer callback
    request: Any = None,                       # Optional HTMX request
) -> Any:  # Tuple of OOB elements (checkbox cell + callback extras)
    "Toggle file selection and return targeted OOB checkbox update."
```

``` python
def _build_selection_oobs(
    changed_paths: List[str],              # File/folder paths whose checkbox state changed
    columns: Tuple[ColumnDef, ...],        # VC column definitions
    items: List[FileInfo],                 # Current directory items
    vc_state: VirtualCollectionState,      # VC state (for window bounds)
    vc_ids: VirtualCollectionHtmlIds,      # VC HTML IDs
    render_cell: Callable,                 # Cell renderer callback
) -> Tuple[Any, ...]:  # OOB cell elements for visible items only
    "Return OOB checkbox cell updates for changed paths visible in the browser."
```

``` python
def _sync_and_build_selection_oobs(
    selected_paths: List[str],             # New full selection state (replaces browser selection)
    changed_paths: List[str],              # Paths whose checkbox state changed
    state_getter: Callable[[], BrowserState],  # Function to get current state
    state_setter: Callable[[BrowserState], None],  # Function to save state
    columns: Tuple[ColumnDef, ...],        # VC column definitions
    items: List[FileInfo],                 # Current directory items
    vc_state: VirtualCollectionState,      # VC state (for window bounds)
    vc_ids: VirtualCollectionHtmlIds,      # VC HTML IDs
    render_cell: Callable,                 # Cell renderer callback
) -> Tuple[Any, ...]:  # OOB cell elements for visible changed items
    "Sync selection state into browser and return targeted checkbox OOBs."
```

``` python
def _build_columns(
    config: FileBrowserConfig,  # Browser config
) -> Tuple[ColumnDef, ...]:  # Column definitions for virtual collection
    "Build ColumnDef tuple from browser config, conditionally including checkbox column."
```

``` python
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."
```

``` python
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

``` python
@dataclass
class FileBrowserRouters:
    "Return value from init_router — both routers, URL bundle, render, and OOB helpers."
    
    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
    render_selection_oobs: Callable = field(...)  # (changed_paths) -> Tuple, targeted checkbox OOBs
    update_selection_oobs: Callable = field(...)  # (selected_paths, changed_paths) -> Tuple, sync + OOBs
    current_path: Callable = field(...)  # () -> str, current browsed directory path
    sync_items: Callable = field(...)  # () -> None, rebuild items from current browser state
```

### HTML IDs (`html_ids.ipynb`)

> HTML ID constants for HTMX targeting in the file browser.

#### Import

``` python
from cjm_fasthtml_file_browser.core.html_ids import (
    FileBrowserHtmlIds
)
```

#### Classes

``` python
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

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

#### Functions

``` python
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."
```

``` python
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.
    """
```

``` python
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."
```

``` python
def render_error_state(
    error_message: str  # Error message to display
) -> Any:  # Error state component
    "Render error state for when directory access fails."
```

#### Variables

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

### Local Provider (`local.ipynb`)

> Local file system provider for interactive directory navigation.

#### Import

``` python
from cjm_fasthtml_file_browser.providers.local import (
    LocalFileSystemProvider
)
```

#### Classes

``` python
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

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

#### Classes

``` python
@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
    
```

``` python
@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)."
```

``` python
@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

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

#### Functions

``` python
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."
```

``` python
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."
```

``` python
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."
```

``` python
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."
```

``` python
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

``` python
from cjm_fasthtml_file_browser.core.protocols import (
    FileSystemProvider
)
```

#### Classes

``` python
@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

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

#### Functions

``` python
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."
```

``` python
def filter_files(
    files: List[FileInfo],           # Files to filter
    filter_config: FilterConfig      # Filter configuration
) -> List[FileInfo]:  # Filtered file list
    "Filter files based on configuration."
```
