Browse Source

Pass _var_is_string parameter to Var.create (#3470)

Masen Furer 11 months ago
parent
commit
66f0a49b75
36 changed files with 163 additions and 90 deletions
  1. 3 1
      reflex/components/chakra/base.py
  2. 1 1
      reflex/components/chakra/forms/checkbox.py
  3. 1 1
      reflex/components/chakra/forms/pininput.py
  4. 1 1
      reflex/components/chakra/forms/rangeslider.py
  5. 3 1
      reflex/components/chakra/navigation/link.py
  6. 16 7
      reflex/components/component.py
  7. 2 1
      reflex/components/core/banner.py
  8. 1 1
      reflex/components/core/client_side_routing.py
  9. 3 1
      reflex/components/core/debounce.py
  10. 1 1
      reflex/components/core/foreach.py
  11. 1 0
      reflex/components/core/upload.py
  12. 4 1
      reflex/components/datadisplay/code.py
  13. 4 6
      reflex/components/datadisplay/dataeditor.py
  14. 7 3
      reflex/components/el/elements/forms.py
  15. 1 1
      reflex/components/el/elements/forms.pyi
  16. 16 10
      reflex/components/markdown/markdown.py
  17. 12 8
      reflex/components/markdown/markdown.pyi
  18. 7 3
      reflex/components/plotly/plotly.py
  19. 1 1
      reflex/components/radix/primitives/accordion.py
  20. 1 0
      reflex/components/radix/themes/base.py
  21. 1 1
      reflex/components/radix/themes/color_mode.py
  22. 3 1
      reflex/components/radix/themes/components/checkbox.py
  23. 6 4
      reflex/components/radix/themes/components/radio_group.py
  24. 1 1
      reflex/components/radix/themes/components/separator.py
  25. 1 1
      reflex/components/radix/themes/layout/container.py
  26. 1 1
      reflex/components/radix/themes/layout/section.py
  27. 1 1
      reflex/components/recharts/charts.py
  28. 7 3
      reflex/components/sonner/toast.py
  29. 1 1
      reflex/components/sonner/toast.pyi
  30. 2 1
      reflex/components/tags/tag.py
  31. 12 9
      reflex/event.py
  32. 8 2
      reflex/experimental/hooks.py
  33. 9 2
      reflex/experimental/layout.py
  34. 2 2
      reflex/style.py
  35. 4 1
      reflex/utils/format.py
  36. 18 10
      reflex/vars.py

+ 3 - 1
reflex/components/chakra/base.py

@@ -65,7 +65,9 @@ class ChakraProvider(ChakraComponent):
             A new ChakraProvider component.
         """
         return super().create(
-            theme=Var.create("extendTheme(theme)", _var_is_local=False),
+            theme=Var.create(
+                "extendTheme(theme)", _var_is_local=False, _var_is_string=False
+            ),
         )
 
     def _get_imports(self) -> imports.ImportDict:

+ 1 - 1
reflex/components/chakra/forms/checkbox.py

@@ -51,7 +51,7 @@ class Checkbox(ChakraComponent):
     name: Var[str]
 
     # The value of the input field when checked (use is_checked prop for a bool)
-    value: Var[str] = Var.create("true")  # type: ignore
+    value: Var[str] = Var.create("true", _var_is_string=True)  # type: ignore
 
     # The spacing between the checkbox and its label text (0.5rem)
     spacing: Var[str]

+ 1 - 1
reflex/components/chakra/forms/pininput.py

@@ -122,7 +122,7 @@ class PinInput(ChakraComponent):
             if ref:
                 return (
                     f"const {ref} = {str(refs_declaration)}; "
-                    f"{str(Var.create_safe(ref).as_ref())} = {ref}"
+                    f"{str(Var.create_safe(ref, _var_is_string=False).as_ref())} = {ref}"
                 )
             return super()._get_ref_hook()
 

+ 1 - 1
reflex/components/chakra/forms/rangeslider.py

@@ -80,7 +80,7 @@ class RangeSlider(ChakraComponent):
             if ref:
                 return (
                     f"const {ref} = Array.from({{length:2}}, () => useRef(null)); "
-                    f"{str(Var.create_safe(ref).as_ref())} = {ref}"
+                    f"{str(Var.create_safe(ref, _var_is_string=False).as_ref())} = {ref}"
                 )
             return super()._get_ref_hook()
 

+ 3 - 1
reflex/components/chakra/navigation/link.py

@@ -25,7 +25,9 @@ class Link(ChakraComponent):
     text: Var[str]
 
     # What the link renders to.
-    as_: Var[str] = BaseVar.create(value="{NextLink}", _var_is_local=False)  # type: ignore
+    as_: Var[str] = BaseVar.create(
+        value="{NextLink}", _var_is_local=False, _var_is_string=False
+    )  # type: ignore
 
     # If true, the link will open in new tab.
     is_external: Var[bool]

+ 16 - 7
reflex/components/component.py

@@ -319,7 +319,9 @@ class Component(BaseComponent, ABC):
             # Set default values for any props.
             if types._issubclass(field.type_, Var):
                 field.required = False
-                field.default = Var.create(field.default)
+                field.default = Var.create(
+                    field.default, _var_is_string=isinstance(field.default, str)
+                )
             elif types._issubclass(field.type_, EventHandler):
                 field.required = False
 
@@ -348,7 +350,10 @@ class Component(BaseComponent, ABC):
             "id": kwargs.get("id"),
             "children": children,
             **{
-                prop: Var.create(kwargs[prop])
+                prop: Var.create(
+                    kwargs[prop],
+                    _var_is_string=False,
+                )
                 for prop in self.get_initial_props()
                 if prop in kwargs
             },
@@ -395,7 +400,7 @@ class Component(BaseComponent, ABC):
                 passed_types = None
                 try:
                     # Try to create a var from the value.
-                    kwargs[key] = Var.create(value)
+                    kwargs[key] = Var.create(value, _var_is_string=False)
 
                     # Check that the var type is not None.
                     if kwargs[key] is None:
@@ -672,7 +677,9 @@ class Component(BaseComponent, ABC):
             # Add ref to element if `id` is not None.
             ref = self.get_ref()
             if ref is not None:
-                props["ref"] = Var.create(ref, _var_is_local=False)
+                props["ref"] = Var.create(
+                    ref, _var_is_local=False, _var_is_string=False
+                )
         else:
             props = props.copy()
 
@@ -1091,7 +1098,9 @@ class Component(BaseComponent, ABC):
                 vars.append(comp_prop)
             elif isinstance(comp_prop, str):
                 # Collapse VarData encoded in f-strings.
-                var = Var.create_safe(comp_prop)
+                var = Var.create_safe(
+                    comp_prop, _var_is_string=isinstance(comp_prop, str)
+                )
                 if var._var_data is not None:
                     vars.append(var)
 
@@ -1388,7 +1397,7 @@ class Component(BaseComponent, ABC):
         """
         ref = self.get_ref()
         if ref is not None:
-            return f"const {ref} = useRef(null); {str(Var.create_safe(ref).as_ref())} = {ref};"
+            return f"const {ref} = useRef(null); {str(Var.create_safe(ref, _var_is_string=False).as_ref())} = {ref};"
 
     def _get_vars_hooks(self) -> dict[str, None]:
         """Get the hooks required by vars referenced in this component.
@@ -2147,7 +2156,7 @@ class StatefulComponent(BaseComponent):
 
             # Store the memoized function name and hook code for this event trigger.
             trigger_memo[event_trigger] = (
-                Var.create_safe(memo_name)._replace(
+                Var.create_safe(memo_name, _var_is_string=False)._replace(
                     _var_type=EventChain, merge_var_data=memo_var_data
                 ),
                 f"const {memo_name} = useCallback({rendered_chain}, [{', '.join(var_deps)}])",

+ 2 - 1
reflex/components/core/banner.py

@@ -132,7 +132,8 @@ useEffect(() => {{
         toast.dismiss("{toast_id}");
         setUserDismissed(false);  // after reconnection reset dismissed state
     }}
-}}, [{connect_errors}]);"""
+}}, [{connect_errors}]);""",
+            _var_is_string=False,
         )
 
         hook._var_data = VarData.merge(  # type: ignore

+ 1 - 1
reflex/components/core/client_side_routing.py

@@ -14,7 +14,7 @@ from reflex.components.component import Component
 from reflex.components.core.cond import cond
 from reflex.vars import Var
 
-route_not_found: Var = Var.create_safe(constants.ROUTE_NOT_FOUND)
+route_not_found: Var = Var.create_safe(constants.ROUTE_NOT_FOUND, _var_is_string=False)
 
 
 class ClientSideRouting(Component):

+ 3 - 1
reflex/components/core/debounce.py

@@ -99,7 +99,9 @@ class DebounceInput(Component):
             props["class_name"] = f"{props.get('class_name', '')} {child.class_name}"
         child_ref = child.get_ref()
         if props.get("input_ref") is None and child_ref:
-            props["input_ref"] = Var.create_safe(child_ref, _var_is_local=False)
+            props["input_ref"] = Var.create_safe(
+                child_ref, _var_is_local=False, _var_is_string=False
+            )
             props["id"] = child.id
 
         # Set the child element to wrap, including any imports/hooks from the child.

+ 1 - 1
reflex/components/core/foreach.py

@@ -60,7 +60,7 @@ class Foreach(Component):
                 deprecation_version="0.5.0",
                 removal_version="0.6.0",
             )
-        iterable = Var.create_safe(iterable)
+        iterable = Var.create_safe(iterable, _var_is_string=False)
         if iterable._var_type == Any:
             raise ForeachVarError(
                 f"Could not foreach over var `{iterable._var_full_name}` of type Any. "

+ 1 - 0
reflex/components/core/upload.py

@@ -119,6 +119,7 @@ def get_upload_dir() -> Path:
 
 uploaded_files_url_prefix: Var = Var.create_safe(
     "${getBackendURL(env.UPLOAD)}",
+    _var_is_string=False,
     _var_data=VarData(
         imports={
             f"/{Dirs.STATE_PATH}": [imports.ImportVar(tag="getBackendURL")],

+ 4 - 1
reflex/components/datadisplay/code.py

@@ -504,10 +504,13 @@ class CodeBlock(Component):
             style=Var.create(
                 format.to_camel_case(f"{predicate}{qmark}{value.replace('`', '')}"),
                 _var_is_local=False,
+                _var_is_string=False,
             )
         ).remove_props("theme", "code")
         if self.code is not None:
-            out.special_props.add(Var.create_safe(f"children={str(self.code)}"))
+            out.special_props.add(
+                Var.create_safe(f"children={str(self.code)}", _var_is_string=False)
+            )
         return out
 
     @staticmethod

+ 4 - 6
reflex/components/datadisplay/dataeditor.py

@@ -263,7 +263,9 @@ class DataEditor(NoSSRComponent):
 
         # Define the name of the getData callback associated with this component and assign to get_cell_content.
         data_callback = f"getData_{editor_id}"
-        self.get_cell_content = Var.create(data_callback, _var_is_local=False)  # type: ignore
+        self.get_cell_content = Var.create(
+            data_callback, _var_is_local=False, _var_is_string=False
+        )  # type: ignore
 
         code = [f"function {data_callback}([col, row])" "{"]
 
@@ -301,11 +303,7 @@ class DataEditor(NoSSRComponent):
 
         # If rows is not provided, determine from data.
         if rows is None:
-            props["rows"] = (
-                data.length()  # BaseVar.create(value=f"{data}.length()", is_local=False)
-                if isinstance(data, Var)
-                else len(data)
-            )
+            props["rows"] = data.length() if isinstance(data, Var) else len(data)
 
         if not isinstance(columns, Var) and len(columns):
             if (

+ 7 - 3
reflex/components/el/elements/forms.py

@@ -17,7 +17,7 @@ from reflex.vars import BaseVar, Var
 
 from .base import BaseHTML
 
-FORM_DATA = Var.create("form_data")
+FORM_DATA = Var.create("form_data", _var_is_string=False)
 HANDLE_SUBMIT_JS_JINJA2 = Environment().from_string(
     """
     const handleSubmit_{{ handle_submit_unique_name }} = useCallback((ev) => {
@@ -221,17 +221,19 @@ class Form(BaseHTML):
             # when ref start with refs_ it's an array of refs, so we need different method
             # to collect data
             if ref.startswith("refs_"):
-                ref_var = Var.create_safe(ref[:-3]).as_ref()
+                ref_var = Var.create_safe(ref[:-3], _var_is_string=False).as_ref()
                 form_refs[ref[5:-3]] = Var.create_safe(
                     f"getRefValues({str(ref_var)})",
                     _var_is_local=False,
+                    _var_is_string=False,
                     _var_data=ref_var._var_data,
                 )
             else:
-                ref_var = Var.create_safe(ref).as_ref()
+                ref_var = Var.create_safe(ref, _var_is_string=False).as_ref()
                 form_refs[ref[4:]] = Var.create_safe(
                     f"getRefValue({str(ref_var)})",
                     _var_is_local=False,
+                    _var_is_string=False,
                     _var_data=ref_var._var_data,
                 )
         return form_refs
@@ -630,6 +632,7 @@ class Textarea(BaseHTML):
                 on_key_down=Var.create_safe(
                     f"(e) => enterKeySubmitOnKeyDown(e, {self.enter_key_submit._var_name_unwrapped})",
                     _var_is_local=False,
+                    _var_is_string=False,
                     _var_data=self.enter_key_submit._var_data,
                 )
             )
@@ -638,6 +641,7 @@ class Textarea(BaseHTML):
                 on_input=Var.create_safe(
                     f"(e) => autoHeightOnInput(e, {self.auto_height._var_name_unwrapped})",
                     _var_is_local=False,
+                    _var_is_string=False,
                     _var_data=self.auto_height._var_data,
                 )
             )

