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

184 lines
4.6 KiB
Python

"""Radix slider components."""
from __future__ import annotations
from typing import Any, List, Literal
from reflex.components.component import Component, ComponentNamespace
from reflex.components.radix.primitives.base import RadixPrimitiveComponentWithClassName
from reflex.event import EventHandler
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]
# Fired when the value of a thumb changes.
on_value_change: EventHandler[lambda e0: [e0]]
# Fired when a thumb is released.
on_value_commit: EventHandler[lambda e0: [e0]]
def add_style(self) -> dict[str, Any] | None:
"""Add style to the component.
Returns:
The style of the component.
"""
return {
"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",
},
}
class SliderTrack(SliderComponent):
"""A Slider Track component."""
tag = "Track"
alias = "RadixSliderTrack"
def add_style(self) -> dict[str, Any] | None:
"""Add style to the component.
Returns:
The style of the component.
"""
return {
"position": "relative",
"flex_grow": "1",
"background_color": "black",
"border_radius": "9999px",
"height": "3px",
"&[data-orientation='vertical']": {"width": "3px"},
}
class SliderRange(SliderComponent):
"""A SliderRange component."""
tag = "Range"
alias = "RadixSliderRange"
def add_style(self) -> dict[str, Any] | None:
"""Add style to the component.
Returns:
The style of the component.
"""
return {
"position": "absolute",
"background_color": "white",
"height": "100%",
"&[data-orientation='vertical']": {"width": "100%"},
}
class SliderThumb(SliderComponent):
"""A SliderThumb component."""
tag = "Thumb"
alias = "RadixSliderThumb"
def add_style(self) -> dict[str, Any] | None:
"""Add style to the component.
Returns:
The style of the component.
"""
return {
"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",
},
}
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()