slider.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. """Radix slider components."""
  2. from __future__ import annotations
  3. from types import SimpleNamespace
  4. from typing import Any, Dict, List, Literal
  5. from reflex.components.component import Component
  6. from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName
  7. from reflex.style import Style
  8. from reflex.vars import Var
  9. LiteralSliderOrientation = Literal["horizontal", "vertical"]
  10. LiteralSliderDir = Literal["ltr", "rtl"]
  11. class SliderComponent(RadixPrimitiveComponentWithClassName):
  12. """Base class for all @radix-ui/react-slider components."""
  13. library = "@radix-ui/react-slider@^1.1.2"
  14. class SliderRoot(SliderComponent):
  15. """The Slider component comtaining all slider parts."""
  16. tag = "Root"
  17. alias = "RadixSliderRoot"
  18. default_value: Var[List[int]]
  19. value: Var[List[int]]
  20. name: Var[str]
  21. disabled: Var[bool]
  22. orientation: Var[LiteralSliderOrientation]
  23. dir: Var[LiteralSliderDir]
  24. inverted: Var[bool]
  25. min: Var[int]
  26. max: Var[int]
  27. step: Var[int]
  28. min_steps_between_thumbs: Var[int]
  29. def get_event_triggers(self) -> Dict[str, Any]:
  30. """Event triggers for radix slider primitive.
  31. Returns:
  32. The triggers for event supported by radix primitives.
  33. """
  34. return {
  35. **super().get_event_triggers(),
  36. "on_value_change": lambda e0: [e0], # trigger for all change of a thumb
  37. "on_value_commit": lambda e0: [e0], # trigger when thumb is released
  38. }
  39. def _apply_theme(self, theme: Component):
  40. self.style = Style(
  41. {
  42. "position": "relative",
  43. "display": "flex",
  44. "align_items": "center",
  45. "user_select": "none",
  46. "touch_action": "none",
  47. "width": "200px",
  48. "height": "20px",
  49. "&[data-orientation='vertical']": {
  50. "flex_direction": "column",
  51. "width": "20px",
  52. "height": "100px",
  53. },
  54. **self.style,
  55. }
  56. )
  57. class SliderTrack(SliderComponent):
  58. """A Slider Track component."""
  59. tag = "Track"
  60. alias = "RadixSliderTrack"
  61. def _apply_theme(self, theme: Component):
  62. self.style = Style(
  63. {
  64. "position": "relative",
  65. "flex_grow": "1",
  66. "background_color": "black",
  67. "border_radius": "9999px",
  68. "height": "3px",
  69. "&[data-orientation='vertical']": {
  70. "width": "3px",
  71. },
  72. **self.style,
  73. }
  74. )
  75. class SliderRange(SliderComponent):
  76. """A SliderRange component."""
  77. tag = "Range"
  78. alias = "RadixSliderRange"
  79. def _apply_theme(self, theme: Component):
  80. self.style = Style(
  81. {
  82. "position": "absolute",
  83. "background_color": "white",
  84. "height": "100%",
  85. "&[data-orientation='vertical']": {
  86. "width": "100%",
  87. },
  88. **self.style,
  89. }
  90. )
  91. class SliderThumb(SliderComponent):
  92. """A SliderThumb component."""
  93. tag = "Thumb"
  94. alias = "RadixSliderThumb"
  95. def _apply_theme(self, theme: Component):
  96. self.style = Style(
  97. {
  98. "display": "block",
  99. "width": "20px",
  100. "height": "20px",
  101. "background_color": "black",
  102. "box_shadow": "0 2px 10px black",
  103. "border_radius": "10px",
  104. "&:hover": {
  105. "background_color": "gray",
  106. },
  107. "&:focus": {
  108. "outline": "none",
  109. "box_shadow": "0 0 0 4px gray",
  110. },
  111. **self.style,
  112. }
  113. )
  114. class Slider(SimpleNamespace):
  115. """High level API for slider."""
  116. root = staticmethod(SliderRoot.create)
  117. track = staticmethod(SliderTrack.create)
  118. range = staticmethod(SliderRange.create)
  119. thumb = staticmethod(SliderThumb.create)
  120. @staticmethod
  121. def __call__(**props) -> Component:
  122. """High level API for slider.
  123. Args:
  124. **props: The props of the slider.
  125. Returns:
  126. A slider component.
  127. """
  128. track = SliderTrack.create(SliderRange.create())
  129. # if default_value is not set, the thumbs will not render properly but the slider will still work
  130. if "default_value" in props:
  131. children = [
  132. track,
  133. *[SliderThumb.create() for _ in props.get("default_value", [])],
  134. ]
  135. else:
  136. children = [
  137. track,
  138. # Foreach.create(props.get("value"), lambda e: SliderThumb.create()), # foreach doesn't render Thumbs properly
  139. ]
  140. return SliderRoot.create(*children, **props)
  141. slider = Slider()