+ 1 - 1
reflex/components/el/elements/forms.pyi

@@ -19,7 +19,7 @@ from reflex.utils.format import format_event_chain
 from reflex.vars import BaseVar, Var
 from .base import BaseHTML
 
-FORM_DATA = Var.create("form_data")
+FORM_DATA = Var.create("form_data", _var_is_string=False)
 HANDLE_SUBMIT_JS_JINJA2 = Environment().from_string(
     "\n    const handleSubmit_{{ handle_submit_unique_name }} = useCallback((ev) => {\n        const $form = ev.target\n        ev.preventDefault()\n        const {{ form_data }} = {...Object.fromEntries(new FormData($form).entries()), ...{{ field_ref_mapping }}}\n\n        {{ on_submit_event_chain }}\n\n        if ({{ reset_on_submit }}) {\n            $form.reset()\n        }\n    })\n    "
 )

+ 16 - 10
reflex/components/markdown/markdown.py

@@ -23,19 +23,23 @@ from reflex.utils.imports import ImportVar
 from reflex.vars import Var
 
 # Special vars used in the component map.
-_CHILDREN = Var.create_safe("children", _var_is_local=False)
-_PROPS = Var.create_safe("...props", _var_is_local=False)
-_MOCK_ARG = Var.create_safe("")
+_CHILDREN = Var.create_safe("children", _var_is_local=False, _var_is_string=False)
+_PROPS = Var.create_safe("...props", _var_is_local=False, _var_is_string=False)
+_MOCK_ARG = Var.create_safe("", _var_is_string=False)
 
 # Special remark plugins.
