Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions reflex/constants/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,4 @@ def __format__(self, format_spec: str) -> str:
Returns:
The formatted color.
"""
from reflex.vars import LiteralColorVar

return LiteralColorVar.create(self).__format__(format_spec)
return format_color(self.color, self.shade, self.alpha)
5 changes: 0 additions & 5 deletions reflex/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@

from reflex import constants
from reflex.components.core.breakpoints import Breakpoints, breakpoints_values
from reflex.constants.colors import Color
from reflex.event import EventChain, EventHandler, EventSpec, run_script
from reflex.utils import format
from reflex.utils.exceptions import ReflexError
from reflex.utils.imports import ImportVar
from reflex.utils.types import typehint_issubclass
from reflex.vars import VarData
from reflex.vars.base import LiteralVar, Var
from reflex.vars.color import LiteralColorVar
from reflex.vars.function import FunctionVar
from reflex.vars.object import ObjectVar

Expand Down Expand Up @@ -134,9 +132,6 @@ def convert_item(
if isinstance(style_item, Var):
return style_item, style_item._get_all_var_data()

if isinstance(style_item, Color):
return LiteralColorVar.create(style_item).to_string(use_json=False), None

# Otherwise, convert to Var to collapse VarData encoded in f-string.
new_var = LiteralVar.create(style_item)
var_data = new_var._get_all_var_data() if new_var is not None else None
Expand Down
10 changes: 3 additions & 7 deletions reflex/utils/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,8 @@ def serialize_decimal(value: decimal.Decimal) -> float:
return float(value)


@serializer(to=dict)
def serialize_color(color: Color) -> dict:
@serializer(to=str)
def serialize_color(color: Color) -> str:
"""Serialize a color.

Args:
Expand All @@ -423,11 +423,7 @@ def serialize_color(color: Color) -> dict:
Returns:
The serialized color.
"""
return {
"color": color.color,
"shade": color.shade,
"alpha": color.alpha,
}
return color.__format__("")


with contextlib.suppress(ImportError):
Expand Down
70 changes: 2 additions & 68 deletions reflex/vars/color.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,72 +10,14 @@
VarData,
cached_property_no_lock,
get_python_literal,
transform,
)
from reflex.vars.number import BooleanVar, NumberVar, ternary_operation
from reflex.vars.object import LiteralObjectVar
from reflex.vars.number import ternary_operation
from reflex.vars.sequence import ConcatVarOperation, LiteralStringVar, StringVar


@transform
def evaluate_color(js_dict: Var[dict]) -> Var[Color]:
"""Evaluate a color var.

Args:
js_dict: The color var as a dict.

Returns:
The color var as a string.
"""
js_color_dict = js_dict.to(dict)
str_part = ConcatVarOperation.create(
LiteralStringVar.create("var(--"),
js_color_dict.color,
LiteralStringVar.create("-"),
ternary_operation(
js_color_dict.alpha,
LiteralStringVar.create("a"),
LiteralStringVar.create(""),
),
js_color_dict.shade.to_string(use_json=False),
LiteralStringVar.create(")"),
)
return js_dict._replace(
_js_expr=f"Object.assign(new String({str_part!s}), {js_dict!s})",
_var_type=Color,
)


class ColorVar(StringVar[Color], python_types=Color):
"""Base class for immutable color vars."""

@property
def color(self) -> StringVar:
"""Get the color of the color var.

Returns:
The color of the color var.
"""
return self.to(dict).color.to(str)

@property
def alpha(self) -> BooleanVar:
"""Get the alpha of the color var.

Returns:
The alpha of the color var.
"""
return self.to(dict).alpha.to(bool)

@property
def shade(self) -> NumberVar:
"""Get the shade of the color var.

