"""Radix slider components.""" from __future__ import annotations from types import SimpleNamespace from typing import Any, Dict, List, Literal from reflex.components.component import Component from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName from reflex.style import Style from reflex.vars import Var LiteralSliderOrientation = Literal["horizontal", "vertical"] LiteralSliderDir = Literal["ltr", "rtl"] class SliderComponent(RadixPrimitiveComponentWithClassName): """Base class for all @radix-ui/react-slider components.""" library = "@radix-ui/react-slider@^1.1.2" class SliderRoot(SliderComponent): """The Slider component comtaining all slider parts.""" tag = "Root" alias = "RadixSliderRoot" default_value: Var[List[int]] value: Var[List[int]] name: Var[str] disabled: Var[bool] orientation: Var[LiteralSliderOrientation] dir: Var[LiteralSliderDir] inverted: Var[bool] min: Var[int] max: Var[int] step: Var[int] min_steps_between_thumbs: Var[int] def get_event_triggers(self) -> Dict[str, Any]: """Event triggers for radix slider primitive. Returns: The triggers for event supported by radix primitives. """ return { **super().get_event_triggers(), "on_value_change": lambda e0: [e0], # trigger for all change of a thumb "on_value_commit": lambda e0: [e0], # trigger when thumb is released } def _apply_theme(self, theme: Component): self.style = Style( { "position": "relative", "display": "flex", "align_items": "center", "user_select": "none", "touch_action": "none", "width": "200px", "height": "20px", "&[data-orientation='vertical']": { "flex_direction": "column", "width": "20px", "height": "100px", }, **self.style, } ) class SliderTrack(SliderComponent): """A Slider Track component.""" tag = "Track" alias = "RadixSliderTrack" def _apply_theme(self, theme: Component): self.style = Style( { "position": "relative", "flex_grow": "1", "background_color": "black", "border_radius": "9999px", "height": "3px", "&[data-orientation='vertical']": { "width": "3px", }, **self.style, } ) class SliderRange(SliderComponent): """A SliderRange component.""" tag = "Range" alias = "RadixSliderRange" def _apply_theme(self, theme: Component): self.style = Style( { "position": "absolute", "background_color": "white", "height": "100%", "&[data-orientation='vertical']": { "width": "100%", }, **self.style, } ) class SliderThumb(SliderComponent): """A SliderThumb component.""" tag = "Thumb" alias = "RadixSliderThumb" def _apply_theme(self, theme: Component): self.style = Style( { "display": "block", "width": "20px", "height": "20px", "background_color": "black", "box_shadow": "0 2px 10px black", "border_radius": "10px", "&:hover": { "background_color": "gray", }, "&:focus": { "outline": "none", "box_shadow": "0 0 0 4px gray", }, **self.style, } ) class Slider(SimpleNamespace): """High level API for slider.""" root = staticmethod(SliderRoot.create) track = staticmethod(SliderTrack.create) range = staticmethod(SliderRange.create) thumb = staticmethod(SliderThumb.create) @staticmethod def __call__(**props) -> Component: """High level API for slider. Args: **props: The props of the slider. Returns: A slider component. """ track = SliderTrack.create(SliderRange.create()) # if default_value is not set, the thumbs will not render properly but the slider will still work if "default_value" in props: children = [ track, *[SliderThumb.create() for _ in props.get("default_value", [])], ] else: children = [ track, # Foreach.create(props.get("value"), lambda e: SliderThumb.create()), # foreach doesn't render Thumbs properly ] return SliderRoot.create(*children, **props) slider = Slider()