Metadata-Version: 2.4
Name: cjm-fasthtml-keyboard-navigation
Version: 0.0.22
Summary: A declarative keyboard navigation framework for FastHTML applications with multi-zone focus management, mode switching, and HTMX integration.
Author-email: "Christian J. Mills" <9126128+cj-mills@users.noreply.github.com>
License: Apache-2.0
Project-URL: Repository, https://github.com/cj-mills/cjm-fasthtml-keyboard-navigation
Project-URL: Documentation, https://cj-mills.github.io/cjm-fasthtml-keyboard-navigation
Keywords: nbdev,jupyter,notebook,python
Classifier: Natural Language :: English
Classifier: Intended Audience :: Developers
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: python-fasthtml==0.13.4
Requires-Dist: cjm_fasthtml_tailwind
Requires-Dist: cjm_fasthtml_daisyui
Requires-Dist: cjm_fasthtml_lucide_icons
Requires-Dist: cjm_fasthtml_design_system>=0.0.8
Dynamic: license-file

# cjm-fasthtml-keyboard-navigation


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

## Install

``` bash
pip install cjm_fasthtml_keyboard_navigation
```

## Project Structure

    nbs/
    ├── components/ (3)
    │   ├── hints.ipynb        # Components for displaying keyboard shortcut hints to users.
    │   ├── hints_modal.ipynb  # Modal-based keyboard shortcut reference with scannable grouped layout and `?` key trigger.
    │   └── system.ipynb       # High-level API for rendering complete keyboard navigation systems.
    ├── core/ (6)
    │   ├── actions.ipynb      # Declarative keyboard action bindings supporting HTMX triggers and JS callbacks.
    │   ├── focus_zone.ipynb   # Configuration for focusable containers with navigable items.
    │   ├── key_mapping.ipynb  # Configurable key-to-direction mappings for customizable navigation keys.
    │   ├── manager.ipynb      # Coordinates keyboard navigation across multiple zones, modes, and actions.
    │   ├── modes.ipynb        # Configuration for keyboard modes that change navigation and action behavior.
    │   └── navigation.ipynb   # Protocols and implementations for keyboard navigation within focus zones.
    ├── htmx/ (2)
    │   ├── buttons.ipynb  # Generate hidden HTMX action buttons triggered by keyboard events.
    │   └── inputs.ipynb   # Generate hidden inputs for HTMX integration with keyboard navigation.
    └── js/ (3)
        ├── coordinator.ipynb  # Global coordinator for hierarchical keyboard system management with single-listener event dispatch.
        ├── generators.ipynb   # Generate complete keyboard navigation JavaScript from configuration.
        └── utils.ipynb        # Core JavaScript utility generators for keyboard navigation.

Total: 14 notebooks across 4 directories

## Module Dependencies

``` mermaid
graph LR
    components_hints[components.hints<br/>Keyboard Hints]
    components_hints_modal[components.hints_modal<br/>Keyboard Hints Modal]
    components_system[components.system<br/>Keyboard System]
    core_actions[core.actions<br/>Key Actions]
    core_focus_zone[core.focus_zone<br/>Focus Zone]
    core_key_mapping[core.key_mapping<br/>Key Mapping]
    core_manager[core.manager<br/>Zone Manager]
    core_modes[core.modes<br/>Keyboard Modes]
    core_navigation[core.navigation<br/>Navigation Patterns]
    htmx_buttons[htmx.buttons<br/>Action Buttons]
    htmx_inputs[htmx.inputs<br/>Hidden Inputs]
    js_coordinator[js.coordinator<br/>Keyboard Coordinator]
    js_generators[js.generators<br/>Script Generators]
    js_utils[js.utils<br/>JavaScript Utilities]

    components_hints --> core_navigation
    components_hints --> core_key_mapping
    components_hints --> core_manager
    components_hints --> core_actions
    components_hints --> core_focus_zone
    components_hints_modal --> components_hints
    components_hints_modal --> core_key_mapping
    components_hints_modal --> core_navigation
    components_hints_modal --> core_manager
    components_hints_modal --> core_actions
    components_hints_modal --> core_focus_zone
    components_system --> htmx_inputs
    components_system --> js_generators
    components_system --> core_manager
    components_system --> components_hints
    components_system --> core_actions
    components_system --> htmx_buttons
    components_system --> core_focus_zone
    core_actions --> core_key_mapping
    core_focus_zone --> core_navigation
    core_manager --> core_navigation
    core_manager --> core_modes
    core_manager --> core_key_mapping
    core_manager --> core_actions
    core_manager --> core_focus_zone
    core_modes --> core_navigation
    htmx_buttons --> core_manager
    htmx_buttons --> core_actions
    htmx_buttons --> core_focus_zone
    htmx_inputs --> core_manager
    htmx_inputs --> core_focus_zone
    js_generators --> core_manager
    js_generators --> js_coordinator
    js_generators --> core_actions
    js_generators --> core_focus_zone
    js_generators --> js_utils
```

*36 cross-module dependencies detected*

## CLI Reference

No CLI commands found in this project.

## Module Overview

Detailed documentation for each module in the project:

### Key Actions (`actions.ipynb`)

> Declarative keyboard action bindings supporting HTMX triggers and JS
> callbacks.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.core.actions import (
    KeyAction
)
```

#### Classes

``` python
@dataclass
class KeyAction:
    "A keyboard shortcut binding."
    
    key: str  # JavaScript key name (e.g., "Enter", " ", "ArrowUp")
    modifiers: frozenset[str] = field(...)
    htmx_trigger: Optional[str]  # ID of hidden button to click
    js_callback: Optional[str]  # JS function name to call
    mode_enter: Optional[str]  # mode name to enter
    mode_exit: bool = False  # exit current mode (return to default)
    prevent_default: bool = True  # call e.preventDefault()
    stop_propagation: bool = False  # call e.stopPropagation()
    zone_ids: Optional[tuple[str, ...]]  # only in these zones (None = all)
    mode_names: Optional[tuple[str, ...]]  # only in these modes (None = all)
    not_modes: Optional[tuple[str, ...]]  # not in these modes
    custom_condition: Optional[str]  # raw JS expression for additional conditions
    description: str = ''  # human-readable description for hints
    hint_group: str = 'General'  # grouping for keyboard hints display
    show_in_hints: bool = True  # whether to show in keyboard hints
    
    def matches_context(
            self,
            zone_id: str,  # current active zone
            mode_name: str  # current mode
        ) -> bool:         # True if action is valid in this context
        "Check if action is valid for given zone and mode."
    
    def is_documentation_only(self) -> bool:  # True if no action path is set (advisory hint only)
            """Check if this is a documentation-only KeyAction (no handler fires).
            
            Documentation-only actions appear in keyboard hints but do not trigger
            HTMX, JS callbacks, or mode transitions. Useful for documenting purely
            client-side keyboard interactions (e.g., text-selector caret movement
            implemented as a separate event listener).
            """
            return (
                self.htmx_trigger is None
                and self.js_callback is None
                and self.mode_enter is None
                and not self.mode_exit
            )
    
        def get_display_key(self) -> str: # formatted key combo for display
        "Check if this is a documentation-only KeyAction (no handler fires).