Returns:
The shade of the color var.
"""
return self.to(dict).shade.to(int)


@dataclasses.dataclass(
eq=False,
Expand Down Expand Up @@ -150,7 +92,7 @@ def _cached_var_name(self) -> str:
if isinstance(shade, Var)
else LiteralStringVar.create(str(shade))
)
string_part = str(
return str(
ConcatVarOperation.create(
LiteralStringVar.create("var(--"),
self._var_value.color,
Expand All @@ -160,14 +102,6 @@ def _cached_var_name(self) -> str:
LiteralStringVar.create(")"),
)
)
dict_part = LiteralObjectVar.create(
{
"color": self._var_value.color,
"alpha": self._var_value.alpha,
"shade": self._var_value.shade,
}
)
return f"Object.assign(new String({string_part!s}), {dict_part!s})"

@cached_property_no_lock
def _cached_get_all_var_data(self) -> VarData | None:
Expand Down
65 changes: 22 additions & 43 deletions tests/units/components/core/test_colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,36 +32,24 @@ def create_color_var(color):
@pytest.mark.parametrize(
("color", "expected", "expected_type"),
[
(
create_color_var(rx.color("mint")),
'Object.assign(new String("var(--mint-7)"), ({ ["color"] : "mint", ["alpha"] : false, ["shade"] : 7 }))',
Color,
),
(
create_color_var(rx.color("mint", 3)),
'Object.assign(new String("var(--mint-3)"), ({ ["color"] : "mint", ["alpha"] : false, ["shade"] : 3 }))',
Color,
),
(
create_color_var(rx.color("mint", 3, True)),
'Object.assign(new String("var(--mint-a3)"), ({ ["color"] : "mint", ["alpha"] : true, ["shade"] : 3 }))',
Color,
),
(create_color_var(rx.color("mint")), '"var(--mint-7)"', Color),
(create_color_var(rx.color("mint", 3)), '"var(--mint-3)"', Color),
(create_color_var(rx.color("mint", 3, True)), '"var(--mint-a3)"', Color),
(
create_color_var(rx.color(ColorState.color, ColorState.shade)),
f'Object.assign(new String(("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+")")), ({{ ["color"] : {color_state_name!s}.color{FIELD_MARKER}, ["alpha"] : false, ["shade"] : {color_state_name!s}.shade{FIELD_MARKER} }}))',
f'("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+")")',
Color,
),
(
create_color_var(
rx.color(ColorState.color, ColorState.shade, ColorState.alpha)
),
f'Object.assign(new String(("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-"+({color_state_name!s}.alpha{FIELD_MARKER} ? "a" : "")+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+")")), ({{ ["color"] : {color_state_name!s}.color{FIELD_MARKER}, ["alpha"] : {color_state_name!s}.alpha{FIELD_MARKER}, ["shade"] : {color_state_name!s}.shade{FIELD_MARKER} }}))',
f'("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-"+({color_state_name!s}.alpha{FIELD_MARKER} ? "a" : "")+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+")")',
Color,
),
(
create_color_var(color_with_fstring),
f'Object.assign(new String(("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+")")), ({{ ["color"] : {color_state_name!s}.color{FIELD_MARKER}, ["alpha"] : false, ["shade"] : {color_state_name!s}.shade{FIELD_MARKER} }}))',
f'("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+")")',
Color,
),
(
Expand All @@ -71,18 +59,18 @@ def create_color_var(color):
ColorState.shade,
)
),
f'Object.assign(new String(("var(--"+({color_state_name!s}.color_part{FIELD_MARKER}+"ato")+"-"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+")")), ({{ ["color"] : ({color_state_name!s}.color_part{FIELD_MARKER}+"ato"), ["alpha"] : false, ["shade"] : {color_state_name!s}.shade{FIELD_MARKER} }}))',
f'("var(--"+({color_state_name!s}.color_part{FIELD_MARKER}+"ato")+"-"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+")")',
Color,
),
(
create_color_var(f"{rx.color(ColorState.color, ColorState.shade)}"),
f'Object.assign(new String(("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+")")), ({{ ["color"] : {color_state_name!s}.color{FIELD_MARKER}, ["alpha"] : false, ["shade"] : {color_state_name!s}.shade{FIELD_MARKER} }}))',
Color,
f'("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-"+{color_state_name!s}.shade{FIELD_MARKER}+")")',
str,
),
(
create_color_var(f"{color_with_fstring}"),
f'Object.assign(new String(("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-"+(((__to_string) => __to_string.toString())({color_state_name!s}.shade{FIELD_MARKER}))+")")), ({{ ["color"] : {color_state_name!s}.color{FIELD_MARKER}, ["alpha"] : false, ["shade"] : {color_state_name!s}.shade{FIELD_MARKER} }}))',
Color,
f'("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-"+{color_state_name!s}.shade{FIELD_MARKER}+")")',
str,
),
],
)
Expand All @@ -96,11 +84,11 @@ def test_color(color, expected, expected_type: type[str] | type[Color]):
[
(
rx.cond(True, rx.color("mint"), rx.color("tomato", 5)),
'(true ? Object.assign(new String("var(--mint-7)"), ({ ["color"] : "mint", ["alpha"] : false, ["shade"] : 7 })) : Object.assign(new String("var(--tomato-5)"), ({ ["color"] : "tomato", ["alpha"] : false, ["shade"] : 5 })))',
'(true ? "var(--mint-7)" : "var(--tomato-5)")',
),
(
rx.cond(True, rx.color(ColorState.color), rx.color(ColorState.color, 5)),
f'(true ? Object.assign(new String(("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-7)")), ({{ ["color"] : {color_state_name!s}.color{FIELD_MARKER}, ["alpha"] : false, ["shade"] : 7 }})) : Object.assign(new String(("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-5)")), ({{ ["color"] : {color_state_name!s}.color{FIELD_MARKER}, ["alpha"] : false, ["shade"] : 5 }})))',
f'(true ? ("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-7)") : ("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-5)"))',
),
(
rx.match(
Expand All @@ -109,9 +97,9 @@ def test_color(color, expected, expected_type: type[str] | type[Color]):
("second", rx.color("tomato", 5)),
rx.color(ColorState.color, 2),
),
'(() => { switch (JSON.stringify("condition")) {case JSON.stringify("first"): return (Object.assign(new String("var(--mint-7)"), ({ ["color"] : "mint", ["alpha"] : false, ["shade"] : 7 })));'
' break;case JSON.stringify("second"): return (Object.assign(new String("var(--tomato-5)"), ({ ["color"] : "tomato", ["alpha"] : false, ["shade"] : 5 }))); break;default: '
f'return (Object.assign(new String(("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-2)")), ({{ ["color"] : {color_state_name!s}.color{FIELD_MARKER}, ["alpha"] : false, ["shade"] : 2 }}))); break;}};}})()',
'(() => { switch (JSON.stringify("condition")) {case JSON.stringify("first"): return ("var(--mint-7)");'
' break;case JSON.stringify("second"): return ("var(--tomato-5)"); break;default: '
f'return (("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-2)")); break;}};}})()',
),
(
rx.match(
Expand All @@ -121,9 +109,9 @@ def test_color(color, expected, expected_type: type[str] | type[Color]):
rx.color(ColorState.color, 2),
),
'(() => { switch (JSON.stringify("condition")) {case JSON.stringify("first"): '
f'return (Object.assign(new String(("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-7)")), ({{ ["color"] : {color_state_name!s}.color{FIELD_MARKER}, ["alpha"] : false, ["shade"] : 7 }}))); break;case JSON.stringify("second"): '
f'return (Object.assign(new String(("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-5)")), ({{ ["color"] : {color_state_name!s}.color{FIELD_MARKER}, ["alpha"] : false, ["shade"] : 5 }}))); break;default: '
f'return (Object.assign(new String(("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-2)")), ({{ ["color"] : {color_state_name!s}.color{FIELD_MARKER}, ["alpha"] : false, ["shade"] : 2 }}))); break;}};}})()',
f'return (("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-7)")); break;case JSON.stringify("second"): '
f'return (("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-5)")); break;default: '
f'return (("var(--"+{color_state_name!s}.color{FIELD_MARKER}+"-2)")); break;}};}})()',
),
],
)
Expand All @@ -134,18 +122,9 @@ def test_color_with_conditionals(cond_var, expected):
@pytest.mark.parametrize(
("color", "expected"),
[
(
create_color_var(rx.color("red")),
'Object.assign(new String("var(--red-7)"), ({ ["color"] : "red", ["alpha"] : false, ["shade"] : 7 }))',
),
(
create_color_var(rx.color("green", shade=1)),
'Object.assign(new String("var(--green-1)"), ({ ["color"] : "green", ["alpha"] : false, ["shade"] : 1 }))',
),
(
create_color_var(rx.color("blue", alpha=True)),
'Object.assign(new String("var(--blue-a7)"), ({ ["color"] : "blue", ["alpha"] : true, ["shade"] : 7 }))',
),
(create_color_var(rx.color("red")), '"var(--red-7)"'),
(create_color_var(rx.color("green", shade=1)), '"var(--green-1)"'),
(create_color_var(rx.color("blue", alpha=True)), '"var(--blue-a7)"'),
("red", '"red"'),
("green", '"green"'),
("blue", '"blue"'),
Expand Down
5 changes: 2 additions & 3 deletions tests/units/components/test_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -2143,10 +2143,9 @@ def add_style(self): # pyright: ignore [reportIncompatibleMethodOverride]
)
assert "useText" in page._get_all_hooks_internal()
assert "useParent" in page._get_all_hooks_internal()
str_page = str(page)
assert (
str_page.count(
f'css:({{ ["fakeParent"] : "parent", ["color"] : (((__to_string) => __to_string.toString())(Object.assign(new String("var(--plum-10)"), ({{ ["color"] : "plum", ["alpha"] : false, ["shade"] : 10 }})))), ["fake"] : "text", ["margin"] : ({test_state.get_name()}.num{FIELD_MARKER}+"%") }})'
str(page).count(
f'css:({{ ["fakeParent"] : "parent", ["color"] : "var(--plum-10)", ["fake"] : "text", ["margin"] : ({test_state.get_name()}.num{FIELD_MARKER}+"%") }})'
)
== 1
)
Expand Down
18 changes: 4 additions & 14 deletions tests/units/utils/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,9 @@ class BaseSubclass(Base):
[datetime.timedelta(1, 1, 1), datetime.timedelta(1, 1, 2)],
["1 day, 0:00:01.000001", "1 day, 0:00:01.000002"],
),
(Color(color="slate", shade=1), {"color": "slate", "alpha": False, "shade": 1}),
(
Color(color="orange", shade=1, alpha=True),
{"color": "orange", "alpha": True, "shade": 1},
),
(
Color(color="accent", shade=1, alpha=True),
{"color": "accent", "alpha": True, "shade": 1},
),
(Color(color="slate", shade=1), "var(--slate-1)"),
(Color(color="orange", shade=1, alpha=True), "var(--orange-a1)"),
(Color(color="accent", shade=1, alpha=True), "var(--accent-a1)"),
(decimal.Decimal("123.456"), 123.456),
(decimal.Decimal("-0.5"), -0.5),
(decimal.Decimal(0), 0.0),
Expand Down Expand Up @@ -233,11 +227,7 @@ def test_serialize(value: Any, expected: str):
True,
),
(datetime.date(2021, 1, 1), '"2021-01-01"', True),
(
Color(color="slate", shade=1),
'Object.assign(new String("var(--slate-1)"), ({ ["color"] : "slate", ["alpha"] : false, ["shade"] : 1 }))',
True,
),
(Color(color="slate", shade=1), '"var(--slate-1)"', True),
(BaseSubclass, '"BaseSubclass"', True),
(Path(), '"."', True),
(decimal.Decimal("123.456"), "123.456", True),
Expand Down
Loading