Exported source
table = SingleValueFactory("table", "Table component for displaying data in rows and columns") # Table componentThe base table component:
Table modifier utilities:
Table size variants:
Test basic table utilities.
Test table modifier utilities.
def test_table_modifiers_examples():
"""Test table modifier utilities."""
assert str(table_modifiers.zebra) == "table-zebra"
assert str(table_modifiers.pin_rows) == "table-pin-rows"
assert str(table_modifiers.pin_cols) == "table-pin-cols"
# With responsive modifiers
assert str(table_modifiers.zebra.hover) == "hover:table-zebra"
assert str(table_modifiers.pin_rows.md) == "md:table-pin-rows"
# Run the tests
test_table_modifiers_examples()Test table size variants.
def test_table_sizes_examples():
"""Test table size variants."""
assert str(table_sizes.xs) == "table-xs"
assert str(table_sizes.sm) == "table-sm"
assert str(table_sizes.md) == "table-md"
assert str(table_sizes.lg) == "table-lg"
assert str(table_sizes.xl) == "table-xl"
# With responsive modifiers
assert str(table_sizes.xs.sm) == "sm:table-xs"
assert str(table_sizes.lg.md) == "md:table-lg"
# Run the tests
test_table_sizes_examples()Test basic table and table with border and background from daisyUI v5 documentation.
def test_table_basic_fasthtml_examples():
"""Test basic table and table with border and background from daisyUI v5 documentation."""
from fasthtml.common import Div, Table, Thead, Tbody, Tr, Th, Td
from cjm_fasthtml_tailwind.utilities.layout import overflow
from cjm_fasthtml_tailwind.utilities.borders import border
from cjm_fasthtml_tailwind.core.base import combine_classes
from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui, border_dui
from cjm_fasthtml_daisyui.utilities.border_radius import border_radius
# Basic tablefrom cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui, border_dui,
basic_table = Div(
Table(
Thead(
Tr(
Th(),
Th("Name"),
Th("Job"),
Th("Favorite Color")
)
),
Tbody(
Tr(
Th("1"),
Td("Cy Ganderton"),
Td("Quality Control Specialist"),
Td("Blue")
),
Tr(
Th("2"),
Td("Hart Hagerty"),
Td("Desktop Support Technician"),
Td("Purple")
),
Tr(
Th("3"),
Td("Brice Swyre"),
Td("Tax Accountant"),
Td("Red")
)
),
cls=str(table)
),
cls=combine_classes(overflow.x.auto)
)
assert "overflow-x-auto" in basic_table.attrs['class']
assert basic_table.children[0].tag == "table"
assert "table" in basic_table.children[0].attrs['class']
# Verify table structure
thead = basic_table.children[0].children[0]
assert thead.tag == "thead"
assert thead.children[0].tag == "tr"
assert len(thead.children[0].children) == 4 # 4 columns
assert thead.children[0].children[0].tag == "th"
assert thead.children[0].children[0].children == () # Empty first header
assert thead.children[0].children[1].tag == "th"
assert thead.children[0].children[1].children[0] == "Name"
# Verify tbody
tbody = basic_table.children[0].children[1]
assert tbody.tag == "tbody"
assert len(tbody.children) == 3 # 3 rows
assert tbody.children[0].tag == "tr"
assert tbody.children[0].children[0].tag == "th"
assert tbody.children[0].children[0].children[0] == "1"
assert tbody.children[0].children[1].tag == "td"
assert tbody.children[0].children[1].children[0] == "Cy Ganderton"
# Table with border and background
bordered_table = Div(
Table(
Thead(
Tr(
Th(),
Th("Name"),
Th("Job"),
Th("Favorite Color")
)
),
Tbody(
Tr(
Th("1"),
Td("Cy Ganderton"),
Td("Quality Control Specialist"),
Td("Blue")
),
Tr(
Th("2"),
Td("Hart Hagerty"),
Td("Desktop Support Technician"),
Td("Purple")
),
Tr(
Th("3"),
Td("Brice Swyre"),
Td("Tax Accountant"),
Td("Red")
)
),
cls=str(table)
),
cls=combine_classes(overflow.x.auto, border_radius.box, border(), border_dui.base_content.opacity(5), bg_dui.base_100)
)
assert "overflow-x-auto" in bordered_table.attrs['class']
assert "rounded-box" in bordered_table.attrs['class']
assert "border" in bordered_table.attrs['class']
assert "border-base-content/5" in bordered_table.attrs['class']
assert "bg-base-100" in bordered_table.attrs['class']
assert bordered_table.children[0].tag == "table"
assert "table" in bordered_table.children[0].attrs['class']
# Verify it has same content as basic table but with border styling
assert len(bordered_table.children[0].children[1].children) == 3 # 3 rows
# Return all examples in a Div
return Div(
basic_table,
bordered_table
)
# Run the tests
test_table_basic_fasthtml_examples()| Name | Job | Favorite Color | |
|---|---|---|---|
| 1 | Cy Ganderton | Quality Control Specialist | Blue |
| 2 | Hart Hagerty | Desktop Support Technician | Purple |
| 3 | Brice Swyre | Tax Accountant | Red |
| Name | Job | Favorite Color | |
|---|---|---|---|
| 1 | Cy Ganderton | Quality Control Specialist | Blue |
| 2 | Hart Hagerty | Desktop Support Technician | Purple |
| 3 | Brice Swyre | Tax Accountant | Red |
Test table with active row, hover row, and zebra stripes from daisyUI v5 documentation.
def test_table_style_fasthtml_examples():
"""Test table with active row, hover row, and zebra stripes from daisyUI v5 documentation."""
from fasthtml.common import Div, Table, Thead, Tbody, Tr, Th, Td
from cjm_fasthtml_tailwind.utilities.layout import overflow
from cjm_fasthtml_tailwind.core.base import combine_classes
from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
# Table with an active row
active_row_table = Div(
Table(
Thead(
Tr(
Th(),
Th("Name"),
Th("Job"),
Th("Favorite Color")
)
),
Tbody(
Tr(
Th("1"),
Td("Cy Ganderton"),
Td("Quality Control Specialist"),
Td("Blue"),
cls=str(bg_dui.base_200)
),
Tr(
Th("2"),
Td("Hart Hagerty"),
Td("Desktop Support Technician"),
Td("Purple")
),
Tr(
Th("3"),
Td("Brice Swyre"),
Td("Tax Accountant"),
Td("Red")
)
),
cls=str(table)
),
cls=combine_classes(overflow.x.auto)
)
assert "overflow-x-auto" in active_row_table.attrs['class']
assert active_row_table.children[0].tag == "table"
assert "table" in active_row_table.children[0].attrs['class']
# Verify active row has bg-base-200
tbody = active_row_table.children[0].children[1]
assert tbody.tag == "tbody"
assert "bg-base-200" in tbody.children[0].attrs['class']
assert tbody.children[0].children[1].children[0] == "Cy Ganderton"
# Other rows should not have bg-base-200
assert 'class' not in tbody.children[1].attrs or "bg-base-200" not in tbody.children[1].attrs.get('class', '')
assert 'class' not in tbody.children[2].attrs or "bg-base-200" not in tbody.children[2].attrs.get('class', '')
# Table with a row that highlights on hover
hover_table = Div(
Table(
Thead(
Tr(
Th(),
Th("Name"),
Th("Job"),
Th("Favorite Color")
)
),
Tbody(
Tr(
Th("1"),
Td("Cy Ganderton"),
Td("Quality Control Specialist"),
Td("Blue")
),
Tr(
Th("2"),
Td("Hart Hagerty"),
Td("Desktop Support Technician"),
Td("Purple"),
cls=str(bg_dui.base_300.hover)
),
Tr(
Th("3"),
Td("Brice Swyre"),
Td("Tax Accountant"),
Td("Red")
)
),
cls=str(table)
),
cls=combine_classes(overflow.x.auto)
)
assert "overflow-x-auto" in hover_table.attrs['class']
assert hover_table.children[0].tag == "table"
assert "table" in hover_table.children[0].attrs['class']
# Verify second row has hover:bg-base-300
tbody = hover_table.children[0].children[1]
assert tbody.tag == "tbody"
assert "hover:bg-base-300" in tbody.children[1].attrs['class']
assert tbody.children[1].children[1].children[0] == "Hart Hagerty"
# Other rows should not have hover styling
assert 'class' not in tbody.children[0].attrs or "hover:bg-base-300" not in tbody.children[0].attrs.get('class', '')
assert 'class' not in tbody.children[2].attrs or "hover:bg-base-300" not in tbody.children[2].attrs.get('class', '')
# Zebra striped table
zebra_table = Div(
Table(
Thead(
Tr(
Th(),
Th("Name"),
Th("Job"),
Th("Favorite Color")
)
),
Tbody(
Tr(
Th("1"),
Td("Cy Ganderton"),
Td("Quality Control Specialist"),
Td("Blue")
),
Tr(
Th("2"),
Td("Hart Hagerty"),
Td("Desktop Support Technician"),
Td("Purple")
),
Tr(
Th("3"),
Td("Brice Swyre"),
Td("Tax Accountant"),
Td("Red")
)
),
cls=combine_classes(table, table_modifiers.zebra)
),
cls=combine_classes(overflow.x.auto)
)
assert "overflow-x-auto" in zebra_table.attrs['class']
assert zebra_table.children[0].tag == "table"
assert "table" in zebra_table.children[0].attrs['class']
assert "table-zebra" in zebra_table.children[0].attrs['class']
# Verify all rows are present
tbody = zebra_table.children[0].children[1]
assert tbody.tag == "tbody"
assert len(tbody.children) == 3
assert tbody.children[0].children[1].children[0] == "Cy Ganderton"
assert tbody.children[1].children[1].children[0] == "Hart Hagerty"
assert tbody.children[2].children[1].children[0] == "Brice Swyre"
# Return all examples in a Div
return Div(
active_row_table,
hover_table,
zebra_table
)
# Run the tests
test_table_style_fasthtml_examples()| Name | Job | Favorite Color | |
|---|---|---|---|
| 1 | Cy Ganderton | Quality Control Specialist | Blue |
| 2 | Hart Hagerty | Desktop Support Technician | Purple |
| 3 | Brice Swyre | Tax Accountant | Red |
| Name | Job | Favorite Color | |
|---|---|---|---|
| 1 | Cy Ganderton | Quality Control Specialist | Blue |
| 2 | Hart Hagerty | Desktop Support Technician | Purple |
| 3 | Brice Swyre | Tax Accountant | Red |
| Name | Job | Favorite Color | |
|---|---|---|---|
| 1 | Cy Ganderton | Quality Control Specialist | Blue |
| 2 | Hart Hagerty | Desktop Support Technician | Purple |
| 3 | Brice Swyre | Tax Accountant | Red |
Test table with visual elements from daisyUI v5 documentation.
def test_table_visual_elements_fasthtml_examples():
"""Test table with visual elements from daisyUI v5 documentation."""
from fasthtml.common import Div, Table, Thead, Tbody, Tr, Th, Td, Tfoot, Input, Button, Img, Span, Label, Br
from cjm_fasthtml_tailwind.utilities.layout import display_tw, overflow
from cjm_fasthtml_tailwind.utilities.flexbox_and_grid import items, gap, flex_display
from cjm_fasthtml_tailwind.utilities.sizing import h, w
from cjm_fasthtml_tailwind.utilities.typography import font_size, font_weight, font_family, text_color
from cjm_fasthtml_tailwind.utilities.effects import opacity
from cjm_fasthtml_tailwind.core.base import combine_classes
from cjm_fasthtml_daisyui.components.actions.button import btn, btn_styles, btn_sizes
from cjm_fasthtml_daisyui.components.data_display.badge import badge, badge_styles, badge_sizes
from cjm_fasthtml_daisyui.components.data_display.avatar import avatar
from cjm_fasthtml_daisyui.components.data_input.checkbox import checkbox as checkbox_factory
from cjm_fasthtml_daisyui.components.layout.mask import mask, mask_styles
# Table with visual elements
visual_table = Div(
Table(
Thead(
Tr(
Th(
Label(
Input(type="checkbox", cls=str(checkbox_factory))
)
),
Th("Name"),
Th("Job"),
Th("Favorite Color"),
Th()
)
),
Tbody(
Tr(
Th(
Label(
Input(type="checkbox", cls=str(checkbox_factory))
)
),
Td(
Div(
Div(
Div(
Img(
src="https://img.daisyui.com/images/profile/demo/2@94.webp",
alt="Avatar Tailwind CSS Component"
),
cls=combine_classes(mask, mask_styles.squircle, h._12, w._12)
),
cls=str(avatar)
),
Div(
Div("Hart Hagerty", cls=str(font_weight.bold)),
Div("United States", cls=combine_classes(font_size.sm, opacity._50))
),
cls=combine_classes(flex_display, items.center, gap._3)
)
),
Td(
"Zemlak, Daniel and Leannon",
Br(),
Span("Desktop Support Technician", cls=combine_classes(badge, badge_styles.ghost, badge_sizes.sm))
),
Td("Purple"),
Th(
Button("details", cls=combine_classes(btn, btn_styles.ghost, btn_sizes.xs))
)
),
Tr(
Th(
Label(
Input(type="checkbox", cls=str(checkbox_factory))
)
),
Td(
Div(
Div(
Div(
Img(
src="https://img.daisyui.com/images/profile/demo/3@94.webp",
alt="Avatar Tailwind CSS Component"
),
cls=combine_classes(mask, mask_styles.squircle, h._12, w._12)
),
cls=str(avatar)
),
Div(
Div("Brice Swyre", cls=str(font_weight.bold)),
Div("China", cls=combine_classes(font_size.sm, opacity._50))
),
cls=combine_classes(flex_display, items.center, gap._3)
)
),
Td(
"Carroll Group",
Br(),
Span("Tax Accountant", cls=combine_classes(badge, badge_styles.ghost, badge_sizes.sm))
),
Td("Red"),
Th(
Button("details", cls=combine_classes(btn, btn_styles.ghost, btn_sizes.xs))
)
),
Tr(
Th(
Label(
Input(type="checkbox", cls=str(checkbox_factory))
)
),
Td(
Div(
Div(
Div(
Img(
src="https://img.daisyui.com/images/profile/demo/4@94.webp",
alt="Avatar Tailwind CSS Component"
),
cls=combine_classes(mask, mask_styles.squircle, h._12, w._12)
),
cls=str(avatar)
),
Div(
Div("Marjy Ferencz", cls=str(font_weight.bold)),
Div("Russia", cls=combine_classes(font_size.sm, opacity._50))
),
cls=combine_classes(flex_display, items.center, gap._3)
)
),
Td(
"Rowe-Schoen",
Br(),
Span("Office Assistant I", cls=combine_classes(badge, badge_styles.ghost, badge_sizes.sm))
),
Td("Crimson"),
Th(
Button("details", cls=combine_classes(btn, btn_styles.ghost, btn_sizes.xs))
)
),
Tr(
Th(
Label(
Input(type="checkbox", cls=str(checkbox_factory))
)
),
Td(
Div(
Div(
Div(
Img(
src="https://img.daisyui.com/images/profile/demo/5@94.webp",
alt="Avatar Tailwind CSS Component"
),
cls=combine_classes(mask, mask_styles.squircle, h._12, w._12)
),
cls=str(avatar)
),
Div(
Div("Yancy Tear", cls=str(font_weight.bold)),
Div("Brazil", cls=combine_classes(font_size.sm, opacity._50))
),
cls=combine_classes(flex_display, items.center, gap._3)
)
),
Td(
"Wyman-Ledner",
Br(),
Span("Community Outreach Specialist", cls=combine_classes(badge, badge_styles.ghost, badge_sizes.sm))
),
Td("Indigo"),
Th(
Button("details", cls=combine_classes(btn, btn_styles.ghost, btn_sizes.xs))
)
)
),
Tfoot(
Tr(
Th(),
Th("Name"),
Th("Job"),
Th("Favorite Color"),
Th()
)
),
cls=str(table)
),
cls=combine_classes(overflow.x.auto)
)
# Verify table structure
assert "overflow-x-auto" in visual_table.attrs['class']
assert visual_table.children[0].tag == "table"
assert "table" in visual_table.children[0].attrs['class']
# Verify thead
thead = visual_table.children[0].children[0]
assert thead.tag == "thead"
assert thead.children[0].tag == "tr"
assert len(thead.children[0].children) == 5 # 5 columns
# First column has checkbox
assert thead.children[0].children[0].tag == "th"
assert thead.children[0].children[0].children[0].tag == "label"
assert thead.children[0].children[0].children[0].children[0].tag == "input"
assert thead.children[0].children[0].children[0].children[0].attrs['type'] == "checkbox"
assert "checkbox" in thead.children[0].children[0].children[0].children[0].attrs['class']
# Verify tbody
tbody = visual_table.children[0].children[1]
assert tbody.tag == "tbody"
assert len(tbody.children) == 4 # 4 rows
# Verify first row structure
first_row = tbody.children[0]
assert first_row.tag == "tr"
assert len(first_row.children) == 5
# Checkbox column
assert first_row.children[0].tag == "th"
assert first_row.children[0].children[0].tag == "label"
assert first_row.children[0].children[0].children[0].tag == "input"
assert "checkbox" in first_row.children[0].children[0].children[0].attrs['class']
# Name column with avatar
name_td = first_row.children[1]
assert name_td.tag == "td"
flex_container = name_td.children[0]
assert "flex" in flex_container.attrs['class']
assert "items-center" in flex_container.attrs['class']
assert "gap-3" in flex_container.attrs['class']
# Avatar
avatar_div = flex_container.children[0]
assert "avatar" in avatar_div.attrs['class']
mask_div = avatar_div.children[0]
assert "mask" in mask_div.attrs['class']
assert "mask-squircle" in mask_div.attrs['class']
assert "h-12" in mask_div.attrs['class']
assert "w-12" in mask_div.attrs['class']
assert mask_div.children[0].tag == "img"
assert mask_div.children[0].attrs['src'] == "https://img.daisyui.com/images/profile/demo/2@94.webp"
# Name text
name_div = flex_container.children[1]
assert name_div.children[0].children[0] == "Hart Hagerty"
assert "font-bold" in name_div.children[0].attrs['class']
assert name_div.children[1].children[0] == "United States"
assert "text-sm" in name_div.children[1].attrs['class']
assert "opacity-50" in name_div.children[1].attrs['class']
# Job column with badge
job_td = first_row.children[2]
assert job_td.tag == "td"
assert job_td.children[0] == "Zemlak, Daniel and Leannon"
assert job_td.children[1].tag == "br"
assert job_td.children[2].tag == "span"
assert "badge" in job_td.children[2].attrs['class']
assert "badge-ghost" in job_td.children[2].attrs['class']
assert "badge-sm" in job_td.children[2].attrs['class']
assert job_td.children[2].children[0] == "Desktop Support Technician"
# Color column
assert first_row.children[3].tag == "td"
assert first_row.children[3].children[0] == "Purple"
# Details button column
assert first_row.children[4].tag == "th"
assert first_row.children[4].children[0].tag == "button"
assert "btn" in first_row.children[4].children[0].attrs['class']
assert "btn-ghost" in first_row.children[4].children[0].attrs['class']
assert "btn-xs" in first_row.children[4].children[0].attrs['class']
assert first_row.children[4].children[0].children[0] == "details"
# Verify second row has different data
second_row = tbody.children[1]
assert second_row.children[1].children[0].children[1].children[0].children[0] == "Brice Swyre"
assert second_row.children[1].children[0].children[1].children[1].children[0] == "China"
assert second_row.children[2].children[0] == "Carroll Group"
assert second_row.children[2].children[2].children[0] == "Tax Accountant"
# Verify tfoot
tfoot = visual_table.children[0].children[2]
assert tfoot.tag == "tfoot"
assert tfoot.children[0].tag == "tr"
assert len(tfoot.children[0].children) == 5 # 5 columns
assert tfoot.children[0].children[1].children[0] == "Name"
assert tfoot.children[0].children[2].children[0] == "Job"
# Return the example in a Div
return Div(visual_table)
# Run the tests
test_table_visual_elements_fasthtml_examples()| Name | Job | Favorite Color | ||
|---|---|---|---|---|
Hart Hagerty
United States
|
Zemlak, Daniel and Leannon Desktop Support Technician |
Purple | ||
Brice Swyre
China
|
Carroll Group Tax Accountant |
Red | ||
Marjy Ferencz
Russia
|
Rowe-Schoen Office Assistant I |
Crimson | ||
Yancy Tear
Brazil
|
Wyman-Ledner Community Outreach Specialist |
Indigo | ||
| Name | Job | Favorite Color |
Test table xs size from daisyUI v5 documentation.
def test_table_sizes_fasthtml_examples():
"""Test table xs size from daisyUI v5 documentation."""
from fasthtml.common import Div, Table, Thead, Tbody, Tr, Th, Td, Tfoot
from cjm_fasthtml_tailwind.utilities.layout import overflow
from cjm_fasthtml_tailwind.core.base import combine_classes
# Table xs (extra small)
xs_table = Div(
Table(
Thead(
Tr(
Th(),
Th("Name"),
Th("Job"),
Th("company"),
Th("location"),
Th("Last Login"),
Th("Favorite Color")
)
),
Tbody(
Tr(
Th("1"),
Td("Cy Ganderton"),
Td("Quality Control Specialist"),
Td("Littel, Schaden and Vandervort"),
Td("Canada"),
Td("12/16/2020"),
Td("Blue")
),
Tr(
Th("2"),
Td("Hart Hagerty"),
Td("Desktop Support Technician"),
Td("Zemlak, Daniel and Leannon"),
Td("United States"),
Td("12/5/2020"),
Td("Purple")
),
Tr(
Th("3"),
Td("Brice Swyre"),
Td("Tax Accountant"),
Td("Carroll Group"),
Td("China"),
Td("8/15/2020"),
Td("Red")
),
Tr(
Th("4"),
Td("Marjy Ferencz"),
Td("Office Assistant I"),
Td("Rowe-Schoen"),
Td("Russia"),
Td("3/25/2021"),
Td("Crimson")
),
Tr(
Th("5"),
Td("Yancy Tear"),
Td("Community Outreach Specialist"),
Td("Wyman-Ledner"),
Td("Brazil"),
Td("5/22/2020"),
Td("Indigo")
),
Tr(
Th("6"),
Td("Irma Vasilik"),
Td("Editor"),
Td("Wiza, Bins and Emard"),
Td("Venezuela"),
Td("12/8/2020"),
Td("Purple")
),
Tr(
Th("7"),
Td("Meghann Durtnal"),
Td("Staff Accountant IV"),
Td("Schuster-Schimmel"),
Td("Philippines"),
Td("2/17/2021"),
Td("Yellow")
),
Tr(
Th("8"),
Td("Sammy Seston"),
Td("Accountant I"),
Td("O'Hara, Welch and Keebler"),
Td("Indonesia"),
Td("5/23/2020"),
Td("Crimson")
),
Tr(
Th("9"),
Td("Lesya Tinham"),
Td("Safety Technician IV"),
Td("Turner-Kuhlman"),
Td("Philippines"),
Td("2/21/2021"),
Td("Maroon")
),
Tr(
Th("10"),
Td("Zaneta Tewkesbury"),
Td("VP Marketing"),
Td("Sauer LLC"),
Td("Chad"),
Td("6/23/2020"),
Td("Green")
),
Tr(
Th("11"),
Td("Andy Tipple"),
Td("Librarian"),
Td("Hilpert Group"),
Td("Poland"),
Td("7/9/2020"),
Td("Indigo")
),
Tr(
Th("12"),
Td("Sophi Biles"),
Td("Recruiting Manager"),
Td("Gutmann Inc"),
Td("Indonesia"),
Td("2/12/2021"),
Td("Maroon")
),
Tr(
Th("13"),
Td("Florida Garces"),
Td("Web Developer IV"),
Td("Gaylord, Pacocha and Baumbach"),
Td("Poland"),
Td("5/31/2020"),
Td("Purple")
),
Tr(
Th("14"),
Td("Maribeth Popping"),
Td("Analyst Programmer"),
Td("Deckow-Pouros"),
Td("Portugal"),
Td("4/27/2021"),
Td("Aquamarine")
),
Tr(
Th("15"),
Td("Moritz Dryburgh"),
Td("Dental Hygienist"),
Td("Schiller, Cole and Hackett"),
Td("Sri Lanka"),
Td("8/8/2020"),
Td("Crimson")
),
Tr(
Th("16"),
Td("Reid Semiras"),
Td("Teacher"),
Td("Sporer, Sipes and Rogahn"),
Td("Poland"),
Td("7/30/2020"),
Td("Green")
),
Tr(
Th("17"),
Td("Alec Lethby"),
Td("Teacher"),
Td("Reichel, Glover and Hamill"),
Td("China"),
Td("2/28/2021"),
Td("Khaki")
),
Tr(
Th("18"),
Td("Aland Wilber"),
Td("Quality Control Specialist"),
Td("Kshlerin, Rogahn and Swaniawski"),
Td("Czech Republic"),
Td("9/29/2020"),
Td("Purple")
),
Tr(
Th("19"),
Td("Teddie Duerden"),
Td("Staff Accountant III"),
Td("Pouros, Ullrich and Windler"),
Td("France"),
Td("10/27/2020"),
Td("Aquamarine")
),
Tr(
Th("20"),
Td("Lorelei Blackstone"),
Td("Data Coordinator"),
Td("Witting, Kutch and Greenfelder"),
Td("Kazakhstan"),
Td("6/3/2020"),
Td("Red")
)
),
Tfoot(
Tr(
Th(),
Th("Name"),
Th("Job"),
Th("company"),
Th("location"),
Th("Last Login"),
Th("Favorite Color")
)
),
cls=combine_classes(table, table_sizes.xs)
),
cls=combine_classes(overflow.x.auto)
)
# Verify table structure
assert "overflow-x-auto" in xs_table.attrs['class']
assert xs_table.children[0].tag == "table"
assert "table" in xs_table.children[0].attrs['class']
assert "table-xs" in xs_table.children[0].attrs['class']
# Verify thead
thead = xs_table.children[0].children[0]
assert thead.tag == "thead"
assert thead.children[0].tag == "tr"
assert len(thead.children[0].children) == 7 # 7 columns
assert thead.children[0].children[3].children[0] == "company" # lowercase as in docs
assert thead.children[0].children[4].children[0] == "location" # lowercase as in docs
# Verify tbody
tbody = xs_table.children[0].children[1]
assert tbody.tag == "tbody"
assert len(tbody.children) == 20 # 20 rows
# Verify first row
first_row = tbody.children[0]
assert first_row.tag == "tr"
assert first_row.children[0].tag == "th"
assert first_row.children[0].children[0] == "1"
assert first_row.children[1].tag == "td"
assert first_row.children[1].children[0] == "Cy Ganderton"
assert first_row.children[2].children[0] == "Quality Control Specialist"
assert first_row.children[3].children[0] == "Littel, Schaden and Vandervort"
assert first_row.children[4].children[0] == "Canada"
assert first_row.children[5].children[0] == "12/16/2020"
assert first_row.children[6].children[0] == "Blue"
# Verify last row
last_row = tbody.children[19]
assert last_row.tag == "tr"
assert last_row.children[0].tag == "th"
assert last_row.children[0].children[0] == "20"
assert last_row.children[1].children[0] == "Lorelei Blackstone"
assert last_row.children[2].children[0] == "Data Coordinator"
assert last_row.children[3].children[0] == "Witting, Kutch and Greenfelder"
assert last_row.children[4].children[0] == "Kazakhstan"
assert last_row.children[5].children[0] == "6/3/2020"
assert last_row.children[6].children[0] == "Red"
# Verify tfoot
tfoot = xs_table.children[0].children[2]
assert tfoot.tag == "tfoot"
assert tfoot.children[0].tag == "tr"
assert len(tfoot.children[0].children) == 7 # 7 columns
assert tfoot.children[0].children[1].children[0] == "Name"
assert tfoot.children[0].children[2].children[0] == "Job"
assert tfoot.children[0].children[3].children[0] == "company" # lowercase as in docs
assert tfoot.children[0].children[4].children[0] == "location" # lowercase as in docs
# Return the example in a Div
return Div(xs_table)
# Run the tests
test_table_sizes_fasthtml_examples()| Name | Job | company | location | Last Login | Favorite Color | |
|---|---|---|---|---|---|---|
| 1 | Cy Ganderton | Quality Control Specialist | Littel, Schaden and Vandervort | Canada | 12/16/2020 | Blue |
| 2 | Hart Hagerty | Desktop Support Technician | Zemlak, Daniel and Leannon | United States | 12/5/2020 | Purple |
| 3 | Brice Swyre | Tax Accountant | Carroll Group | China | 8/15/2020 | Red |
| 4 | Marjy Ferencz | Office Assistant I | Rowe-Schoen | Russia | 3/25/2021 | Crimson |
| 5 | Yancy Tear | Community Outreach Specialist | Wyman-Ledner | Brazil | 5/22/2020 | Indigo |
| 6 | Irma Vasilik | Editor | Wiza, Bins and Emard | Venezuela | 12/8/2020 | Purple |
| 7 | Meghann Durtnal | Staff Accountant IV | Schuster-Schimmel | Philippines | 2/17/2021 | Yellow |
| 8 | Sammy Seston | Accountant I | O'Hara, Welch and Keebler | Indonesia | 5/23/2020 | Crimson |
| 9 | Lesya Tinham | Safety Technician IV | Turner-Kuhlman | Philippines | 2/21/2021 | Maroon |
| 10 | Zaneta Tewkesbury | VP Marketing | Sauer LLC | Chad | 6/23/2020 | Green |
| 11 | Andy Tipple | Librarian | Hilpert Group | Poland | 7/9/2020 | Indigo |
| 12 | Sophi Biles | Recruiting Manager | Gutmann Inc | Indonesia | 2/12/2021 | Maroon |
| 13 | Florida Garces | Web Developer IV | Gaylord, Pacocha and Baumbach | Poland | 5/31/2020 | Purple |
| 14 | Maribeth Popping | Analyst Programmer | Deckow-Pouros | Portugal | 4/27/2021 | Aquamarine |
| 15 | Moritz Dryburgh | Dental Hygienist | Schiller, Cole and Hackett | Sri Lanka | 8/8/2020 | Crimson |
| 16 | Reid Semiras | Teacher | Sporer, Sipes and Rogahn | Poland | 7/30/2020 | Green |
| 17 | Alec Lethby | Teacher | Reichel, Glover and Hamill | China | 2/28/2021 | Khaki |
| 18 | Aland Wilber | Quality Control Specialist | Kshlerin, Rogahn and Swaniawski | Czech Republic | 9/29/2020 | Purple |
| 19 | Teddie Duerden | Staff Accountant III | Pouros, Ullrich and Windler | France | 10/27/2020 | Aquamarine |
| 20 | Lorelei Blackstone | Data Coordinator | Witting, Kutch and Greenfelder | Kazakhstan | 6/3/2020 | Red |
| Name | Job | company | location | Last Login | Favorite Color |
Test table with pinned rows and pinned rows+columns from daisyUI v5 documentation.
def test_table_pinned_fasthtml_examples():
"""Test table with pinned rows and pinned rows+columns from daisyUI v5 documentation."""
from fasthtml.common import Div, Table, Thead, Tbody, Tr, Th, Td, Tfoot
from cjm_fasthtml_tailwind.utilities.layout import overflow
from cjm_fasthtml_tailwind.utilities.sizing import h
from cjm_fasthtml_tailwind.core.base import combine_classes
from cjm_fasthtml_daisyui.utilities.semantic_colors import bg_dui
# Table with pinned rows
pinned_rows_table = Div(
Table(
Thead(
Tr(
Th("A")
)
),
Tbody(
Tr(Td("Ant-Man")),
Tr(Td("Aquaman")),
Tr(Td("Asterix")),
Tr(Td("The Atom")),
Tr(Td("The Avengers"))
),
Thead(
Tr(
Th("B")
)
),
Tbody(
Tr(Td("Batgirl")),
Tr(Td("Batman")),
Tr(Td("Batwoman")),
Tr(Td("Black Canary")),
Tr(Td("Black Panther"))
),
Thead(
Tr(
Th("C")
)
),
Tbody(
Tr(Td("Captain America")),
Tr(Td("Captain Marvel")),
Tr(Td("Catwoman")),
Tr(Td("Conan the Barbarian"))
),
Thead(
Tr(
Th("D")
)
),
Tbody(
Tr(Td("Daredevil")),
Tr(Td("The Defenders")),
Tr(Td("Doc Savage")),
Tr(Td("Doctor Strange"))
),
Thead(
Tr(
Th("E")
)
),
Tbody(
Tr(Td("Elektra"))
),
Thead(
Tr(
Th("F")
)
),
Tbody(
Tr(Td("Fantastic Four"))
),
Thead(
Tr(
Th("G")
)
),
Tbody(
Tr(Td("Ghost Rider")),
Tr(Td("Green Arrow")),
Tr(Td("Green Lantern")),
Tr(Td("Guardians of the Galaxy"))
),
Thead(
Tr(
Th("H")
)
),
Tbody(
Tr(Td("Hawkeye")),
Tr(Td("Hellboy")),
Tr(Td("Incredible Hulk"))
),
Thead(
Tr(
Th("I")
)
),
Tbody(
Tr(Td("Iron Fist")),
Tr(Td("Iron Man"))
),
Thead(
Tr(
Th("M")
)
),
Tbody(
Tr(Td("Marvelman"))
),
Thead(
Tr(
Th("R")
)
),
Tbody(
Tr(Td("Robin")),
Tr(Td("The Rocketeer"))
),
Thead(
Tr(
Th("S")
)
),
Tbody(
Tr(Td("The Shadow")),
Tr(Td("Spider-Man")),
Tr(Td("Sub-Mariner")),
Tr(Td("Supergirl")),
Tr(Td("Superman"))
),
Thead(
Tr(
Th("T")
)
),
Tbody(
Tr(Td("Teenage Mutant Ninja Turtles")),
Tr(Td("Thor"))
),
Thead(
Tr(
Th("W")
)
),
Tbody(
Tr(Td("The Wasp")),
Tr(Td("Watchmen")),
Tr(Td("Wolverine")),
Tr(Td("Wonder Woman"))
),
Thead(
Tr(
Th("X")
)
),
Tbody(
Tr(Td("X-Men"))
),
Thead(
Tr(
Th("Z")
)
),
Tbody(
Tr(Td("Zatanna")),
Tr(Td("Zatara"))
),
cls=combine_classes(table, table_modifiers.pin_rows, bg_dui.base_200)
),
cls=combine_classes(h._96, overflow.x.auto)
)
# Verify table structure
assert "h-96" in pinned_rows_table.attrs['class']
assert "overflow-x-auto" in pinned_rows_table.attrs['class']
assert pinned_rows_table.children[0].tag == "table"
assert "table" in pinned_rows_table.children[0].attrs['class']
assert "table-pin-rows" in pinned_rows_table.children[0].attrs['class']
assert "bg-base-200" in pinned_rows_table.children[0].attrs['class']
# Verify alternating thead/tbody structure
table_elem = pinned_rows_table.children[0]
# First group - A
assert table_elem.children[0].tag == "thead"
assert table_elem.children[0].children[0].children[0].children[0] == "A"
assert table_elem.children[1].tag == "tbody"
assert table_elem.children[1].children[0].children[0].children[0] == "Ant-Man"
assert table_elem.children[1].children[1].children[0].children[0] == "Aquaman"
# Second group - B
assert table_elem.children[2].tag == "thead"
assert table_elem.children[2].children[0].children[0].children[0] == "B"
assert table_elem.children[3].tag == "tbody"
assert table_elem.children[3].children[0].children[0].children[0] == "Batgirl"
# Last group - Z
assert table_elem.children[-2].tag == "thead"
assert table_elem.children[-2].children[0].children[0].children[0] == "Z"
assert table_elem.children[-1].tag == "tbody"
assert table_elem.children[-1].children[0].children[0].children[0] == "Zatanna"
assert table_elem.children[-1].children[1].children[0].children[0] == "Zatara"
# Table with pinned rows and columns
pinned_both_table = Div(
Table(
Thead(
Tr(
Th(),
Td("Name"),
Td("Job"),
Td("company"),
Td("location"),
Td("Last Login"),
Td("Favorite Color"),
Th()
)
),
Tbody(
Tr(
Th("1"),
Td("Cy Ganderton"),
Td("Quality Control Specialist"),
Td("Littel, Schaden and Vandervort"),
Td("Canada"),
Td("12/16/2020"),
Td("Blue"),
Th("1")
),
Tr(
Th("2"),
Td("Hart Hagerty"),
Td("Desktop Support Technician"),
Td("Zemlak, Daniel and Leannon"),
Td("United States"),
Td("12/5/2020"),
Td("Purple"),
Th("2")
),
Tr(
Th("3"),
Td("Brice Swyre"),
Td("Tax Accountant"),
Td("Carroll Group"),
Td("China"),
Td("8/15/2020"),
Td("Red"),
Th("3")
),
Tr(
Th("4"),
Td("Marjy Ferencz"),
Td("Office Assistant I"),
Td("Rowe-Schoen"),
Td("Russia"),
Td("3/25/2021"),
Td("Crimson"),
Th("4")
),
Tr(
Th("5"),
Td("Yancy Tear"),
Td("Community Outreach Specialist"),
Td("Wyman-Ledner"),
Td("Brazil"),
Td("5/22/2020"),
Td("Indigo"),
Th("5")
),
Tr(
Th("6"),
Td("Irma Vasilik"),
Td("Editor"),
Td("Wiza, Bins and Emard"),
Td("Venezuela"),
Td("12/8/2020"),
Td("Purple"),
Th("6")
),
Tr(
Th("7"),
Td("Meghann Durtnal"),
Td("Staff Accountant IV"),
Td("Schuster-Schimmel"),
Td("Philippines"),
Td("2/17/2021"),
Td("Yellow"),
Th("7")
),
Tr(
Th("8"),
Td("Sammy Seston"),
Td("Accountant I"),
Td("O'Hara, Welch and Keebler"),
Td("Indonesia"),
Td("5/23/2020"),
Td("Crimson"),
Th("8")
),
Tr(
Th("9"),
Td("Lesya Tinham"),
Td("Safety Technician IV"),
Td("Turner-Kuhlman"),
Td("Philippines"),
Td("2/21/2021"),
Td("Maroon"),
Th("9")
),
Tr(
Th("10"),
Td("Zaneta Tewkesbury"),
Td("VP Marketing"),
Td("Sauer LLC"),
Td("Chad"),
Td("6/23/2020"),
Td("Green"),
Th("10")
),
Tr(
Th("11"),
Td("Andy Tipple"),
Td("Librarian"),
Td("Hilpert Group"),
Td("Poland"),
Td("7/9/2020"),
Td("Indigo"),
Th("11")
),
Tr(
Th("12"),
Td("Sophi Biles"),
Td("Recruiting Manager"),
Td("Gutmann Inc"),
Td("Indonesia"),
Td("2/12/2021"),
Td("Maroon"),
Th("12")
),
Tr(
Th("13"),
Td("Florida Garces"),
Td("Web Developer IV"),
Td("Gaylord, Pacocha and Baumbach"),
Td("Poland"),
Td("5/31/2020"),
Td("Purple"),
Th("13")
),
Tr(
Th("14"),
Td("Maribeth Popping"),
Td("Analyst Programmer"),
Td("Deckow-Pouros"),
Td("Portugal"),
Td("4/27/2021"),
Td("Aquamarine"),
Th("14")
),
Tr(
Th("15"),
Td("Moritz Dryburgh"),
Td("Dental Hygienist"),
Td("Schiller, Cole and Hackett"),
Td("Sri Lanka"),
Td("8/8/2020"),
Td("Crimson"),
Th("15")
),
Tr(
Th("16"),
Td("Reid Semiras"),
Td("Teacher"),
Td("Sporer, Sipes and Rogahn"),
Td("Poland"),
Td("7/30/2020"),
Td("Green"),
Th("16")
),
Tr(
Th("17"),
Td("Alec Lethby"),
Td("Teacher"),
Td("Reichel, Glover and Hamill"),
Td("China"),
Td("2/28/2021"),
Td("Khaki"),
Th("17")
),
Tr(
Th("18"),
Td("Aland Wilber"),
Td("Quality Control Specialist"),
Td("Kshlerin, Rogahn and Swaniawski"),
Td("Czech Republic"),
Td("9/29/2020"),
Td("Purple"),
Th("18")
),
Tr(
Th("19"),
Td("Teddie Duerden"),
Td("Staff Accountant III"),
Td("Pouros, Ullrich and Windler"),
Td("France"),
Td("10/27/2020"),
Td("Aquamarine"),
Th("19")
),
Tr(
Th("20"),
Td("Lorelei Blackstone"),
Td("Data Coordinator"),
Td("Witting, Kutch and Greenfelder"),
Td("Kazakhstan"),
Td("6/3/2020"),
Td("Red"),
Th("20")
)
),
Tfoot(
Tr(
Th(),
Td("Name"),
Td("Job"),
Td("company"),
Td("location"),
Td("Last Login"),
Td("Favorite Color"),
Th()
)
),
cls=combine_classes(table, table_sizes.xs, table_modifiers.pin_rows, table_modifiers.pin_cols)
),
cls=combine_classes(overflow.x.auto)
)
# Verify table structure
assert "overflow-x-auto" in pinned_both_table.attrs['class']
assert pinned_both_table.children[0].tag == "table"
assert "table" in pinned_both_table.children[0].attrs['class']
assert "table-xs" in pinned_both_table.children[0].attrs['class']
assert "table-pin-rows" in pinned_both_table.children[0].attrs['class']
assert "table-pin-cols" in pinned_both_table.children[0].attrs['class']
# Verify thead uses td instead of th for column headers (except first and last)
thead = pinned_both_table.children[0].children[0]
assert thead.tag == "thead"
tr = thead.children[0]
assert tr.children[0].tag == "th" # First column is th
assert tr.children[0].children == () # Empty
assert tr.children[1].tag == "td" # Column headers are td
assert tr.children[1].children[0] == "Name"
assert tr.children[2].tag == "td"
assert tr.children[2].children[0] == "Job"
assert tr.children[-1].tag == "th" # Last column is th
assert tr.children[-1].children == () # Empty
# Verify tbody rows have th at both ends
tbody = pinned_both_table.children[0].children[1]
assert tbody.tag == "tbody"
first_row = tbody.children[0]
assert first_row.children[0].tag == "th"
assert first_row.children[0].children[0] == "1"
assert first_row.children[1].tag == "td"
assert first_row.children[1].children[0] == "Cy Ganderton"
assert first_row.children[-1].tag == "th"
assert first_row.children[-1].children[0] == "1" # Same number on both sides
# Verify last row
last_row = tbody.children[19]
assert last_row.children[0].tag == "th"
assert last_row.children[0].children[0] == "20"
assert last_row.children[1].children[0] == "Lorelei Blackstone"
assert last_row.children[-1].tag == "th"
assert last_row.children[-1].children[0] == "20" # Same number on both sides
# Verify tfoot structure
tfoot = pinned_both_table.children[0].children[2]
assert tfoot.tag == "tfoot"
tfoot_tr = tfoot.children[0]
assert tfoot_tr.children[0].tag == "th" # First column is th
assert tfoot_tr.children[1].tag == "td" # Column footers are td
assert tfoot_tr.children[1].children[0] == "Name"
assert tfoot_tr.children[-1].tag == "th" # Last column is th
# Return all examples in a Div
return Div(
pinned_rows_table,
pinned_both_table
)
# Run the tests
test_table_pinned_fasthtml_examples()| Name | Job | company | location | Last Login | Favorite Color | ||
| 1 | Cy Ganderton | Quality Control Specialist | Littel, Schaden and Vandervort | Canada | 12/16/2020 | Blue | 1 |
| 2 | Hart Hagerty | Desktop Support Technician | Zemlak, Daniel and Leannon | United States | 12/5/2020 | Purple | 2 |
| 3 | Brice Swyre | Tax Accountant | Carroll Group | China | 8/15/2020 | Red | 3 |
| 4 | Marjy Ferencz | Office Assistant I | Rowe-Schoen | Russia | 3/25/2021 | Crimson | 4 |
| 5 | Yancy Tear | Community Outreach Specialist | Wyman-Ledner | Brazil | 5/22/2020 | Indigo | 5 |
| 6 | Irma Vasilik | Editor | Wiza, Bins and Emard | Venezuela | 12/8/2020 | Purple | 6 |
| 7 | Meghann Durtnal | Staff Accountant IV | Schuster-Schimmel | Philippines | 2/17/2021 | Yellow | 7 |
| 8 | Sammy Seston | Accountant I | O'Hara, Welch and Keebler | Indonesia | 5/23/2020 | Crimson | 8 |
| 9 | Lesya Tinham | Safety Technician IV | Turner-Kuhlman | Philippines | 2/21/2021 | Maroon | 9 |
| 10 | Zaneta Tewkesbury | VP Marketing | Sauer LLC | Chad | 6/23/2020 | Green | 10 |
| 11 | Andy Tipple | Librarian | Hilpert Group | Poland | 7/9/2020 | Indigo | 11 |
| 12 | Sophi Biles | Recruiting Manager | Gutmann Inc | Indonesia | 2/12/2021 | Maroon | 12 |
| 13 | Florida Garces | Web Developer IV | Gaylord, Pacocha and Baumbach | Poland | 5/31/2020 | Purple | 13 |
| 14 | Maribeth Popping | Analyst Programmer | Deckow-Pouros | Portugal | 4/27/2021 | Aquamarine | 14 |
| 15 | Moritz Dryburgh | Dental Hygienist | Schiller, Cole and Hackett | Sri Lanka | 8/8/2020 | Crimson | 15 |
| 16 | Reid Semiras | Teacher | Sporer, Sipes and Rogahn | Poland | 7/30/2020 | Green | 16 |
| 17 | Alec Lethby | Teacher | Reichel, Glover and Hamill | China | 2/28/2021 | Khaki | 17 |
| 18 | Aland Wilber | Quality Control Specialist | Kshlerin, Rogahn and Swaniawski | Czech Republic | 9/29/2020 | Purple | 18 |
| 19 | Teddie Duerden | Staff Accountant III | Pouros, Ullrich and Windler | France | 10/27/2020 | Aquamarine | 19 |
| 20 | Lorelei Blackstone | Data Coordinator | Witting, Kutch and Greenfelder | Kazakhstan | 6/3/2020 | Red | 20 |
| Name | Job | company | location | Last Login | Favorite Color |