diff --git a/reflex/constants/colors.py b/reflex/constants/colors.py index 22a74a4d494..f769f8099b6 100644 --- a/reflex/constants/colors.py +++ b/reflex/constants/colors.py @@ -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) diff --git a/reflex/style.py b/reflex/style.py index 88a5bf3c2d7..6dc43fcd504 100644 --- a/reflex/style.py +++ b/reflex/style.py @@ -7,7 +7,6 @@ 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 @@ -15,7 +14,6 @@ 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 @@ -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 diff --git a/reflex/utils/serializers.py b/reflex/utils/serializers.py index 692044a0721..32283c8b411 100644 --- a/reflex/utils/serializers.py +++ b/reflex/utils/serializers.py @@ -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: @@ -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): diff --git a/reflex/vars/color.py b/reflex/vars/color.py index b1d7c245ac5..f699eac35ad 100644 --- a/reflex/vars/color.py +++ b/reflex/vars/color.py @@ -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, @@ -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, @@ -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: diff --git a/tests/units/components/core/test_colors.py b/tests/units/components/core/test_colors.py index f0958d4a249..417b12e7261 100644 --- a/tests/units/components/core/test_colors.py +++ b/tests/units/components/core/test_colors.py @@ -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, ), ( @@ -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, ), ], ) @@ -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( @@ -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( @@ -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;}};}})()', ), ], ) @@ -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"'), diff --git a/tests/units/components/test_component.py b/tests/units/components/test_component.py index 5a048fa7652..48bec2ba9cf 100644 --- a/tests/units/components/test_component.py +++ b/tests/units/components/test_component.py @@ -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 ) diff --git a/tests/units/utils/test_serializers.py b/tests/units/utils/test_serializers.py index ea8a20171d9..a81177ab226 100644 --- a/tests/units/utils/test_serializers.py +++ b/tests/units/utils/test_serializers.py @@ -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), @@ -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),