-_REMARK_MATH = Var.create_safe("remarkMath", _var_is_local=False)
-_REMARK_GFM = Var.create_safe("remarkGfm", _var_is_local=False)
-_REMARK_UNWRAP_IMAGES = Var.create_safe("remarkUnwrapImages", _var_is_local=False)
+_REMARK_MATH = Var.create_safe("remarkMath", _var_is_local=False, _var_is_string=False)
+_REMARK_GFM = Var.create_safe("remarkGfm", _var_is_local=False, _var_is_string=False)
+_REMARK_UNWRAP_IMAGES = Var.create_safe(
+    "remarkUnwrapImages", _var_is_local=False, _var_is_string=False
+)
 _REMARK_PLUGINS = Var.create_safe([_REMARK_MATH, _REMARK_GFM, _REMARK_UNWRAP_IMAGES])
 
 # Special rehype plugins.
-_REHYPE_KATEX = Var.create_safe("rehypeKatex", _var_is_local=False)
-_REHYPE_RAW = Var.create_safe("rehypeRaw", _var_is_local=False)
+_REHYPE_KATEX = Var.create_safe(
+    "rehypeKatex", _var_is_local=False, _var_is_string=False
+)
+_REHYPE_RAW = Var.create_safe("rehypeRaw", _var_is_local=False, _var_is_string=False)
 _REHYPE_PLUGINS = Var.create_safe([_REHYPE_KATEX, _REHYPE_RAW])
 
 # These tags do NOT get props passed to them
