def build_slots_response( card_items:List, # All data items state:CardStackState, # Current card stack state config:CardStackConfig, # Card stack configuration ids:CardStackHtmlIds, # HTML IDs for this instance urls:CardStackUrls, # URL bundle for navigation render_card:Callable, # Card renderer callback)->List: # OOB slot elements (3 viewport sections)
Build OOB slot updates for the viewport sections only.
def build_nav_response( card_items:List, # All data items state:CardStackState, # Current card stack state config:CardStackConfig, # Card stack configuration ids:CardStackHtmlIds, # HTML IDs for this instance urls:CardStackUrls, # URL bundle for navigation render_card:Callable, # Card renderer callback progress_label:str='Item', # Label for progress indicator form_input_name:str='focused_index', # Name for the focused index hidden input)->Tuple: # OOB elements (slots + progress + focus + scrollbar)
Build full OOB response for navigation: slots + progress + focus inputs + scrollbar.
def card_stack_navigate( direction:str, # "up", "down", "first", "last", "page_up", "page_down" card_items:List, # All data items state:CardStackState, # Current card stack state (mutated in place) config:CardStackConfig, # Card stack configuration ids:CardStackHtmlIds, # HTML IDs for this instance urls:CardStackUrls, # URL bundle for navigation render_card:Callable, # Card renderer callback progress_label:str='Item', # Label for progress indicator form_input_name:str='focused_index', # Name for the focused index hidden input)->Tuple: # OOB elements (slots + progress + focus)
Navigate to a different item. Mutates state.focused_index in place.
def card_stack_navigate_to_index( target_index:int, # Target item index to navigate to card_items:List, # All data items state:CardStackState, # Current card stack state (mutated in place) config:CardStackConfig, # Card stack configuration ids:CardStackHtmlIds, # HTML IDs for this instance urls:CardStackUrls, # URL bundle for navigation render_card:Callable, # Card renderer callback progress_label:str='Item', # Label for progress indicator form_input_name:str='focused_index', # Name for the focused index hidden input)->Tuple: # OOB elements (slots + progress + focus)
Navigate to a specific item index. Mutates state.focused_index in place.
def card_stack_update_viewport( visible_count:int, # New number of visible cards card_items:List, # All data items state:CardStackState, # Current card stack state (mutated in place) config:CardStackConfig, # Card stack configuration ids:CardStackHtmlIds, # HTML IDs for this instance urls:CardStackUrls, # URL bundle for navigation render_card:Callable, # Card renderer callback is_auto:bool=True, # Whether this update came from auto-adjust mode)->Tuple: # OOB section elements (3 viewport sections + scrollbar)
Update viewport with new card count via OOB section swaps. Mutates state in place.
def card_stack_save_width( state:CardStackState, # Current card stack state (mutated in place) card_width:int, # Card stack width in rem config:CardStackConfig, # Card stack configuration (for clamping bounds))->None: # No response (swap=none on client)
Save card stack width. Mutates state.card_width in place.
# Test card_stack_navigate — empty itemsstate = CardStackState(focused_index=0, visible_count=3)result = card_stack_navigate("down", [], state, _test_config, _test_ids, _test_urls, _test_render_card)assert state.focused_index ==0# Unchangedassertlen(result) >0# Still returns elements (empty viewport sections)print("Empty items navigate test passed!")
Empty items navigate test passed!
# Test card_stack_navigate_to_indexstate = CardStackState(focused_index=0, visible_count=3)result = card_stack_navigate_to_index(15, _test_items, state, _test_config, _test_ids, _test_urls, _test_render_card)assert state.focused_index ==15# Clamps out-of-rangecard_stack_navigate_to_index(100, _test_items, state, _test_config, _test_ids, _test_urls, _test_render_card)assert state.focused_index ==19# Clamped to total-1card_stack_navigate_to_index(-5, _test_items, state, _test_config, _test_ids, _test_urls, _test_render_card)assert state.focused_index ==0# Clamped to 0print("Navigate to index tests passed!")
Navigate to index tests passed!
# Test form_input_name is passed through navigationfrom fasthtml.common import to_xmlstate = CardStackState(focused_index=5, visible_count=3)result = card_stack_navigate("down", _test_items, state, _test_config, _test_ids, _test_urls, _test_render_card, form_input_name="segment_index")# Find the Hidden input in the result tuplehidden_found =Falsefor el in result: html = to_xml(el)if'name="segment_index"'in html: hidden_found =Trueassert'value="6"'in html # focused_index after nav down from 5breakassert hidden_found, "Hidden input with custom form_input_name not found in response"print("form_input_name passthrough test passed!")