|
@@ -1,9 +1,10 @@
|
|
"""Table components."""
|
|
"""Table components."""
|
|
-from typing import List
|
|
|
|
|
|
+from typing import List, Tuple
|
|
|
|
|
|
from reflex.components.component import Component
|
|
from reflex.components.component import Component
|
|
from reflex.components.layout.foreach import Foreach
|
|
from reflex.components.layout.foreach import Foreach
|
|
from reflex.components.libs.chakra import ChakraComponent
|
|
from reflex.components.libs.chakra import ChakraComponent
|
|
|
|
+from reflex.utils import types
|
|
from reflex.vars import Var
|
|
from reflex.vars import Var
|
|
|
|
|
|
|
|
|
|
@@ -44,16 +45,16 @@ class Table(ChakraComponent):
|
|
if len(children) == 0:
|
|
if len(children) == 0:
|
|
children = []
|
|
children = []
|
|
|
|
|
|
- if caption:
|
|
|
|
|
|
+ if caption is not None:
|
|
children.append(TableCaption.create(caption))
|
|
children.append(TableCaption.create(caption))
|
|
|
|
|
|
- if headers:
|
|
|
|
|
|
+ if headers is not None:
|
|
children.append(Thead.create(headers=headers))
|
|
children.append(Thead.create(headers=headers))
|
|
|
|
|
|
- if rows:
|
|
|
|
|
|
+ if rows is not None:
|
|
children.append(Tbody.create(rows=rows))
|
|
children.append(Tbody.create(rows=rows))
|
|
|
|
|
|
- if footers:
|
|
|
|
|
|
+ if footers is not None:
|
|
children.append(Tfoot.create(footers=footers))
|
|
children.append(Tfoot.create(footers=footers))
|
|
return super().create(*children, **props)
|
|
return super().create(*children, **props)
|
|
|
|
|
|
@@ -77,11 +78,36 @@ class Thead(ChakraComponent):
|
|
|
|
|
|
Returns:
|
|
Returns:
|
|
The table header component.
|
|
The table header component.
|
|
|
|
+
|
|
"""
|
|
"""
|
|
if len(children) == 0:
|
|
if len(children) == 0:
|
|
|
|
+ cls.validate_headers(headers)
|
|
|
|
+
|
|
children = [Tr.create(cell_type="header", cells=headers)]
|
|
children = [Tr.create(cell_type="header", cells=headers)]
|
|
return super().create(*children, **props)
|
|
return super().create(*children, **props)
|
|
|
|
|
|
|
|
+ @staticmethod
|
|
|
|
+ def validate_headers(headers):
|
|
|
|
+ """Type checking for table headers.
|
|
|
|
+
|
|
|
|
+ Args:
|
|
|
|
+ headers: The table headers.
|
|
|
|
+
|
|
|
|
+ Raises:
|
|
|
|
+ TypeError: If headers are not of type list or type tuple.
|
|
|
|
+
|
|
|
|
+ """
|
|
|
|
+ allowed_types = (list, tuple)
|
|
|
|
+ if (
|
|
|
|
+ (
|
|
|
|
+ isinstance(headers, Var)
|
|
|
|
+ and not types.check_type_in_allowed_types(headers.type_, allowed_types)
|
|
|
|
+ )
|
|
|
|
+ or not isinstance(headers, Var)
|
|
|
|
+ and not types.check_type_in_allowed_types(type(headers), allowed_types)
|
|
|
|
+ ):
|
|
|
|
+ raise TypeError("table headers should be a list or tuple")
|
|
|
|
+
|
|
|
|
|
|
class Tbody(ChakraComponent):
|
|
class Tbody(ChakraComponent):
|
|
"""A table body component."""
|
|
"""A table body component."""
|
|
@@ -101,9 +127,11 @@ class Tbody(ChakraComponent):
|
|
**props: The properties of the component.
|
|
**props: The properties of the component.
|
|
|
|
|
|
Returns:
|
|
Returns:
|
|
- Component: _description_
|
|
|
|
|
|
+ Component: The table body component
|
|
"""
|
|
"""
|
|
if len(children) == 0:
|
|
if len(children) == 0:
|
|
|
|
+ cls.validate_rows(rows) if rows is not None else None
|
|
|
|
+
|
|
if isinstance(rows, Var):
|
|
if isinstance(rows, Var):
|
|
children = [
|
|
children = [
|
|
Foreach.create(
|
|
Foreach.create(
|
|
@@ -116,6 +144,44 @@ class Tbody(ChakraComponent):
|
|
]
|
|
]
|
|
return super().create(*children, **props)
|
|
return super().create(*children, **props)
|
|
|
|
|
|
|
|
+ @staticmethod
|
|
|
|
+ def validate_rows(rows):
|
|
|
|
+ """Type checking for table rows.
|
|
|
|
+
|
|
|
|
+ Args:
|
|
|
|
+ rows: Table rows.
|
|
|
|
+
|
|
|
|
+ Raises:
|
|
|
|
+ TypeError: If rows are not lists or tuples containing inner lists or tuples.
|
|
|
|
+ """
|
|
|
|
+ allowed_subclasses = (List, Tuple)
|
|
|
|
+ if isinstance(rows, Var):
|
|
|
|
+ outer_type = rows.type_
|
|
|
|
+ inner_type = (
|
|
|
|
+ outer_type.__args__[0] if hasattr(outer_type, "__args__") else None
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ # check that the outer container and inner container types are lists or tuples.
|
|
|
|
+ if not (
|
|
|
|
+ types._issubclass(types.get_base_class(outer_type), allowed_subclasses)
|
|
|
|
+ and (
|
|
|
|
+ inner_type is None
|
|
|
|
+ or types._issubclass(
|
|
|
|
+ types.get_base_class(inner_type), allowed_subclasses
|
|
|
|
+ )
|
|
|
|
+ )
|
|
|
|
+ ):
|
|
|
|
+ raise TypeError(
|
|
|
|
+ f"table rows should be a list or tuple containing inner lists or tuples. Got {outer_type} instead"
|
|
|
|
+ )
|
|
|
|
+ elif not (
|
|
|
|
+ types._issubclass(type(rows), allowed_subclasses)
|
|
|
|
+ and (not rows or types._issubclass(type(rows[0]), allowed_subclasses))
|
|
|
|
+ ):
|
|
|
|
+ raise TypeError(
|
|
|
|
+ "table rows should be a list or tuple containing inner lists or tuples."
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
|
|
class Tfoot(ChakraComponent):
|
|
class Tfoot(ChakraComponent):
|
|
"""A table footer component."""
|
|
"""A table footer component."""
|
|
@@ -138,9 +204,31 @@ class Tfoot(ChakraComponent):
|
|
The table footer component.
|
|
The table footer component.
|
|
"""
|
|
"""
|
|
if len(children) == 0:
|
|
if len(children) == 0:
|
|
|
|
+ cls.validate_footers(footers)
|
|
children = [Tr.create(cell_type="header", cells=footers)]
|
|
children = [Tr.create(cell_type="header", cells=footers)]
|
|
return super().create(*children, **props)
|
|
return super().create(*children, **props)
|
|
|
|
|
|
|
|
+ @staticmethod
|
|
|
|
+ def validate_footers(footers):
|
|
|
|
+ """Type checking for table footers.
|
|
|
|
+
|
|
|
|
+ Args:
|
|
|
|
+ footers: Table rows.
|
|
|
|
+
|
|
|
|
+ Raises:
|
|
|
|
+ TypeError: If footers are not of type list.
|
|
|
|
+ """
|
|
|
|
+ allowed_types = (list, tuple)
|
|
|
|
+ if (
|
|
|
|
+ (
|
|
|
|
+ isinstance(footers, Var)
|
|
|
|
+ and not types.check_type_in_allowed_types(footers.type_, allowed_types)
|
|
|
|
+ )
|
|
|
|
+ or not isinstance(footers, Var)
|
|
|
|
+ and not types.check_type_in_allowed_types(type(footers), allowed_types)
|
|
|
|
+ ):
|
|
|
|
+ raise TypeError("table headers should be a list or tuple")
|
|
|
|
+
|
|
|
|
|
|
class Tr(ChakraComponent):
|
|
class Tr(ChakraComponent):
|
|
"""A table row component."""
|
|
"""A table row component."""
|