@@ -210,7 +214,9 @@ class Markdown(Component):
         # If the children are set as a prop, don't pass them as children.
         children_prop = props.pop("children", None)
         if children_prop is not None:
-            special_props.add(Var.create_safe(f"children={str(children_prop)}"))
+            special_props.add(
+                Var.create_safe(f"children={str(children_prop)}", _var_is_string=False)
+            )
             children = []
 
         # Get the component.
@@ -259,7 +265,7 @@ class Markdown(Component):
     return inline ? (
         {self.format_component("code")}
     ) : (
-        {self.format_component("codeblock", language=Var.create_safe("language", _var_is_local=False))}
+        {self.format_component("codeblock", language=Var.create_safe("language", _var_is_local=False, _var_is_string=False))}
     );
       }}}}""".replace("\n", " ")
 

+ 12 - 8
reflex/components/markdown/markdown.pyi

@@ -26,15 +26,19 @@ from reflex.utils import imports, types
 from reflex.utils.imports import ImportVar
 from reflex.vars import Var
 
-_CHILDREN = Var.create_safe("children", _var_is_local=False)
-_PROPS = Var.create_safe("...props", _var_is_local=False)
-_MOCK_ARG = Var.create_safe("")
-_REMARK_MATH = Var.create_safe("remarkMath", _var_is_local=False)
-_REMARK_GFM = Var.create_safe("remarkGfm", _var_is_local=False)
-_REMARK_UNWRAP_IMAGES = Var.create_safe("remarkUnwrapImages", _var_is_local=False)
+_CHILDREN = Var.create_safe("children", _var_is_local=False, _var_is_string=False)
+_PROPS = Var.create_safe("...props", _var_is_local=False, _var_is_string=False)
+_MOCK_ARG = Var.create_safe("", _var_is_string=False)
+_REMARK_MATH = Var.create_safe("remarkMath", _var_is_local=False, _var_is_string=False)
+_REMARK_GFM = Var.create_safe("remarkGfm", _var_is_local=False, _var_is_string=False)
+_REMARK_UNWRAP_IMAGES = Var.create_safe(
+    "remarkUnwrapImages", _var_is_local=False, _var_is_string=False
+)
 _REMARK_PLUGINS = Var.create_safe([_REMARK_MATH, _REMARK_GFM, _REMARK_UNWRAP_IMAGES])
-_REHYPE_KATEX = Var.create_safe("rehypeKatex", _var_is_local=False)
-_REHYPE_RAW = Var.create_safe("rehypeRaw", _var_is_local=False)
+_REHYPE_KATEX = Var.create_safe(
+    "rehypeKatex", _var_is_local=False, _var_is_string=False
+)
+_REHYPE_RAW = Var.create_safe("rehypeRaw", _var_is_local=False, _var_is_string=False)
 _REHYPE_PLUGINS = Var.create_safe([_REHYPE_KATEX, _REHYPE_RAW])
 NO_PROPS_TAGS = ("ul", "ol", "li")
 

+ 7 - 3
reflex/components/plotly/plotly.py

@@ -29,7 +29,7 @@ def _event_data_signature(e0: Var) -> List[Any]:
     Returns:
         The event key extracted from the event data (if defined).
     """