Documentation-only actions appear in keyboard hints but do not trigger
HTMX, JS callbacks, or mode transitions. Useful for documenting purely
client-side keyboard interactions (e.g., text-selector caret movement
implemented as a separate event listener)."
    
    def get_display_key(self) -> str: # formatted key combo for display
            """Get formatted key combination for display."""
            return format_key_combo(self.key, self.modifiers)
    
        def to_js_config(self) -> dict: # JavaScript-compatible configuration
        "Get formatted key combination for display."
    
    def to_js_config(self) -> dict: # JavaScript-compatible configuration
            """Convert to JavaScript configuration object."""
            return {
                "key": self.key,
        "Convert to JavaScript configuration object."
    
    def documentation_only(
            cls,
            key: str,                                       # JavaScript key name (e.g., "ArrowLeft")
            description: str,                               # human-readable description for hints
            *,
            modifiers: frozenset[str] = frozenset(),        # required modifiers
            zone_ids: Optional[tuple[str, ...]] = None,     # restrict to these zones
            mode_names: Optional[tuple[str, ...]] = None,   # restrict to these modes
            not_modes: Optional[tuple[str, ...]] = None,    # not in these modes
            hint_group: str = "General",                    # hint group label
        ) -> "KeyAction":                                   # KeyAction that appears in hints only
        "Create a KeyAction that ONLY appears in keyboard hints — no handler fires.

Use for documenting client-side-only key interactions (e.g., a text-selector
that handles ArrowLeft / ArrowRight via its own DOM event listener — the
keyboard-navigation library shouldn't fire any action, but the user should
still see those keys in the hints modal).

The returned action has all action paths unset (no htmx_trigger, js_callback,
mode_enter, or mode_exit) and explicitly disables prevent_default and
stop_propagation so the client-side handler receives the event unaltered."
```

### Action Buttons (`buttons.ipynb`)

> Generate hidden HTMX action buttons triggered by keyboard events.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.htmx.buttons import (
    build_htmx_trigger,
    render_action_button,
    render_action_buttons
)
```

#### Functions

``` python
def build_htmx_trigger(
    key: str,                           # JavaScript key name
    modifiers: frozenset[str] = frozenset(),  # modifier keys
    input_selector: str = "input, textarea, select, [contenteditable]"  # input elements to exclude
) -> str:                               # HTMX trigger expression
    "Build HTMX trigger expression for keyboard event."
```

``` python
def render_action_button(
    action: KeyAction,           # the action configuration
    url: str,                    # POST URL for the action
    target: str,                 # HTMX target selector
    include: str = "",           # hx-include selector
    swap: str = "outerHTML",     # hx-swap value
    vals: dict | None = None,    # hx-vals dictionary (JSON values to include in request)
    use_htmx_trigger: bool = False,  # use hx-trigger (False = JS triggerClick only)
    input_selector: str = "input, textarea, select, [contenteditable]"  # inputs to exclude from trigger
) -> Button | None:              # hidden button or None if not HTMX action
    "Render a hidden HTMX button for a keyboard action."
```

``` python
def render_action_buttons(
    manager: ZoneManager,                         # the zone manager configuration
    url_map: dict[str, str],                      # action button ID -> URL
    target_map: dict[str, str],                   # action button ID -> target selector
    include_map: dict[str, str] | None = None,    # action button ID -> include selector
    swap_map: dict[str, str] | None = None,       # action button ID -> swap value
    vals_map: dict[str, dict] | None = None,      # action button ID -> hx-vals dict
    use_htmx_triggers: bool = False,              # use hx-trigger (False = JS triggerClick only)
    container_id: str = "kb-action-buttons"       # container element ID
) -> Div:                                         # container with all action buttons
    "Render all hidden HTMX action buttons for keyboard navigation."
```

### Keyboard Coordinator (`coordinator.ipynb`)

> Global coordinator for hierarchical keyboard system management with
> single-listener event dispatch.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.js.coordinator import (
    js_coordinator_setup
)
```

#### Functions

``` python
def js_coordinator_setup() -> str: # JavaScript coordinator singleton code
    "Generate the global keyboard coordinator singleton."
```

### Focus Zone (`focus_zone.ipynb`)

> Configuration for focusable containers with navigable items.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.core.focus_zone import (
    FocusZone
)
```

#### Classes

``` python
@dataclass
class FocusZone:
    "A focusable container with navigable items."
    
    id: str  # HTML element ID of the container
    label: Optional[str]  # human-readable label for keyboard-hints display (falls back to id when None)
    item_selector: Optional[str]  # CSS selector for items (None = scroll only)
    navigation: Union[NavigationPattern, LinearVertical] = field(...)
    navigation_throttle_ms: int = 0  # minimum ms between navigation events (0 = no throttle)
    item_focus_classes: tuple[str, ...] = (str(ring(2)), str(ring_dui.primary))  # CSS classes for focused item
    item_focus_attribute: str = 'data-focused'  # attribute set to "true" on focused item
    zone_focus_classes: tuple[str, ...] = (str(ring(2)), str(ring_dui.primary), str(inset_ring(2)))
    data_attributes: tuple[str, ...] = ()  # data attributes to extract from focused item
    on_focus_change: Optional[str]  # called when focused item changes
    on_navigate: Optional[str]  # called on any navigation (for side effects like audition)
    on_zone_enter: Optional[str]  # called when zone becomes active
    on_zone_leave: Optional[str]  # called when zone loses focus
    scroll_behavior: str = 'smooth'  # "smooth" or "auto"
    scroll_block: str = 'nearest'  # "start", "center", "end", "nearest"
    hidden_input_prefix: str = ''  # prefix for auto-generated hidden input IDs
    initial_index: int = 0  # initial focused item index
    
    def has_items(self) -> bool: # True if zone has selectable items
            """Check if zone has selectable items."""
            return self.item_selector is not None
    
        def get_display_label(self) -> str: # human-readable label, falling back to id
        "Check if zone has selectable items."
    
    def get_display_label(self) -> str: # human-readable label, falling back to id
            """Get the label for keyboard-hints display, falling back to id when label is None."""
            return self.label if self.label is not None else self.id
    
        def get_hidden_input_id(
            self,
            attr: str  # the data attribute name
        ) -> str:      # the hidden input element ID
        "Get the label for keyboard-hints display, falling back to id when label is None."
    
    def get_hidden_input_id(
            self,
            attr: str  # the data attribute name
        ) -> str:      # the hidden input element ID
        "Get the hidden input ID for a data attribute."
    
    def to_js_config(self) -> dict: # JavaScript-compatible configuration
            """Convert to JavaScript configuration object."""
            return {
                "id": self.id,
        "Convert to JavaScript configuration object."
```

### Script Generators (`generators.ipynb`)

> Generate complete keyboard navigation JavaScript from configuration.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.js.generators import (
    js_zone_state,
    js_focus_management,
    js_zone_switching,
    js_navigation,
    js_mode_management,
    js_action_dispatch,
    js_keyboard_handler,
    js_state_notification,
    js_initialization,
    js_global_api,
    generate_keyboard_script
)
```

#### Functions

``` python
def js_zone_state() -> str: # JavaScript state and getter/setter code
    "Generate JavaScript code for zone state management."
```

``` python
def js_focus_management() -> str: # JavaScript focus management code
    "Generate JavaScript code for focus management."
```

``` python
def js_zone_switching() -> str: # JavaScript zone switching code
    "Generate JavaScript code for zone switching."
```

``` python
def js_navigation() -> str: # JavaScript navigation code
    """Generate JavaScript code for item navigation."""
    return '''
// === Navigation ===
// Track last navigation time per zone for throttling
let lastNavigationTime = {};

function getNavigationPattern(zoneId) {
    // Check if mode overrides navigation
    const modeConfig = getModeConfig(currentMode);
    if (modeConfig && modeConfig.navigationOverride) {
        return modeConfig.navigationOverride;
    }
    // Use zone's pattern
    const zone = getZoneConfig(zoneId);
    return zone ? zone.navigationPattern : 'linear_vertical';
    "Generate JavaScript code for item navigation."
```

``` python
def js_mode_management() -> str: # JavaScript mode management code
    "Generate JavaScript code for mode management."
```

``` python
def js_action_dispatch() -> str: # JavaScript action dispatch code
    "Generate JavaScript code for action dispatch."
```

``` python
def js_keyboard_handler() -> str: # JavaScript keyboard handler code
    "Generate JavaScript code for keyboard event handling."
```

``` python
def js_state_notification() -> str: # JavaScript state notification code
    "Generate JavaScript code for state change notification."
```

``` python
def js_initialization() -> str: # JavaScript initialization code
    "Generate JavaScript code for initialization with focus recovery."
```

``` python
def js_global_api() -> str:  # JavaScript global API exposure code
    "Generate JavaScript code to expose control functions globally."
```

``` python
def generate_keyboard_script(
    manager: ZoneManager  # the zone manager configuration
) -> str:                 # complete JavaScript code wrapped in IIFE
    "Generate complete keyboard navigation JavaScript from ZoneManager."
```

### Keyboard Hints (`hints.ipynb`)

> Components for displaying keyboard shortcut hints to users.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.components.hints import (
    NAV_ICON_MAP,
    KEY_ICON_MAP,
    get_key_icon,
    render_hint_badge,
    create_nav_icon_hint,
    create_modifier_key_hint,
    render_hint_group,
    group_actions_by_hint_group,
    group_actions_by_zone_and_hint_group,
    mode_context_label,
    derive_navigation_hints,
    render_hints_from_actions,
    render_keyboard_hints
)
```

#### Functions

``` python
def get_key_icon(
    key_name: str,                      # key name to look up (case-insensitive)
    size: int = icons.dense_inline      # icon size (V11 dense_inline role)
) -> FT | None:                         # icon component or None if no icon mapping
    "Get a lucide icon for a key name, if one exists."
```

``` python
def render_hint_badge(
    key_display: Union[str, FT],  # formatted key string or icon component
    description: str,              # action description
    style: str = "ghost",          # badge style (ghost, outline, soft, dash)
    auto_icon: bool = False        # auto-convert known keys to icons
) -> Div:                          # hint badge component
    "Render a single keyboard hint as a badge."
```

``` python
def create_nav_icon_hint(
    icon_name: str,      # lucide icon name (e.g., "arrow-down-up")
    description: str,    # action description
    style: str = "ghost" # badge style
) -> Div:                # hint badge with icon
    "Create a hint badge with a lucide icon."
```

``` python
def create_modifier_key_hint(
    modifier: str,       # modifier key name (e.g., "shift", "ctrl")
    key_icon_or_text: Union[str, FT],  # the main key icon or text
    description: str,    # action description
    style: str = "ghost" # badge style
) -> Div:                # hint badge with modifier + key
    "Create a hint badge with a modifier key and main key."
```

``` python
def render_hint_group(
    group_name: str,         # group header text
    hints: list[tuple[str, str]],  # list of (key_display, description) tuples
    badge_style: str = "ghost"     # badge style for this group
) -> Div:                    # group container with header and hints
    "Render a group of related keyboard hints."
```

``` python
def group_actions_by_hint_group(
    actions: tuple[KeyAction, ...]  # actions to group
) -> dict[str, list[KeyAction]]:    # grouped actions
    "Group actions by their hint_group attribute."
```

``` python
def group_actions_by_zone_and_hint_group(
    manager: ZoneManager,  # the zone manager whose actions to group
) -> list[tuple[Optional[str], str, list[KeyAction]]]:  # ordered (zone_label_or_None, hint_group, actions) tuples
    """
    Group actions for hint display, scoped by zone and hint_group.
    
    Returns an ordered list of (zone_label, hint_group, actions) tuples:
    
    - **Shared section** (zone_label=None) appears FIRST, containing actions
      with zone_ids=None (truly global) or zone_ids covering all zones in the
      manager. Single-zone managers route all actions through this section,
      preserving single-zone consumer rendering (no zone-label prefix).
    - **Per-zone sections** follow, in the order zones are declared on the
      manager. zone_label is FocusZone.get_display_label() (label, falling
      back to id). Actions with zone_ids matching exactly one zone land here.
    - **Within each section**, hint_groups appear in insertion (first-seen)
      order. Actions are emitted in their original tuple order.
    
    Actions with show_in_hints=False or empty description are excluded.
    
    Edge cases:
    - Multi-zone partial coverage (zone_ids touches >1 zone but not all):
      routed to shared. Rare in practice; documents the action as shared.
    - zone_ids referencing a zone not in manager.zones: silently dropped.
    """
```

``` python
def mode_context_label(
    action: KeyAction,  # action whose mode constraints to summarize
) -> Optional[str]:     # short chip-friendly label, or None for unrestricted actions
    """
    Derive a short mode-context label from a KeyAction's mode constraints.
    
    Returns None when the action has no mode restrictions (works in any mode —
    no chip should render). Returns the mode name(s) when mode_names is set.
    Returns 'default' when not_modes is set (action is excluded from specified
    modes, so it fires in the default mode).
    
    Examples:
        mode_names=("split",)             -> "split"
        mode_names=("token-select",)      -> "token-select"
        mode_names=("split", "edit")      -> "split + edit"
        not_modes=("split",)              -> "default"
        no mode constraints               -> None
    """
```

``` python
def derive_navigation_hints(
    manager: ZoneManager,  # the zone manager whose navigation to derive hints from
) -> list[tuple[str, str]]:  # ordered (display_key, description) tuples
    """
    Derive built-in navigation hint rows from manager.key_mapping + zone patterns.
    
    Walks every zone with `has_items()` true, unions the navigable directions
    via each zone's `navigation.get_supported_directions()`, and emits hint
    rows using the actual keys from `manager.key_mapping`. Replaces the
    earlier hardcoded `↑/↓ Navigate items` row, which was wrong under custom
    key_mappings (wasd, vim, etc.).
    
    Returns rows for each direction pair (up/down, left/right) whose keys are
    *actually* bound and *actually* used by some zone:
    
    - **Vertical pair** (up/down): emitted when any zone has a pattern that
      supports up/down navigation. Display uses `key_mapping.up[0]` /
      `key_mapping.down[0]`.
    - **Horizontal pair** (left/right): emitted when any zone supports
      left/right navigation, UNLESS the in-zone horizontal keys collide with
      the manager's zone-switch keys (prev_zone_key/next_zone_key). In that
      case the zone-switch row already documents those keys; emitting a
      second row would be misleading (the zone-switch path wins at runtime).
    
    Returns an empty list when no zone supports key-based navigation (e.g.,
    all zones are ScrollOnly, or no zone has an item_selector).
    """
```

``` python
def render_hints_from_actions(
    actions: tuple[KeyAction, ...],  # actions to display hints for
    badge_style: str = "ghost"       # badge style
) -> Div:                            # container with all hint groups
    "Render keyboard hints from action configurations."
```

``` python
def render_keyboard_hints(
    manager: ZoneManager,                      # the zone manager
    include_navigation: bool = True,           # include navigation hints
    include_zone_switch: bool = True,          # include zone switching hints
    badge_style: str = "ghost",                # badge style
    container_id: str = "kb-hints",            # container element ID
    use_icons: bool = True                     # use lucide icons for nav hints
) -> Div:                                      # complete hints component
    "Render complete keyboard hints for a zone manager."
```

#### Variables

``` python
NAV_ICON_MAP = {2 items}
KEY_ICON_MAP = {9 items}
```

### Keyboard Hints Modal (`hints_modal.ipynb`)

> Modal-based keyboard shortcut reference with scannable grouped layout
> and `?` key trigger.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.components.hints_modal import (
    render_keyboard_hints_trigger,
    render_keyboard_hints_modal
)
```

#### Functions

``` python
def _render_key_combo(
    display_key: str,  # formatted key combo string (e.g., "Ctrl+Shift+\u2191")
) -> Div:              # container with kbd elements for each key part
    "Render a key combination as a sequence of kbd elements joined by `+`."
```

``` python
def _render_hint_row(
    display_key: str,                       # formatted key combo string
    description: str,                       # action description
    mode_label: Optional[str] = None,        # mode-context chip text (e.g., "split", "default"); None for no chip
) -> Div:                                    # single shortcut row with key, description, and optional mode chip
    "Render a single shortcut row: key combo on left, description (with optional mode chip) on right."
```

``` python
def _render_modal_group(
    group_name: str,                                                   # group header text
    rows: list[tuple[str, str, Optional[str]]],                         # list of (display_key, description, mode_label)
) -> Div:                                                              # group container with header and rows
    """
    Render a group of related shortcuts with a header.
    
    `break_util.inside.avoid_column` keeps the entire group (header + rows)
    in one column inside the modal body's CSS-columns layout — groups never
    split across columns, preserving "form follows function" scannability.
    """
```

``` python
def _render_section_header(
    label: str,  # human-readable section label
) -> Div:        # styled section-header element
    """
    Render a section header for one manager in a multi-manager modal.
    
    Visually distinct from group headers (`_render_modal_group`):
    - Section headers: font-sm + bold + secondary tier + top border + extra spacing
    - Group headers:   font-xs + semibold + muted tier + bottom border (no top)
    
    `break_util.after.avoid` keeps a section header attached to its first
    group inside the CSS-columns layout — prevents the orphan-header case where
    a header lands at the bottom of one column and its first group at the top
    of the next. (`break_util.inside.avoid_column` exists but only applies to
    breaks INSIDE the element; for "don't break right after", `break-after: avoid`
    is the correct CSS property.)
    """
```

``` python
def _render_manager_groups(
    manager: ZoneManager,                # the manager to render groups for
    include_zone_switch: bool = True,    # include zone-switch hint when multi-zone
) -> list[FT]:                           # flat list of group FT elements (no wrapping Div)
    """
    Render the keyboard-shortcut groups for a single ZoneManager.
    
    Composes:
    1. **Manager-derived "Navigation" group**: derived nav rows from
       `derive_navigation_hints(manager)` (via `manager.key_mapping` + each zone's
       `navigation.get_supported_directions()`), plus the Switch-panel row when
       `include_zone_switch=True` and multi-zone. **Plus** any consumer actions
       whose `hint_group == "Navigation"` AND land in the shared section
       (zone_label=None) — they fold into the same group rather than rendering
       a duplicate "Navigation" header underneath the derived rows.
    2. **Zone-aware action groups**: from `group_actions_by_zone_and_hint_group`,
       with `"<zone label> — <hint_group>"` headers for per-zone sections and
       plain `"<hint_group>"` for shared sections (other than Navigation).
    
    Per-zone "Navigation" groups stay separate (they're zone-scoped — distinct
    from the manager-level Navigation row). Only the shared-section Navigation
    rows merge into the manager-derived group.
    
    Returned as a flat list (no wrapping Div) so callers can interleave section
    headers between groups when rendering multi-manager hierarchies.
    """
```

``` python
def _render_modal_body(
    manager: ZoneManager,                            # primary keyboard zone manager
    include_zone_switch: bool = True,                # include zone-switch hint (single-manager: when multi-zone; multi-manager: per-manager)
    include_navigation: bool = True,                 # DEPRECATED: no-op. Built-in nav row derived from key_mapping now.
    child_managers: Optional[Sequence[ZoneManager]] = None,  # additional managers for hierarchical hint display (each renders as a labeled section)
) -> Div:                                            # modal body with grouped shortcuts
    """
    Render the modal body with grouped keyboard shortcuts.
    
    **Single-manager mode** (`child_managers=None`, the common case):
    - Renders one manager's content as a flat list of groups (no section header).
    - Layout: derived "Navigation" group → zone-aware action groups.
    
    **Multi-manager mode** (`child_managers=[...]`, hierarchical keyboard systems):
    - Renders the primary manager as a labeled section (header = `manager.get_display_label()`),
      followed by each child manager as its own labeled section. Used for
      coordinator-based hierarchies where multiple ZoneManagers cooperate
      (e.g., parent + N children pattern in `cjm-fasthtml-keyboard-navigation`'s
      hierarchy demo). Each manager's content composes via `_render_manager_groups`.
    
    Layout details (same in both modes):
    - Each group container has `break-inside: avoid-column` so the CSS-columns
      layout never splits a group across columns.
    - Section headers (multi-manager mode) carry `break-after: avoid`
      to keep each header attached to its first group.
    - Mode-restricted actions get a small chip ("split", "default", etc.)
      derived from `mode_context_label(action)`.
    - Per-manager: shared-section actions with `hint_group="Navigation"` fold
      into the manager-derived Navigation group (no duplicate group headers).
    
    History: an earlier version hardcoded `↑/↓ Navigate items` regardless of
    the manager's actual `key_mapping`. That row was wrong under custom
    mappings (wasd, vim) and was dropped in G4. This version derives the
    nav row from `manager.key_mapping` via `derive_navigation_hints`, which
    is accurate under any KeyMapping configuration.
    """
```

``` python
def render_keyboard_hints_trigger(
    modal_id: str = "kb-hints-modal",             # ID of the modal dialog to open
    icon_size: IconSize = icons.ghost_button,     # lucide icon size (V11.R3 ghost-button: "full" — pairs with V1.modal_disclosure at btn-xs)
) -> Button:                                      # ghost button with keyboard icon
    "Render a keyboard icon button that opens the hints modal."
```

``` python
def _render_question_mark_listener(
    modal_id: str,  # ID of the modal dialog to toggle
) -> Script:        # script element with global `?` key listener
    """
    Render a global `?` key listener that toggles the hints modal.
    
    Uses a named function stored on `window` so that HTMX re-renders
    replace the previous listener instead of accumulating duplicates.
    """
```

``` python
def render_keyboard_hints_modal(
    manager: ZoneManager,                                   # primary keyboard zone manager
    modal_id: str = "kb-hints-modal",                        # HTML ID for the modal dialog
    include_navigation: bool = True,                         # DEPRECATED: no-op kept for backward compat. See _render_modal_body.
    include_zone_switch: bool = True,                        # include zone-switch hint (auto-hidden for single zone)
    enable_question_mark_key: bool = True,                   # add global `?` key listener
    title: str = "Keyboard Shortcuts",                       # modal title text
    child_managers: Optional[Sequence[ZoneManager]] = None,  # child managers for hierarchical hint display (each rendered as a labeled section)
) -> tuple[FT, FT, FT]:                                     # (modal_dialog, trigger_button, question_mark_script)
    """
    Render a modal-based keyboard shortcut reference.
    
    Returns three components:
    - `modal_dialog`: The Dialog element (place anywhere in page)
    - `trigger_button`: Small keyboard icon button (place in step header)
    - `question_mark_script`: Global `?` key listener Script (place in page)
    
    If `enable_question_mark_key` is False, `question_mark_script` is an empty Div.
    
    **Hierarchical hints** (`child_managers=[...]`): when working with multiple
    ZoneManagers coordinated by `window.kbCoordinator` (parent + N children), pass
    the parent as `manager` and the children as `child_managers`. The modal will
    render each as a labeled section using `manager.get_display_label()` for
    section headers. Set `label` on each ZoneManager for human-readable headers;
    falls back to `system_id` otherwise.
    
    Modal width ladder (R2 cap + optimal-space response — see
    layout-system.md M1–M6 modes): grows responsively with viewport. Combined
    with `columns.sm` on the body, this gives 1 column at narrow widths,
    2 columns at laptop full-screen (lg breakpoint with max_w._4xl), and
    3 columns at desktop full-screen (2xl breakpoint with max_w._7xl).
    Modal width is an upper bound; DaisyUI's `modal_box` sizes the actual
    modal to its content within that bound, so short content stays compact.
    """
```

#### Variables

``` python
_BUILTIN_NAV_GROUP = 'Navigation'
```

### Hidden Inputs (`inputs.ipynb`)

> Generate hidden inputs for HTMX integration with keyboard navigation.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.htmx.inputs import (
    render_zone_hidden_inputs,
    render_hidden_inputs,
    build_include_selector,
    build_all_zones_include_selector
)
```

#### Functions

``` python
def render_zone_hidden_inputs(
    zone: FocusZone  # the focus zone configuration
) -> list:           # list of Hidden input components
    "Render hidden inputs for a single zone's data attributes."
```

``` python
def render_hidden_inputs(
    manager: ZoneManager,            # the zone manager configuration
    include_state: bool = False,     # include state tracking inputs
    container_id: str = "kb-hidden-inputs"  # container element ID
) -> Div:                            # container with all hidden inputs
    """
    Render all hidden inputs for keyboard navigation.
    
    Deduplicates inputs by ID - zones with the same hidden_input_prefix
    will share inputs rather than creating duplicates.
    """
```

``` python
def build_include_selector(
    zone: FocusZone,              # the zone to include inputs from
    include_state: bool = False   # include state inputs
) -> str:                         # CSS selector for hx-include
    "Build hx-include selector for zone's hidden inputs."
```

``` python
def build_all_zones_include_selector(
    manager: ZoneManager,         # the zone manager
    include_state: bool = False   # include state inputs
) -> str:                         # CSS selector for all zones
    """
    Build hx-include selector for all zones' hidden inputs.
    
    Deduplicates selectors - zones with the same hidden_input_prefix
    will only include each input once.
    """
```

### Key Mapping (`key_mapping.ipynb`)

> Configurable key-to-direction mappings for customizable navigation
> keys.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.core.key_mapping import (
    ARROW_KEYS,
    WASD_KEYS,
    VIM_KEYS,
    NUMPAD_KEYS,
    ARROWS_AND_WASD,
    ARROWS_AND_VIM,
    KEY_DISPLAY_MAP,
    KeyMapping,
    format_key_for_display,
    format_key_combo
)
```

#### Functions

``` python
def format_key_for_display(
    key: str  # the JavaScript key name
) -> str:     # human-readable display string
    "Format a key name for user display."
```

``` python
def format_key_combo(
    key: str,                        # the main key
    modifiers: frozenset[str] = frozenset() # modifier keys (shift, ctrl, alt, meta)
) -> str:                            # formatted string like "Ctrl+Shift+A"
    "Format a key combination for display."
```

#### Classes

``` python
class KeyMapping:
    "Maps physical keys to navigation directions."
    
    def get_direction(
            self,
            key: str  # the pressed key (e.g., "ArrowUp", "w")
        ) -> str | None: # the direction ("up", "down", "left", "right") or None
        "Get direction for a given key press."
    
    def all_keys(self) -> tuple[str, ...]: # all mapped keys
            """Return all mapped keys."""
            return self.up + self.down + self.left + self.right
    
        def to_js_map(self) -> dict[str, str]: # {key: direction} mapping
        "Return all mapped keys."
    
    def to_js_map(self) -> dict[str, str]: # {key: direction} mapping
            """Convert to JavaScript-compatible key-to-direction map."""
            result = {}
            for key in self.up
        "Convert to JavaScript-compatible key-to-direction map."
```

#### Variables

``` python
ARROW_KEYS
WASD_KEYS
VIM_KEYS
NUMPAD_KEYS
ARROWS_AND_WASD
ARROWS_AND_VIM
KEY_DISPLAY_MAP: dict[str, str]
```

### Zone Manager (`manager.ipynb`)

> Coordinates keyboard navigation across multiple zones, modes, and
> actions.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.core.manager import (
    ZoneManager
)
```

#### Classes

``` python
@dataclass
class ZoneManager:
    "Coordinates keyboard navigation across zones."
    
    zones: tuple[FocusZone, ...]  # all focus zones
    system_id: Optional[str]  # unique ID for coordinator registration (defaults to initial zone ID)
    label: Optional[str]  # human-readable label for keyboard-hints display (falls back to system_id when None)
    prev_zone_key: str = 'ArrowLeft'  # key to switch to previous zone
    next_zone_key: str = 'ArrowRight'  # key to switch to next zone
    zone_switch_modifiers: frozenset[str] = field(...)
    wrap_zones: bool = True  # wrap from last zone to first
    key_mapping: KeyMapping = field(...)
    initial_zone_id: Optional[str]  # defaults to first zone
    modes: tuple[KeyboardMode, ...] = ()  # custom modes (navigation mode is implicit)
    default_mode: str = 'navigation'  # mode to return to after exiting others
    actions: tuple[KeyAction, ...] = ()  # keyboard action bindings
    on_zone_change: Optional[str]  # called when active zone changes
    on_mode_change: Optional[str]  # called when mode changes
    on_state_change: Optional[str]  # called on any state change (for persistence)
    skip_when_input_focused: bool = True  # ignore keys in input/textarea
    input_selector: str = 'input, textarea, select, [contenteditable]'  # elements to skip
    htmx_settle_event: str = 'htmx:afterSettle'  # event to reinitialize on
    expose_state_globally: bool = False  # expose state on window object
    global_state_name: str = 'keyboardNavState'  # name for global state
    state_hidden_inputs: bool = False  # write state to hidden inputs
    
    def get_zone(
            self,
            zone_id: str  # zone ID to find
        ) -> Optional[FocusZone]: # the zone or None
        "Get zone by ID."
    
    def get_initial_zone_id(self) -> str: # the initial zone ID
            """Get initial zone ID."""
            return self.initial_zone_id or self.zones[0].id
    
        def get_display_label(self) -> str: # human-readable label, falling back to system_id
        "Get initial zone ID."
    
    def get_display_label(self) -> str: # human-readable label, falling back to system_id
            """Get the label for keyboard-hints display, falling back to system_id when label is None.
    
            Used by hierarchical hints-modal rendering to label child manager sections
            (`render_keyboard_hints_modal(..., child_managers=[...])`). Set `label` to
            a human-friendly string (e.g., "Alpha List") so the modal's section headers
            read clearly instead of using technical system_id values (e.g., "child-a").
            """
            return self.label if self.label is not None else self.system_id
    
        def get_all_modes(self) -> tuple[KeyboardMode, ...]: # all modes including default
        "Get the label for keyboard-hints display, falling back to system_id when label is None.

Used by hierarchical hints-modal rendering to label child manager sections
(`render_keyboard_hints_modal(..., child_managers=[...])`). Set `label` to
a human-friendly string (e.g., "Alpha List") so the modal's section headers
read clearly instead of using technical system_id values (e.g., "child-a")."
    
    def get_all_modes(self) -> tuple[KeyboardMode, ...]: # all modes including default
            """Get all modes including the default navigation mode."""
            return (NAVIGATION_MODE,) + self.modes
    
        def get_mode(
            self,
            mode_name: str  # mode name to find
        ) -> Optional[KeyboardMode]: # the mode or None
        "Get all modes including the default navigation mode."
    
    def get_mode(
            self,
            mode_name: str  # mode name to find
        ) -> Optional[KeyboardMode]: # the mode or None
        "Get mode by name."
    
    def get_actions_for_context(
            self,
            zone_id: str,  # current zone
            mode_name: str  # current mode
        ) -> list[KeyAction]: # actions valid in this context
        "Get actions valid for given zone and mode."
    
    def get_all_data_attributes(self) -> set[str]: # unique data attributes across all zones
            """Get all unique data attributes from all zones."""
            attrs = set()
            for zone in self.zones
        "Get all unique data attributes from all zones."
    
    def to_js_config(self) -> dict: # JavaScript-compatible configuration
            """Convert to JavaScript configuration object."""
            return {
                "systemId": self.system_id,
        "Convert to JavaScript configuration object."
```

### Keyboard Modes (`modes.ipynb`)

> Configuration for keyboard modes that change navigation and action
> behavior.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.core.modes import (
    NAVIGATION_MODE,
    KeyboardMode
)
```

#### Classes

``` python
@dataclass
class KeyboardMode:
    "A named mode that changes keyboard behavior."
    
    name: str  # unique mode name (e.g., "navigation", "split", "audition")
    enter_key: Optional[str]  # key to enter mode (None = programmatic only)
    enter_modifiers: frozenset[str] = field(...)
    exit_key: str = 'Escape'  # key to exit mode
    exit_modifiers: frozenset[str] = field(...)
    zone_ids: Optional[tuple[str, ...]]  # only available in these zones (None = all)
    navigation_override: Optional[NavigationPattern]  # override zone's navigation pattern
    on_enter: Optional[str]  # called when entering mode
    on_exit: Optional[str]  # called when exiting mode
    indicator_text: Optional[str]  # text shown in UI when mode is active
    exit_on_zone_change: bool = True  # exit mode when switching zones
    
    def is_available_in_zone(
            self,
            zone_id: str  # the zone to check
        ) -> bool:        # True if mode is available in zone
        "Check if mode is available in given zone."
    
    def to_js_config(self) -> dict: # JavaScript-compatible configuration
            """Convert to JavaScript configuration object."""
            return {
                "name": self.name,
        "Convert to JavaScript configuration object."
```

#### Variables

``` python
NAVIGATION_MODE
```

### Navigation Patterns (`navigation.ipynb`)

> Protocols and implementations for keyboard navigation within focus
> zones.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.core.navigation import (
    Direction,
    NavigationPattern,
    LinearVertical,
    LinearHorizontal,
    ScrollOnly,
    Grid
)
```

#### Classes

``` python
@runtime_checkable
class NavigationPattern(Protocol):
    "Protocol for navigation within a focus zone."
    
    def name(self) -> str: # unique identifier for this pattern
            """Return the pattern name."""
            ...
    
        def get_next_index(
            self,
            current: int,      # current focused index
            direction: Direction, # navigation direction
            total: int,        # total number of items
            columns: int = 1   # number of columns (for grid navigation)
        ) -> int:              # the new index after navigation
        "Return the pattern name."
    
    def get_next_index(
            self,
            current: int,      # current focused index
            direction: Direction, # navigation direction
            total: int,        # total number of items
            columns: int = 1   # number of columns (for grid navigation)
        ) -> int:              # the new index after navigation
        "Calculate next index given current position and direction."
    
    def get_supported_directions(self) -> tuple[Direction, ...]: # directions this pattern responds to
        "Return which arrow key directions this pattern handles."
```

``` python
@dataclass
class LinearVertical:
    "Up/Down navigation through a vertical list."
    
    wrap: bool = False  # wrap from last item to first (and vice versa)
    
    def name(self) -> str:
            """Return the pattern name."""
            return "linear_vertical"
    
        def get_supported_directions(self) -> tuple[Direction, ...]: # ("up", "down")
        "Return the pattern name."
    
    def get_supported_directions(self) -> tuple[Direction, ...]: # ("up", "down")
            """Return supported directions."""
            return ("up", "down")
    
        def get_next_index(
            self,
            current: int,      # current focused index
            direction: Direction, # "up" or "down"
            total: int,        # total number of items
            columns: int = 1   # unused for linear navigation
        ) -> int:              # the new index
        "Return supported directions."
    
    def get_next_index(
            self,
            current: int,      # current focused index
            direction: Direction, # "up" or "down"
            total: int,        # total number of items
            columns: int = 1   # unused for linear navigation
        ) -> int:              # the new index
        "Calculate next index for vertical navigation."
```

``` python
@dataclass
class LinearHorizontal:
    "Left/Right navigation through a horizontal list."
    
    wrap: bool = False  # wrap from last item to first (and vice versa)
    
    def name(self) -> str:
            """Return the pattern name."""
            return "linear_horizontal"
    
        def get_supported_directions(self) -> tuple[Direction, ...]: # ("left", "right")
        "Return the pattern name."
    
    def get_supported_directions(self) -> tuple[Direction, ...]: # ("left", "right")
            """Return supported directions."""
            return ("left", "right")
    
        def get_next_index(
            self,
            current: int,      # current focused index
            direction: Direction, # "left" or "right"
            total: int,        # total number of items
            columns: int = 1   # unused for linear navigation
        ) -> int:              # the new index
        "Return supported directions."
    
    def get_next_index(
            self,
            current: int,      # current focused index
            direction: Direction, # "left" or "right"
            total: int,        # total number of items
            columns: int = 1   # unused for linear navigation
        ) -> int:              # the new index
        "Calculate next index for horizontal navigation."
```

``` python
@dataclass
class ScrollOnly:
    "No item navigation, zone is scrollable content only."
    
    def name(self) -> str:
            """Return the pattern name."""
            return "scroll_only"
    
        def get_supported_directions(self) -> tuple[Direction, ...]: # empty tuple
        "Return the pattern name."
    
    def get_supported_directions(self) -> tuple[Direction, ...]: # empty tuple
            """Return no supported directions."""
            return ()
    
        def get_next_index(
            self,
            current: int,      # current index (unused)
            direction: Direction, # direction (unused)
            total: int,        # total items (unused)
            columns: int = 1   # columns (unused)
        ) -> int:              # always returns current
        "Return no supported directions."
    
    def get_next_index(
            self,
            current: int,      # current index (unused)
            direction: Direction, # direction (unused)
            total: int,        # total items (unused)
            columns: int = 1   # columns (unused)
        ) -> int:              # always returns current
        "Return current index unchanged."
```

``` python
@dataclass
class Grid:
    "2D grid navigation (placeholder for future implementation)."
    
    columns: int = 4  # number of columns in the grid
    wrap_horizontal: bool = True  # wrap at row edges
    wrap_vertical: bool = False  # wrap at grid top/bottom
    
    def name(self) -> str:
            """Return the pattern name."""
            return "grid"
    
        def get_supported_directions(self) -> tuple[Direction, ...]: # all four directions
        "Return the pattern name."
    
    def get_supported_directions(self) -> tuple[Direction, ...]: # all four directions
            """Return all four directions."""
            return ("up", "down", "left", "right")
    
        def get_next_index(
            self,
            current: int,      # current focused index
            direction: Direction, # navigation direction
            total: int,        # total number of items
            columns: int = 0   # override columns (0 = use self.columns)
        ) -> int:              # the new index
        "Return all four directions."
    
    def get_next_index(
            self,
            current: int,      # current focused index
            direction: Direction, # navigation direction
            total: int,        # total number of items
            columns: int = 0   # override columns (0 = use self.columns)
        ) -> int:              # the new index
        "Calculate next index for 2D grid navigation."
```

### Keyboard System (`system.ipynb`)

> High-level API for rendering complete keyboard navigation systems.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.components.system import (
    KeyboardSystem,
    render_keyboard_system,
    quick_keyboard_system
)
```

#### Functions

``` python
def _build_auto_include_map(
    manager: ZoneManager,        # the zone manager configuration
    include_state: bool = False  # include state inputs in selector
) -> dict[str, str]:             # action button ID -> include selector
    "Auto-generate include_map based on actions and their zone constraints."
```

``` python
def render_keyboard_system(
    manager: ZoneManager,                         # the zone manager configuration
    url_map: dict[str, str],                      # action button ID -> URL
    target_map: dict[str, str],                   # action button ID -> target selector
    include_map: dict[str, str] | None = None,    # action button ID -> include selector (auto-generated if None)
    swap_map: dict[str, str] | None = None,       # action button ID -> swap value
    vals_map: dict[str, dict] | None = None,      # action button ID -> hx-vals dict
    show_hints: bool = True,                      # render keyboard hints UI
    hints_badge_style: str = "ghost",             # badge style for hints
    include_state_inputs: bool = False            # include state tracking inputs
) -> KeyboardSystem:                              # complete keyboard system
    "Render complete keyboard navigation system."
```

``` python
def quick_keyboard_system(
    zones: tuple[FocusZone, ...],                # focus zones
    actions: tuple[KeyAction, ...],              # keyboard actions
    url_map: dict[str, str],                     # action URLs
    target_map: dict[str, str],                  # action targets
    **kwargs                                     # additional ZoneManager/render options
) -> KeyboardSystem:                             # complete keyboard system
    "Quick setup for simple keyboard navigation."
```

#### Classes

``` python
@dataclass
class KeyboardSystem:
    "Container for all keyboard navigation components."
    
    script: Script  # the keyboard navigation JavaScript
    hidden_inputs: Div  # hidden inputs for HTMX
    action_buttons: Div  # hidden action buttons for HTMX
    hints: Optional[Div]  # optional keyboard hints UI
    
    def all_components(self) -> tuple:  # all components as tuple
            """Return all components for easy unpacking into render."""
            components = [self.script, self.hidden_inputs, self.action_buttons]
            if self.hints
        "Return all components for easy unpacking into render."
```

### JavaScript Utilities (`utils.ipynb`)

> Core JavaScript utility generators for keyboard navigation.

#### Import

``` python
from cjm_fasthtml_keyboard_navigation.js.utils import (
    js_config_from_dict,
    js_input_detection,
    js_focus_ring_helpers,
    js_scroll_into_view,
    js_hidden_input_update,
    js_trigger_click,
    js_get_data_attributes,
    js_get_modifiers,
    js_all_utils
)
```

#### Functions

``` python
def js_config_from_dict(
    config: dict[str, Any],  # Python dict to convert
    var_name: str = "cfg"    # JavaScript variable name
) -> str:                    # JavaScript const declaration
    "Generate JavaScript const declaration from Python dict."
```

``` python
def js_input_detection(
    selector: str = "input, textarea, select, [contenteditable='true']"  # CSS selector for input elements
) -> str:  # JavaScript function definition
    "Generate JavaScript function to detect if input element is focused."
```

``` python
def js_focus_ring_helpers(
    default_classes: tuple[str, ...] = (str(ring(2)), str(ring_dui.primary))  # default focus ring CSS classes
) -> str:  # JavaScript function definitions
    "Generate JavaScript functions for adding/removing focus ring classes."
```

``` python
def js_scroll_into_view(
    behavior: str = "smooth",  # "smooth" or "auto"
    block: str = "nearest"     # "start", "center", "end", "nearest"
) -> str:  # JavaScript function definition
    "Generate JavaScript function to scroll element into view."
```

``` python
def js_hidden_input_update() -> str: # JavaScript function definition
    "Generate JavaScript function to update hidden input values."
```

``` python
def js_trigger_click() -> str: # JavaScript function definition
    "Generate JavaScript function to programmatically click a button."
```

``` python
def js_get_data_attributes() -> str: # JavaScript function definition
    "Generate JavaScript function to extract data attributes from element."
```

``` python
def js_get_modifiers() -> str: # JavaScript function definition
    "Generate JavaScript function to extract modifier keys from event."
```

``` python
def js_all_utils(
    input_selector: str = "input, textarea, select, [contenteditable='true']",  # input element selector
    default_focus_classes: tuple[str, ...] = (str(ring(2)), str(ring_dui.primary)),  # focus ring classes
    scroll_behavior: str = "smooth",  # scroll behavior
    scroll_block: str = "nearest"     # scroll block alignment
) -> str:  # all utility functions combined
    "Generate all JavaScript utility functions."
```
