slider.py 4.6 KB

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