rx.color to work with conditional vars (#2546)

This commit is contained in:
Elijah Ahianyo 2024-02-08 19:45:15 +00:00 committed by GitHub
parent 64a90fa6eb
commit 601dd34792
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 83 additions and 20 deletions

View File

@ -2,10 +2,11 @@
from reflex.constants.colors import Color, ColorType, ShadeType from reflex.constants.colors import Color, ColorType, ShadeType
from reflex.utils.types import validate_parameter_literals from reflex.utils.types import validate_parameter_literals
from reflex.vars import Var
@validate_parameter_literals @validate_parameter_literals
def color(color: ColorType, shade: ShadeType = 7, alpha: bool = False) -> Color: def color(color: ColorType, shade: ShadeType = 7, alpha: bool = False) -> Var:
"""Create a color object. """Create a color object.
Args: Args:
@ -16,4 +17,4 @@ def color(color: ColorType, shade: ShadeType = 7, alpha: bool = False) -> Color:
Returns: Returns:
The color object. The color object.
""" """
return Color(color, shade, alpha) return Var.create(Color(color, shade, alpha))._replace(_var_is_string=True) # type: ignore

View File

@ -253,24 +253,20 @@ def format_cond(
# Use Python truthiness. # Use Python truthiness.
cond = f"isTrue({cond})" cond = f"isTrue({cond})"
def create_var(cond_part):
return Var.create_safe(cond_part, _var_is_string=type(cond_part) is str)
# Format prop conds. # Format prop conds.
if is_prop: if is_prop:
if not isinstance(true_value, Var): true_value = create_var(true_value)
true_value = Var.create_safe(
true_value,
_var_is_string=type(true_value) is str,
)
prop1 = true_value._replace( prop1 = true_value._replace(
_var_is_local=True, _var_is_local=True,
) )
if not isinstance(false_value, Var):
false_value = Var.create_safe( false_value = create_var(false_value)
false_value,
_var_is_string=type(false_value) is str,
)
prop2 = false_value._replace(_var_is_local=True) prop2 = false_value._replace(_var_is_local=True)
prop1, prop2 = str(prop1), str(prop2) # avoid f-string semantics for Var # unwrap '{}' to avoid f-string semantics for Var
return f"{cond} ? {prop1} : {prop2}".replace("{", "").replace("}", "") return f"{cond} ? {prop1._var_name_unwrapped} : {prop2._var_name_unwrapped}"
# Format component conds. # Format component conds.
return wrap(f"{cond} ? {true_value} : {false_value}", "{") return wrap(f"{cond} ? {true_value} : {false_value}", "{")

View File

@ -1612,13 +1612,13 @@ class Var:
if types.is_generic_alias(self._var_type) if types.is_generic_alias(self._var_type)
else self._var_type else self._var_type
) )
wrapped_var = str(self) wrapped_var = str(self)
return ( return (
wrapped_var wrapped_var
if not self._var_state if not self._var_state
and issubclass(type_, dict) and types._issubclass(type_, dict)
or issubclass(type_, Style) or types._issubclass(type_, Style)
else wrapped_var.strip("{}") else wrapped_var.strip("{}")
) )

View File

View File

@ -0,0 +1,66 @@
import pytest
import reflex as rx
class ColorState(rx.State):
"""Test color state."""
color: str = "mint"
shade: int = 4
@pytest.mark.parametrize(
"color, expected",
[
(rx.color("mint"), "{`var(--mint-7)`}"),
(rx.color("mint", 3), "{`var(--mint-3)`}"),
(rx.color("mint", 3, True), "{`var(--mint-a3)`}"),
(
rx.color(ColorState.color, ColorState.shade), # type: ignore
"{`var(--${state__color_state.color}-${state__color_state.shade})`}",
),
],
)
def test_color(color, expected):
assert str(color) == expected
@pytest.mark.parametrize(
"cond_var, expected",
[
(
rx.cond(True, rx.color("mint"), rx.color("tomato", 5)),
"{isTrue(true) ? `var(--mint-7)` : `var(--tomato-5)`}",
),
(
rx.cond(True, rx.color(ColorState.color), rx.color(ColorState.color, 5)), # type: ignore
"{isTrue(true) ? `var(--${state__color_state.color}-7)` : `var(--${state__color_state.color}-5)`}",
),
(
rx.match(
"condition",
("first", rx.color("mint")),
("second", rx.color("tomato", 5)),
rx.color(ColorState.color, 2), # type: ignore
),
"{(() => { switch (JSON.stringify(`condition`)) {case JSON.stringify(`first`): return (`var(--mint-7)`);"
" break;case JSON.stringify(`second`): return (`var(--tomato-5)`); break;default: "
"return (`var(--${state__color_state.color}-2)`); break;};})()}",
),
(
rx.match(
"condition",
("first", rx.color(ColorState.color)), # type: ignore
("second", rx.color(ColorState.color, 5)), # type: ignore
rx.color(ColorState.color, 2), # type: ignore
),
"{(() => { switch (JSON.stringify(`condition`)) {case JSON.stringify(`first`): "
"return (`var(--${state__color_state.color}-7)`); break;case JSON.stringify(`second`): "
"return (`var(--${state__color_state.color}-5)`); break;default: "
"return (`var(--${state__color_state.color}-2)`); break;};})()}",
),
],
)
def test_color_with_conditionals(cond_var, expected):
assert str(cond_var) == expected

View File

@ -5,7 +5,7 @@ from typing import Any, Dict, List, Type
import pytest import pytest
from reflex.base import Base from reflex.base import Base
from reflex.components.core.colors import color from reflex.components.core.colors import Color
from reflex.utils import serializers from reflex.utils import serializers
from reflex.vars import Var from reflex.vars import Var
@ -170,8 +170,8 @@ class BaseSubclass(Base):
[datetime.timedelta(1, 1, 1), datetime.timedelta(1, 1, 2)], [datetime.timedelta(1, 1, 1), datetime.timedelta(1, 1, 2)],
'["1 day, 0:00:01.000001", "1 day, 0:00:01.000002"]', '["1 day, 0:00:01.000001", "1 day, 0:00:01.000002"]',
), ),
(color("slate", shade=1), "var(--slate-1)"), (Color(color="slate", shade=1), "var(--slate-1)"),
(color("orange", shade=1, alpha=True), "var(--orange-a1)"), (Color(color="orange", shade=1, alpha=True), "var(--orange-a1)"),
], ],
) )
def test_serialize(value: Any, expected: str): def test_serialize(value: Any, expected: str):