浏览代码

Handle Var passed to `rx.toast` (#4405)

* Handle Var passed to `rx.toast`

If the user provides a `Var` for `message` then apply it as `props["title"]` to
avoid a var operations error.

* remove unnecessary parentheses

* remove weird hacks

* get it right pyright

---------

Co-authored-by: Khaleel Al-Adhami <khaleel.aladhami@gmail.com>
Masen Furer 6 月之前
父节点
当前提交
bbfbc82c9d
共有 3 个文件被更改,包括 33 次插入18 次删除
  1. 23 12
      reflex/components/sonner/toast.py
  2. 6 6
      reflex/components/sonner/toast.pyi
  3. 4 0
      reflex/utils/types.py

+ 23 - 12
reflex/components/sonner/toast.py

@@ -15,6 +15,8 @@ from reflex.utils.imports import ImportVar
 from reflex.utils.serializers import serializer
 from reflex.vars import VarData
 from reflex.vars.base import LiteralVar, Var
+from reflex.vars.function import FunctionVar
+from reflex.vars.object import ObjectVar
 
 LiteralPosition = Literal[
     "top-left",
@@ -232,7 +234,9 @@ class Toaster(Component):
         return [hook]
 
     @staticmethod
-    def send_toast(message: str = "", level: str | None = None, **props) -> EventSpec:
+    def send_toast(
+        message: str | Var = "", level: str | None = None, **props
+    ) -> EventSpec:
         """Send a toast message.
 
         Args:
@@ -250,20 +254,27 @@ class Toaster(Component):
             raise ValueError(
                 "Toaster component must be created before sending a toast. (use `rx.toast.provider()`)"
             )
-        toast_command = f"{toast_ref}.{level}" if level is not None else toast_ref
-        if message == "" and ("title" not in props or "description" not in props):
+
+        toast_command = (
+            ObjectVar.__getattr__(toast_ref.to(dict), level) if level else toast_ref
+        ).to(FunctionVar)
+
+        if isinstance(message, Var):
+            props.setdefault("title", message)
+            message = ""
+        elif message == "" and "title" not in props and "description" not in props:
             raise ValueError("Toast message or title or description must be provided.")
+
         if props:
-            args = LiteralVar.create(ToastProps(component_name="rx.toast", **props))  # type: ignore
-            toast = f"{toast_command}(`{message}`, {str(args)})"
+            args = LiteralVar.create(ToastProps(component_name="rx.toast", **props))  # pyright: ignore [reportCallIssue, reportGeneralTypeIssues]
+            toast = toast_command.call(message, args)
         else:
-            toast = f"{toast_command}(`{message}`)"
+            toast = toast_command.call(message)
 
-        toast_action = Var(_js_expr=toast)
-        return run_script(toast_action)
+        return run_script(toast)
 
     @staticmethod
-    def toast_info(message: str = "", **kwargs):
+    def toast_info(message: str | Var = "", **kwargs):
         """Display an info toast message.
 
         Args:
@@ -276,7 +287,7 @@ class Toaster(Component):
         return Toaster.send_toast(message, level="info", **kwargs)
 
     @staticmethod
-    def toast_warning(message: str = "", **kwargs):
+    def toast_warning(message: str | Var = "", **kwargs):
         """Display a warning toast message.
 
         Args:
@@ -289,7 +300,7 @@ class Toaster(Component):
         return Toaster.send_toast(message, level="warning", **kwargs)
 
     @staticmethod
-    def toast_error(message: str = "", **kwargs):
+    def toast_error(message: str | Var = "", **kwargs):
         """Display an error toast message.
 
         Args:
@@ -302,7 +313,7 @@ class Toaster(Component):
         return Toaster.send_toast(message, level="error", **kwargs)
 
     @staticmethod
-    def toast_success(message: str = "", **kwargs):
+    def toast_success(message: str | Var = "", **kwargs):
         """Display a success toast message.
 
         Args:

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

@@ -59,16 +59,16 @@ class Toaster(Component):
     def add_hooks(self) -> list[Var | str]: ...
     @staticmethod
     def send_toast(
-        message: str = "", level: str | None = None, **props
+        message: str | Var = "", level: str | None = None, **props
     ) -> EventSpec: ...
     @staticmethod
-    def toast_info(message: str = "", **kwargs): ...
+    def toast_info(message: str | Var = "", **kwargs): ...
     @staticmethod
-    def toast_warning(message: str = "", **kwargs): ...
+    def toast_warning(message: str | Var = "", **kwargs): ...
     @staticmethod
-    def toast_error(message: str = "", **kwargs): ...
+    def toast_error(message: str | Var = "", **kwargs): ...
     @staticmethod
-    def toast_success(message: str = "", **kwargs): ...
+    def toast_success(message: str | Var = "", **kwargs): ...
     @staticmethod
     def toast_dismiss(id: Var | str | None = None): ...
     @overload
@@ -176,7 +176,7 @@ class ToastNamespace(ComponentNamespace):
 
     @staticmethod
     def __call__(
-        message: str = "", level: Optional[str] = None, **props
+        message: Union[str, Var] = "", level: Optional[str] = None, **props
     ) -> "Optional[EventSpec]":
         """Send a toast message.
 

+ 4 - 0
reflex/utils/types.py

@@ -576,6 +576,10 @@ def _isinstance(obj: Any, cls: GenericType, nested: bool = False) -> bool:
                 return does_obj_satisfy_typed_dict(obj, cls)
             return isinstance(obj, dict)
 
+        # cls is a float
+        if cls is float:
+            return isinstance(obj, (float, int))
+
         # cls is a simple class
         return isinstance(obj, cls)