-    return [Var.create_safe(f"{e0}?.event")]
+    return [Var.create_safe(f"{e0}?.event", _var_is_string=False)]
 
 
 def _event_points_data_signature(e0: Var) -> List[Any]:
@@ -42,9 +42,10 @@ def _event_points_data_signature(e0: Var) -> List[Any]:
         The event data and the extracted points.
     """
     return [
-        Var.create_safe(f"{e0}?.event"),
+        Var.create_safe(f"{e0}?.event", _var_is_string=False),
         Var.create_safe(
             f"extractPoints({e0}?.points)",
+            _var_is_string=False,
         ),
     ]
 
@@ -277,11 +278,14 @@ const extractPoints = (points) => {
                 Var.create_safe(
                     f"{{...mergician({figure._var_name_unwrapped},"
                     f"{','.join(md._var_name_unwrapped for md in merge_dicts)})}}",
+                    _var_is_string=False,
                 ),
             )
         else:
             # Spread the figure dict over props, nothing to merge.
             tag.special_props.add(
-                Var.create_safe(f"{{...{figure._var_name_unwrapped}}}")
+                Var.create_safe(
+                    f"{{...{figure._var_name_unwrapped}}}", _var_is_string=False
+                )
             )
         return tag

+ 1 - 1
reflex/components/radix/primitives/accordion.py

@@ -105,7 +105,7 @@ class AccordionRoot(AccordionComponent):
     duration: Var[int] = Var.create_safe(DEFAULT_ANIMATION_DURATION)
 
     # The easing function to use for the animation.
-    easing: Var[str] = Var.create_safe(DEFAULT_ANIMATION_EASING)
+    easing: Var[str] = Var.create_safe(DEFAULT_ANIMATION_EASING, _var_is_string=True)
 
     # Whether to show divider lines between items.
     show_dividers: Var[bool]

+ 1 - 0
reflex/components/radix/themes/base.py

@@ -233,6 +233,7 @@ class Theme(RadixThemesComponent):
             css=Var.create(
                 "{{...theme.styles.global[':root'], ...theme.styles.global.body}}",
                 _var_is_local=False,
+                _var_is_string=False,
             ),
         )
         return tag

+ 1 - 1
reflex/components/radix/themes/color_mode.py

@@ -73,7 +73,7 @@ position_map = {
 
 # needed to inverse contains for find
 def _find(const, var):
-    return Var.create_safe(const).contains(var)
+    return Var.create_safe(const, _var_is_string=False).contains(var)
 
 
 def _set_var_default(props, position, prop, default1, default2=""):

+ 3 - 1
reflex/components/radix/themes/components/checkbox.py

@@ -130,7 +130,9 @@ class HighLevelCheckbox(RadixThemesComponent):
         }
 
     @classmethod
-    def create(cls, text: Var[str] = Var.create_safe(""), **props) -> Component:
+    def create(
+        cls, text: Var[str] = Var.create_safe("", _var_is_string=True), **props
+    ) -> Component:
         """Create a checkbox with a label.
 
         Args:

+ 6 - 4
reflex/components/radix/themes/components/radio_group.py

@@ -91,10 +91,10 @@ class HighLevelRadioGroup(RadixThemesComponent):
     direction: Var[LiteralFlexDirection]
 
     # The gap between the items of the radio group.
-    spacing: Var[LiteralSpacing] = Var.create_safe("2")
+    spacing: Var[LiteralSpacing] = Var.create_safe("2", _var_is_string=True)
 
     # The size of the radio group.
-    size: Var[Literal["1", "2", "3"]] = Var.create_safe("2")
+    size: Var[Literal["1", "2", "3"]] = Var.create_safe("2", _var_is_string=True)
 
     # The variant of the radio group
     variant: Var[Literal["classic", "surface", "soft"]]
@@ -151,11 +151,13 @@ class HighLevelRadioGroup(RadixThemesComponent):
             default_value = Var.create(default_value, _var_is_string=True)  # type: ignore
         else:
             default_value = (
-                Var.create(default_value).to_string()._replace(_var_is_local=False)  # type: ignore
+                Var.create(default_value, _var_is_string=False)
+                .to_string()  # type: ignore
+                ._replace(_var_is_local=False)
             )
 
         def radio_group_item(value: str | Var) -> Component:
