reflex/reflex/components/radix/primitives/slider.py

186 lines
4.9 KiB
Python

"""Radix slider components."""
from __future__ import annotations
from typing import Any, Dict, List, Literal
from reflex.components.component import Component, ComponentNamespace
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(ComponentNamespace):
"""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()