list.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. """List components."""
  2. from typing import Iterable, Literal, Optional, Union
  3. from reflex.components.component import Component, ComponentNamespace
  4. from reflex.components.core.foreach import Foreach
  5. from reflex.components.el.elements.typography import Li
  6. from reflex.components.lucide.icon import Icon
  7. from reflex.components.radix.themes.typography.text import Text
  8. from reflex.style import Style
  9. from reflex.vars import Var
  10. from .base import LayoutComponent
  11. from .flex import Flex
  12. LiteralListStyleTypeUnordered = Literal[
  13. "none",
  14. "disc",
  15. "circle",
  16. "square",
  17. ]
  18. LiteralListStyleTypeOrdered = Literal[
  19. "none",
  20. "decimal",
  21. "decimal-leading-zero",
  22. "lower-roman",
  23. "upper-roman",
  24. "lower-greek",
  25. "lower-latin",
  26. "upper-latin",
  27. "armenian",
  28. "georgian",
  29. "lower-alpha",
  30. "upper-alpha",
  31. "hiragana",
  32. "katakana",
  33. ]
  34. class BaseList(Flex, LayoutComponent):
  35. """Base class for ordered and unordered lists."""
  36. # The style of the list. Default to "none".
  37. list_style_type: Var[
  38. Union[LiteralListStyleTypeUnordered, LiteralListStyleTypeOrdered]
  39. ]
  40. @classmethod
  41. def create(
  42. cls,
  43. *children,
  44. items: Optional[Union[Var[Iterable], Iterable]] = None,
  45. **props,
  46. ):
  47. """Create a list component.
  48. Args:
  49. *children: The children of the component.
  50. items: A list of items to add to the list.
  51. **props: The properties of the component.
  52. Returns:
  53. The list component.
  54. """
  55. list_style_type = props.pop("list_style_type", "none")
  56. if not children and items is not None:
  57. if isinstance(items, Var):
  58. children = [Foreach.create(items, ListItem.create)]
  59. else:
  60. children = [ListItem.create(item) for item in items]
  61. # props["list_style_type"] = list_style_type
  62. props["direction"] = "column"
  63. style = props.setdefault("style", {})
  64. style["list_style_position"] = "outside"
  65. style["list_style_type"] = list_style_type
  66. if "gap" in props:
  67. style["gap"] = props["gap"]
  68. return super().create(*children, **props)
  69. def _apply_theme(self, theme: Component):
  70. self.style = Style(
  71. {
  72. "direction": "column",
  73. "list_style_position": "outside",
  74. **self.style,
  75. }
  76. )
  77. class UnorderedList(BaseList):
  78. """Display an unordered list."""
  79. @classmethod
  80. def create(
  81. cls,
  82. *children,
  83. items: Optional[Var[Iterable]] = None,
  84. list_style_type: LiteralListStyleTypeUnordered = "disc",
  85. **props,
  86. ):
  87. """Create a unordered list component.
  88. Args:
  89. *children: The children of the component.
  90. items: A list of items to add to the list.
  91. list_style_type: The style of the list.
  92. **props: The properties of the component.
  93. Returns:
  94. The list component.
  95. """
  96. return super().create(
  97. *children, items=items, list_style_type=list_style_type, **props
  98. )
  99. class OrderedList(BaseList):
  100. """Display an ordered list."""
  101. @classmethod
  102. def create(
  103. cls,
  104. *children,
  105. items: Optional[Var[Iterable]] = None,
  106. list_style_type: LiteralListStyleTypeOrdered = "decimal",
  107. **props,
  108. ):
  109. """Create an ordered list component.
  110. Args:
  111. *children: The children of the component.
  112. items: A list of items to add to the list.
  113. list_style_type: The style of the list.
  114. **props: The properties of the component.
  115. Returns:
  116. The list component.
  117. """
  118. return super().create(
  119. *children, items=items, list_style_type=list_style_type, **props
  120. )
  121. class ListItem(Li):
  122. """Display an item of an ordered or unordered list."""
  123. @classmethod
  124. def create(cls, *children, **props):
  125. """Create a list item component.
  126. Args:
  127. *children: The children of the component.
  128. **props: The properties of the component.
  129. Returns:
  130. The list item component.
  131. """
  132. for child in children:
  133. if isinstance(child, Text):
  134. child.as_ = "span"
  135. elif isinstance(child, Icon) and "display" not in child.style:
  136. child.style["display"] = "inline"
  137. return super().create(*children, **props)
  138. class List(ComponentNamespace):
  139. """List components."""
  140. item = staticmethod(ListItem.create)
  141. ordered = staticmethod(OrderedList.create)
  142. unordered = staticmethod(UnorderedList.create)
  143. __call__ = staticmethod(BaseList.create)
  144. list_ns = List()