Config

Configuration dataclasses for card stack initialization and visual styling.

Prefix Counter

Auto-generates unique prefixes (cs0, cs1, …) for card stack instances when no explicit prefix is provided. Ensures multi-instance HTML ID uniqueness.

# Test auto-prefix generation
_reset_prefix_counter()
assert _auto_prefix() == "cs0"
assert _auto_prefix() == "cs1"
assert _auto_prefix() == "cs2"
_reset_prefix_counter()
assert _auto_prefix() == "cs0"  # Reset works
print("Prefix counter tests passed!")
Prefix counter tests passed!

Style Defaults

Module-level constants for focused card emphasis. Computed from the cjm_fasthtml_tailwind and cjm_fasthtml_daisyui libraries so consumers can see (and override) the exact default class strings.

# Verify default class strings
assert _DEFAULT_FOCUS_RING == "ring-1 ring-[color-mix(in_oklch,var(--color-primary),transparent_50%)]"
assert _DEFAULT_FOCUS_SHADOW == "shadow-lg shadow-primary"
assert _DEFAULT_FOCUS_BORDER_RADIUS == "rounded-box"
print("Style default constants tests passed!")
Style default constants tests passed!

CardStackStyleConfig

Visual styling for a card stack instance. Spacing values are set as CSS custom properties on the outer container and consumed by child elements via Tailwind’s arbitrary value syntax (e.g., gap-[var(--cs0-section-gap)]). Consumer JS can update them dynamically via style.setProperty().


source

CardStackStyleConfig


def CardStackStyleConfig(
    section_gap:str='1rem', slot_padding:str='0.25rem', viewport_padding_x:str='0.5rem',
    viewport_padding_y:str='0.5rem', focus_padding_x:str='0.5rem', focus_padding_b:str='1rem',
    focus_ring:str='ring-1 ring-[color-mix(in_oklch,var(--color-primary),transparent_50%)]',
    focus_shadow:str='shadow-lg shadow-primary', focus_border_radius:str='rounded-box'
)->None:

Visual styling for a card stack instance.

# Test CardStackStyleConfig defaults
style = CardStackStyleConfig()
assert style.section_gap == "1rem"
assert style.slot_padding == "0.25rem"
assert style.viewport_padding_x == "0.5rem"
assert style.viewport_padding_y == "0.5rem"
assert style.focus_padding_x == "0.5rem"
assert style.focus_padding_b == "1rem"
assert style.focus_shadow == "shadow-lg shadow-primary"
assert style.focus_border_radius == "rounded-box"
print("CardStackStyleConfig defaults tests passed!")
CardStackStyleConfig defaults tests passed!
# Test css_vars_style generates correct CSS custom property declarations
style = CardStackStyleConfig()
css = style.css_vars_style("cs0")
assert "--cs0-section-gap: 1rem" in css
assert "--cs0-slot-padding: 0.25rem" in css
assert "--cs0-viewport-padding-x: 0.5rem" in css
assert "--cs0-viewport-padding-y: 0.5rem" in css
assert "--cs0-focus-padding-x: 0.5rem" in css
assert "--cs0-focus-padding-b: 1rem" in css
print("css_vars_style tests passed!")
css_vars_style tests passed!
# Test css_vars_style with custom values and different prefix
style = CardStackStyleConfig(section_gap="0.5rem", slot_padding="0.125rem")
css = style.css_vars_style("chat")
assert "--chat-section-gap: 0.5rem" in css
assert "--chat-slot-padding: 0.125rem" in css
# Unchanged defaults still present
assert "--chat-viewport-padding-x: 0.5rem" in css
print("css_vars_style custom values test passed!")
css_vars_style custom values test passed!

CardStackConfig

Initialization-time settings for a card stack instance. Created once and reused across requests. The prefix drives CardStackHtmlIds and CardStackButtonIds generation for multi-instance support.


source

CardStackConfig


def CardStackConfig(
    prefix:str=<factory>, visible_count_options:Tuple=(1, 3, 5, 7, 9), card_width_min:int=30, card_width_max:int=120,
    card_width_step:int=5, card_scale_min:int=50, card_scale_max:int=200, card_scale_step:int=10,
    click_to_focus:bool=False, disable_scroll_in_modes:Tuple=(), show_scrollbar:bool=True,
    style:CardStackStyleConfig=<factory>
)->None:

Initialization-time settings for a card stack instance.

# Test CardStackConfig defaults with auto-prefix
_reset_prefix_counter()
config1 = CardStackConfig()
config2 = CardStackConfig()
assert config1.prefix == "cs0"
assert config2.prefix == "cs1"
assert config1.prefix != config2.prefix  # Unique prefixes
print("Auto-prefix uniqueness tests passed!")
Auto-prefix uniqueness tests passed!
# Test CardStackConfig with explicit prefix
config = CardStackConfig(prefix="text-stack")
assert config.prefix == "text-stack"
print("Explicit prefix test passed!")
Explicit prefix test passed!
# Test CardStackConfig field defaults
_reset_prefix_counter()
config = CardStackConfig()
assert config.visible_count_options == (1, 3, 5, 7, 9)
assert config.card_width_min == 30
assert config.card_width_max == 120
assert config.card_width_step == 5
assert config.card_scale_min == 50
assert config.card_scale_max == 200
assert config.card_scale_step == 10
assert config.click_to_focus == False
assert config.disable_scroll_in_modes == ()
assert isinstance(config.style, CardStackStyleConfig)
assert config.style.section_gap == "1rem"
print("CardStackConfig defaults tests passed!")
# Test CardStackConfig with custom values
config = CardStackConfig(
    prefix="chat",
    visible_count_options=(3, 5, 7),
    card_width_min=40,
    card_width_max=100,
    card_scale_min=75,
    card_scale_max=150,
    click_to_focus=True,
    disable_scroll_in_modes=("split", "edit"),
    style=CardStackStyleConfig(section_gap="0.5rem", focus_shadow="shadow-md"),
)
assert config.prefix == "chat"
assert config.visible_count_options == (3, 5, 7)
assert config.card_width_min == 40
assert config.card_scale_min == 75
assert config.click_to_focus == True
assert config.disable_scroll_in_modes == ("split", "edit")
assert config.style.section_gap == "0.5rem"
assert config.style.focus_shadow == "shadow-md"
assert config.style.slot_padding == "0.25rem"  # Unchanged default
print("CardStackConfig custom value tests passed!")