keyboard_config

Alignment-specific keyboard building blocks for assembly into a shared ZoneManager

Keyboard Parts Builder

Returns (zone, actions, modes) tuple for assembly into a shared ZoneManager by the combined-level keyboard config. No sub-modes needed (unlike decomp’s split mode).


create_align_kb_parts


def create_align_kb_parts(
    ids:CardStackHtmlIds, # Card stack HTML IDs
    button_ids:CardStackButtonIds, # Card stack button IDs for navigation
    config:CardStackConfig, # Card stack configuration
)->Tuple: # (zone, actions, modes)

Create alignment-specific keyboard building blocks.

# Speed cycle KeyActions wire correctly into the alignment zone
from cjm_fasthtml_card_stack.core.html_ids import CardStackHtmlIds as _IDs
from cjm_fasthtml_card_stack.core.button_ids import CardStackButtonIds as _BtnIds
from cjm_fasthtml_card_stack.core.config import CardStackConfig as _Cfg

_zone, _actions, _modes = create_align_kb_parts(
    ids=_IDs(prefix="align-cs"),
    button_ids=_BtnIds(prefix="align-cs"),
    config=_Cfg(),
)

_by_key = {(a.key, frozenset(a.modifiers)): a for a in _actions}

_up = _by_key.get(("ArrowUp", frozenset({"shift"})))
_dn = _by_key.get(("ArrowDown", frozenset({"shift"})))
assert _up is not None, "Shift+ArrowUp binding missing"
assert _dn is not None, "Shift+ArrowDown binding missing"

# Scoped to the alignment card-stack zone, wired to web-audio's cycle helpers,
# grouped with the other audio bindings in the hint panel
assert _up.js_callback == "cycleAlignSpeedUp"
assert _dn.js_callback == "cycleAlignSpeedDown"
assert _up.zone_ids == (_zone.id,)
assert _dn.zone_ids == (_zone.id,)
assert _up.hint_group == "Audio"
assert _dn.hint_group == "Audio"

# Plain ArrowUp/ArrowDown (card-stack nav) must NOT collide — distinct modifiers frozenset
_nav_up = _by_key.get(("ArrowUp", frozenset()))
_nav_dn = _by_key.get(("ArrowDown", frozenset()))
assert _nav_up is not None and _nav_up.htmx_trigger, "Plain ArrowUp should still be the card-stack nav binding"
assert _nav_dn is not None and _nav_dn.htmx_trigger, "Plain ArrowDown should still be the card-stack nav binding"

print("Shift+Arrow speed cycle bindings test passed")
Shift+Arrow speed cycle bindings test passed