-            item_value = Var.create(value)  # type: ignore
+            item_value = Var.create(value, _var_is_string=False)  # type: ignore
             item_value = rx.cond(
                 item_value._type() == str,  # type: ignore
                 item_value,

+ 1 - 1
reflex/components/radix/themes/components/separator.py

@@ -17,7 +17,7 @@ class Separator(RadixThemesComponent):
     tag = "Separator"
 
     # The size of the select: "1" | "2" | "3" | "4"
-    size: Var[LiteralSeperatorSize] = Var.create_safe("4")
+    size: Var[LiteralSeperatorSize] = Var.create_safe("4", _var_is_string=True)
 
     # The color of the select
     color_scheme: Var[LiteralAccentColor]

+ 1 - 1
reflex/components/radix/themes/layout/container.py

@@ -21,7 +21,7 @@ class Container(elements.Div, RadixThemesComponent):
     tag = "Container"
 
     # The size of the container: "1" - "4" (default "3")
-    size: Var[LiteralContainerSize] = Var.create_safe("3")
+    size: Var[LiteralContainerSize] = Var.create_safe("3", _var_is_string=True)
 
     @classmethod
     def create(

+ 1 - 1
reflex/components/radix/themes/layout/section.py

@@ -17,7 +17,7 @@ class Section(elements.Section, RadixThemesComponent):
     tag = "Section"
 
     # The size of the section: "1" - "3" (default "2")
-    size: Var[LiteralSectionSize] = Var.create_safe("2")
+    size: Var[LiteralSectionSize] = Var.create_safe("2", _var_is_string=True)
 
 
 section = Section.create

+ 1 - 1
reflex/components/recharts/charts.py

@@ -154,7 +154,7 @@ class BarChart(CategoricalChartBase):
     alias = "RechartsBarChart"
 
     # The gap between two bar categories, which can be a percent value or a fixed value. Percentage | Number
-    bar_category_gap: Var[Union[str, int]] = Var.create_safe("10%")  # type: ignore
+    bar_category_gap: Var[Union[str, int]] = Var.create_safe("10%", _var_is_string=True)  # type: ignore
 
     # The gap between two bars in the same category, which can be a percent value or a fixed value. Percentage | Number
     bar_gap: Var[Union[str, int]] = Var.create_safe(4)  # type: ignore

+ 7 - 3
reflex/components/sonner/toast.py

@@ -28,7 +28,7 @@ LiteralPosition = Literal[
 ]
 
 
-toast_ref = Var.create_safe("refs['__toast']")
+toast_ref = Var.create_safe("refs['__toast']", _var_is_string=False)
 
 
 class ToastAction(Base):
@@ -65,7 +65,8 @@ def _toast_callback_signature(toast: Var) -> list[Var]:
     """
     return [
         Var.create_safe(
-            f"(() => {{let {{action, cancel, onDismiss, onAutoClose, ...rest}} = {toast}; return rest}})()"
+            f"(() => {{let {{action, cancel, onDismiss, onAutoClose, ...rest}} = {toast}; return rest}})()",
+            _var_is_string=False,
         )
     ]
 
@@ -179,7 +180,9 @@ class Toaster(Component):
     visible_toasts: Var[int]
 
     # the position of the toast
-    position: Var[LiteralPosition] = Var.create_safe("bottom-right")
+    position: Var[LiteralPosition] = Var.create_safe(
+        "bottom-right", _var_is_string=True
+    )
 
     # whether to show the close button
     close_button: Var[bool] = Var.create_safe(False)
@@ -217,6 +220,7 @@ class Toaster(Component):
         hook = Var.create_safe(
             f"{toast_ref} = toast",
             _var_is_local=True,
+            _var_is_string=False,
             _var_data=VarData(
                 imports={
                     "/utils/state": [ImportVar(tag="refs")],

+ 1 - 1
reflex/components/sonner/toast.pyi

@@ -27,7 +27,7 @@ LiteralPosition = Literal[
     "bottom-center",
     "bottom-right",
 ]
-toast_ref = Var.create_safe("refs['__toast']")
+toast_ref = Var.create_safe("refs['__toast']", _var_is_string=False)
 
 class ToastAction(Base):
     label: str

+ 2 - 1
reflex/components/tags/tag.py

@@ -41,7 +41,8 @@ class Tag(Base):
         # Convert any props to vars.
         if "props" in kwargs:
             kwargs["props"] = {
-                name: Var.create(value) for name, value in kwargs["props"].items()
+                name: Var.create(value, _var_is_string=False)
+                for name, value in kwargs["props"].items()
             }
         super().__init__(*args, **kwargs)
 

+ 12 - 9
reflex/event.py

@@ -186,7 +186,7 @@ class EventHandler(EventActionsMixin):
 
         # Get the function args.
         fn_args = inspect.getfullargspec(self.fn).args[1:]
-        fn_args = (Var.create_safe(arg) for arg in fn_args)
+        fn_args = (Var.create_safe(arg, _var_is_string=False) for arg in fn_args)
 
         # Construct the payload.
         values = []
@@ -264,7 +264,7 @@ class EventSpec(EventActionsMixin):
 
         # Get the remaining unfilled function args.
         fn_args = inspect.getfullargspec(self.handler.fn).args[1 + len(self.args) :]
-        fn_args = (Var.create_safe(arg) for arg in fn_args)
+        fn_args = (Var.create_safe(arg, _var_is_string=False) for arg in fn_args)
 
         # Construct the payload.
         values = []
@@ -389,13 +389,13 @@ class FileUpload(Base):
 
         spec_args = [
             (
-                Var.create_safe("files"),
-                Var.create_safe(f"filesById.{upload_id}")._replace(
-                    _var_data=upload_files_context_var_data
-                ),
+                Var.create_safe("files", _var_is_string=False),
+                Var.create_safe(
+                    f"filesById.{upload_id}", _var_is_string=False
+                )._replace(_var_data=upload_files_context_var_data),
             ),
             (
-                Var.create_safe("upload_id"),
+                Var.create_safe("upload_id", _var_is_string=False),
                 Var.create_safe(upload_id, _var_is_string=True),
             ),
         ]
@@ -424,7 +424,7 @@ class FileUpload(Base):
             formatted_chain = str(format.format_prop(on_upload_progress_chain))
             spec_args.append(
                 (
-                    Var.create_safe("on_upload_progress"),
+                    Var.create_safe("on_upload_progress", _var_is_string=False),
                     BaseVar(
                         _var_name=formatted_chain.strip("{}"),
                         _var_type=EventChain,
@@ -464,7 +464,10 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
     return EventSpec(
         handler=EventHandler(fn=fn),
         args=tuple(
-            (Var.create_safe(k), Var.create_safe(v, _var_is_string=isinstance(v, str)))
+            (
+                Var.create_safe(k, _var_is_string=False),
+                Var.create_safe(v, _var_is_string=isinstance(v, str)),
+            )
             for k, v in kwargs.items()
         ),
     )

+ 8 - 2
reflex/experimental/hooks.py

@@ -20,8 +20,10 @@ def const(name, value) -> Var:
         The constant Var.
     """
     if isinstance(name, list):
-        return Var.create_safe(f"const [{', '.join(name)}] = {value}")
-    return Var.create_safe(f"const {name} = {value}")
+        return Var.create_safe(
+            f"const [{', '.join(name)}] = {value}", _var_is_string=False
+        )
+    return Var.create_safe(f"const {name} = {value}", _var_is_string=False)
 
 
 def useCallback(func, deps) -> Var:
@@ -36,6 +38,7 @@ def useCallback(func, deps) -> Var:
     """
     return Var.create_safe(
         f"useCallback({func}, {deps})" if deps else f"useCallback({func})",
+        _var_is_string=False,
         _var_data=VarData(imports=_compose_react_imports(["useCallback"])),
     )
 
@@ -51,6 +54,7 @@ def useContext(context) -> Var:
     """
     return Var.create_safe(
         f"useContext({context})",
+        _var_is_string=False,
         _var_data=VarData(imports=_compose_react_imports(["useContext"])),
     )
 
@@ -66,6 +70,7 @@ def useRef(default) -> Var:
     """
     return Var.create_safe(
         f"useRef({default})",
+        _var_is_string=False,
         _var_data=VarData(imports=_compose_react_imports(["useRef"])),
     )
 
@@ -84,6 +89,7 @@ def useState(var_name, default=None) -> Var:
         [var_name, f"set{var_name.capitalize()}"],
         Var.create_safe(
             f"useState({default})",
+            _var_is_string=False,
             _var_data=VarData(imports=_compose_react_imports(["useState"])),
         ),
     )

+ 9 - 2
reflex/experimental/layout.py

@@ -52,7 +52,11 @@ class Sidebar(Box, MemoizationLeaf):
         """
         sidebar: Component = self.children[-2]  # type: ignore
         spacer: Component = self.children[-1]  # type: ignore
-        open = self.State.open if self.State else Var.create("open")  # type: ignore
+        open = (
+            self.State.open  # type: ignore
+            if self.State
+            else Var.create_safe("open", _var_is_string=False)
+        )
         sidebar.style["display"] = spacer.style["display"] = cond(open, "block", "none")
 
         return Style(
@@ -167,7 +171,10 @@ class SidebarTrigger(Fragment):
         if sidebar.State:
             open, toggle = sidebar.State.open, sidebar.State.toggle  # type: ignore
         else:
-            open, toggle = Var.create("open"), call_script(Var.create("setOpen(!open)"))  # type: ignore
+            open, toggle = (
+                Var.create_safe("open", _var_is_string=False),
+                call_script(Var.create_safe("setOpen(!open)", _var_is_string=False)),
+            )
 
         trigger_props["left"] = cond(open, f"calc({sidebar_width} - 32px)", "0")
 

+ 2 - 2
reflex/style.py

@@ -79,7 +79,7 @@ def convert_item(style_item: str | Var) -> tuple[str, VarData | None]:
         return str(style_item), style_item._var_data
 
     # Otherwise, convert to Var to collapse VarData encoded in f-string.
-    new_var = Var.create(style_item)
+    new_var = Var.create(style_item, _var_is_string=False)
     if new_var is not None and new_var._var_data:
         # The wrapped backtick is used to identify the Var for interpolation.
         return f"`{str(new_var)}`", new_var._var_data
@@ -204,7 +204,7 @@ class Style(dict):
             value: The value to set.
         """
         # Create a Var to collapse VarData encoded in f-string.
-        _var = Var.create(value)
+        _var = Var.create(value, _var_is_string=False)
         if _var is not None:
             # Carry the imports/hooks when setting a Var as a value.
             self._var_data = VarData.merge(self._var_data, _var._var_data)

+ 4 - 1
reflex/utils/format.py

@@ -916,4 +916,7 @@ def format_data_editor_cell(cell: Any):
     Returns:
         The formatted cell.
     """
-    return {"kind": Var.create(value="GridCellKind.Text"), "data": cell}
+    return {
+        "kind": Var.create(value="GridCellKind.Text", _var_is_string=False),
+        "data": cell,
+    }

+ 18 - 10
reflex/vars.py

@@ -535,7 +535,7 @@ class Var:
         if other is None:
             return self._replace()
         if not isinstance(other, Var):
-            other = Var.create(other)
+            other = Var.create(other, _var_is_string=False)
         return self._replace(
             _var_name=f"{{...{self._var_name}, ...{other._var_name}}}"  # type: ignore
         )
@@ -831,9 +831,9 @@ class Var:
         from reflex.utils import format
 
         if isinstance(other, str):
-            other = Var.create(json.dumps(other))
+            other = Var.create(json.dumps(other), _var_is_string=False)
         else:
-            other = Var.create(other)
+            other = Var.create(other, _var_is_string=False)
 
         type_ = type_ or self._var_type
 
@@ -1416,7 +1416,7 @@ class Var:
         if isinstance(other, str):
             other = Var.create(json.dumps(other), _var_is_string=True)
         elif not isinstance(other, Var):
-            other = Var.create(other)
+            other = Var.create(other, _var_is_string=False)
         if types._issubclass(self._var_type, Dict):
             return self._replace(
                 _var_name=f"{self._var_name}.{method}({other._var_full_name})",
@@ -1520,7 +1520,11 @@ class Var:
         if not types._issubclass(self._var_type, str):
             raise VarTypeError(f"Cannot strip non-string var {self._var_full_name}.")
 
-        other = Var.create_safe(json.dumps(other)) if isinstance(other, str) else other
+        other = (
+            Var.create_safe(json.dumps(other), _var_is_string=False)
+            if isinstance(other, str)
+            else other
+        )
 
         return self._replace(
             _var_name=f"{self._var_name}.replace(/^${other._var_full_name}|${other._var_full_name}$/g, '')",
@@ -1543,7 +1547,11 @@ class Var:
         if not types._issubclass(self._var_type, str):
             raise VarTypeError(f"Cannot split non-string var {self._var_full_name}.")
 
-        other = Var.create_safe(json.dumps(other)) if isinstance(other, str) else other
+        other = (
+            Var.create_safe(json.dumps(other), _var_is_string=False)
+            if isinstance(other, str)
+            else other
+        )
 
         return self._replace(
             _var_name=f"{self._var_name}.split({other._var_full_name})",
@@ -1568,11 +1576,11 @@ class Var:
             raise VarTypeError(f"Cannot join non-list var {self._var_full_name}.")
 
         if other is None:
-            other = Var.create_safe('""')
+            other = Var.create_safe('""', _var_is_string=False)
         if isinstance(other, str):
-            other = Var.create_safe(json.dumps(other))
+            other = Var.create_safe(json.dumps(other), _var_is_string=False)
         else:
-            other = Var.create_safe(other)
+            other = Var.create_safe(other, _var_is_string=False)
 
         return self._replace(
             _var_name=f"{self._var_name}.join({other._var_full_name})",
@@ -1641,7 +1649,7 @@ class Var:
         if not isinstance(v2, Var):
             v2 = Var.create(v2)
         if v2 is None:
-            v2 = Var.create_safe("undefined")
+            v2 = Var.create_safe("undefined", _var_is_string=False)
         elif v2._var_type != int:
             raise VarTypeError(f"Cannot get range on non-int var {v2._var_full_name}.")