promote toast to main namespace (#3422)

This commit is contained in:
Thomas Brandého 2024-06-06 19:38:35 +02:00 committed by GitHub
parent 4b955d3831
commit e1244b4ea6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 73 additions and 23 deletions

View File

@ -248,7 +248,12 @@ _MAPPING: dict = {
"admin": ["AdminDash"], "admin": ["AdminDash"],
"app": ["App", "UploadFile"], "app": ["App", "UploadFile"],
"base": ["Base"], "base": ["Base"],
"components.component": ["Component", "NoSSRComponent", "memo"], "components.component": [
"Component",
"NoSSRComponent",
"memo",
"ComponentNamespace",
],
"components.el.elements.media": ["image"], "components.el.elements.media": ["image"],
"components.lucide": ["icon"], "components.lucide": ["icon"],
**COMPONENTS_BASE_MAPPING, **COMPONENTS_BASE_MAPPING,
@ -270,6 +275,7 @@ _MAPPING: dict = {
"data_editor", "data_editor",
"data_editor_theme", "data_editor_theme",
], ],
"components.sonner.toast": ["toast"],
"components.datadisplay.logo": ["logo"], "components.datadisplay.logo": ["logo"],
"components.gridjs": ["data_table"], "components.gridjs": ["data_table"],
"components.moment": ["MomentDelta", "moment"], "components.moment": ["MomentDelta", "moment"],

View File

@ -24,6 +24,7 @@ from .base import Base as Base
from .components.component import Component as Component from .components.component import Component as Component
from .components.component import NoSSRComponent as NoSSRComponent from .components.component import NoSSRComponent as NoSSRComponent
from .components.component import memo as memo from .components.component import memo as memo
from .components.component import ComponentNamespace as ComponentNamespace
from .components.el.elements.media import image as image from .components.el.elements.media import image as image
from .components.lucide import icon as icon from .components.lucide import icon as icon
from .components.base.fragment import fragment as fragment from .components.base.fragment import fragment as fragment
@ -143,6 +144,7 @@ from .components.core.upload import upload as upload
from .components.datadisplay.code import code_block as code_block from .components.datadisplay.code import code_block as code_block
from .components.datadisplay.dataeditor import data_editor as data_editor from .components.datadisplay.dataeditor import data_editor as data_editor
from .components.datadisplay.dataeditor import data_editor_theme as data_editor_theme from .components.datadisplay.dataeditor import data_editor_theme as data_editor_theme
from .components.sonner.toast import toast as toast
from .components.datadisplay.logo import logo as logo from .components.datadisplay.logo import logo as logo
from .components.gridjs import data_table as data_table from .components.gridjs import data_table as data_table
from .components.moment import MomentDelta as MomentDelta from .components.moment import MomentDelta as MomentDelta

View File

@ -106,7 +106,7 @@ class ToastProps(PropsBase):
cancel: Optional[ToastAction] cancel: Optional[ToastAction]
# Custom id for the toast. # Custom id for the toast.
id: Optional[str] id: Optional[Union[str, Var]]
# Removes the default styling, which allows for easier customization. # Removes the default styling, which allows for easier customization.
unstyled: Optional[bool] unstyled: Optional[bool]
@ -127,7 +127,7 @@ class ToastProps(PropsBase):
# Function that gets called when the toast disappears automatically after it's timeout (duration` prop). # Function that gets called when the toast disappears automatically after it's timeout (duration` prop).
on_auto_close: Optional[Any] on_auto_close: Optional[Any]
def dict(self, *args, **kwargs) -> dict: def dict(self, *args, **kwargs) -> dict[str, Any]:
"""Convert the object to a dictionary. """Convert the object to a dictionary.
Args: Args:
@ -137,7 +137,7 @@ class ToastProps(PropsBase):
Returns: Returns:
The object as a dictionary with ToastAction fields intact. The object as a dictionary with ToastAction fields intact.
""" """
kwargs.setdefault("exclude_none", True) kwargs.setdefault("exclude_none", True) # type: ignore
d = super().dict(*args, **kwargs) d = super().dict(*args, **kwargs)
# Keep these fields as ToastAction so they can be serialized specially # Keep these fields as ToastAction so they can be serialized specially
if "action" in d: if "action" in d:
@ -208,7 +208,12 @@ class Toaster(Component):
# Pauses toast timers when the page is hidden, e.g., when the tab is backgrounded, the browser is minimized, or the OS is locked. # Pauses toast timers when the page is hidden, e.g., when the tab is backgrounded, the browser is minimized, or the OS is locked.
pause_when_page_is_hidden: Var[bool] pause_when_page_is_hidden: Var[bool]
def _get_hooks(self) -> Var[str]: def add_hooks(self) -> list[Var | str]:
"""Add hooks for the toaster component.
Returns:
The hooks for the toaster component.
"""
hook = Var.create_safe( hook = Var.create_safe(
f"{toast_ref} = toast", f"{toast_ref} = toast",
_var_is_local=True, _var_is_local=True,
@ -219,7 +224,7 @@ class Toaster(Component):
} }
), ),
) )
return hook return [hook]
@staticmethod @staticmethod
def send_toast(message: str, level: str | None = None, **props) -> EventSpec: def send_toast(message: str, level: str | None = None, **props) -> EventSpec:
@ -235,13 +240,13 @@ class Toaster(Component):
""" """
toast_command = f"{toast_ref}.{level}" if level is not None else toast_ref toast_command = f"{toast_ref}.{level}" if level is not None else toast_ref
if props: if props:
args = serialize(ToastProps(**props)) args = serialize(ToastProps(**props)) # type: ignore
toast = f"{toast_command}(`{message}`, {args})" toast = f"{toast_command}(`{message}`, {args})"
else: else:
toast = f"{toast_command}(`{message}`)" toast = f"{toast_command}(`{message}`)"
toast_action = Var.create(toast, _var_is_string=False, _var_is_local=True) toast_action = Var.create_safe(toast, _var_is_string=False, _var_is_local=True)
return call_script(toast_action) # type: ignore return call_script(toast_action)
@staticmethod @staticmethod
def toast_info(message: str, **kwargs): def toast_info(message: str, **kwargs):
@ -295,7 +300,8 @@ class Toaster(Component):
""" """
return Toaster.send_toast(message, level="success", **kwargs) return Toaster.send_toast(message, level="success", **kwargs)
def toast_dismiss(self, id: str | None): @staticmethod
def toast_dismiss(id: Var | str | None = None):
"""Dismiss a toast. """Dismiss a toast.
Args: Args:
@ -304,12 +310,22 @@ class Toaster(Component):
Returns: Returns:
The toast dismiss event. The toast dismiss event.
""" """
if id is None: dismiss_var_data = None
dismiss = f"{toast_ref}.dismiss()"
if isinstance(id, Var):
dismiss = f"{toast_ref}.dismiss({id._var_name_unwrapped})"
dismiss_var_data = id._var_data
elif isinstance(id, str):
dismiss = f"{toast_ref}.dismiss('{id}')"
else: else:
dismiss = f"{toast_ref}.dismiss({id})" dismiss = f"{toast_ref}.dismiss()"
dismiss_action = Var.create(dismiss, _var_is_string=False, _var_is_local=True) dismiss_action = Var.create_safe(
return call_script(dismiss_action) # type: ignore dismiss,
_var_is_string=False,
_var_is_local=True,
_var_data=dismiss_var_data,
)
return call_script(dismiss_action)
# TODO: figure out why loading toast stay open forever # TODO: figure out why loading toast stay open forever

View File

@ -46,7 +46,7 @@ class ToastProps(PropsBase):
dismissible: Optional[bool] dismissible: Optional[bool]
action: Optional[ToastAction] action: Optional[ToastAction]
cancel: Optional[ToastAction] cancel: Optional[ToastAction]
id: Optional[str] id: Optional[Union[str, Var]]
unstyled: Optional[bool] unstyled: Optional[bool]
style: Optional[Style] style: Optional[Style]
action_button_styles: Optional[Style] action_button_styles: Optional[Style]
@ -54,9 +54,10 @@ class ToastProps(PropsBase):
on_dismiss: Optional[Any] on_dismiss: Optional[Any]
on_auto_close: Optional[Any] on_auto_close: Optional[Any]
def dict(self, *args, **kwargs) -> dict: ... def dict(self, *args, **kwargs) -> dict[str, Any]: ...
class Toaster(Component): class Toaster(Component):
def add_hooks(self) -> list[Var | str]: ...
@staticmethod @staticmethod
def send_toast(message: str, level: str | None = None, **props) -> EventSpec: ... def send_toast(message: str, level: str | None = None, **props) -> EventSpec: ...
@staticmethod @staticmethod
@ -67,7 +68,8 @@ class Toaster(Component):
def toast_error(message: str, **kwargs): ... def toast_error(message: str, **kwargs): ...
@staticmethod @staticmethod
def toast_success(message: str, **kwargs): ... def toast_success(message: str, **kwargs): ...
def toast_dismiss(self, id: str | None): ... @staticmethod
def toast_dismiss(id: Var | str | None = None): ...
@overload @overload
@classmethod @classmethod
def create( # type: ignore def create( # type: ignore
@ -202,7 +204,9 @@ class ToastNamespace(ComponentNamespace):
dismiss = staticmethod(Toaster.toast_dismiss) dismiss = staticmethod(Toaster.toast_dismiss)
@staticmethod @staticmethod
def __call__(message: str, level: Optional[str], **props) -> "Optional[EventSpec]": def __call__(
message: str, level: Optional[str] = None, **props
) -> "Optional[EventSpec]":
"""Send a toast message. """Send a toast message.
Args: Args:

View File

@ -714,7 +714,7 @@ def _callback_arg_spec(eval_result):
def call_script( def call_script(
javascript_code: str, javascript_code: str | Var[str],
callback: EventSpec callback: EventSpec
| EventHandler | EventHandler
| Callable | Callable

View File

@ -17,7 +17,28 @@ warn(
"`rx._x` contains experimental features and might be removed at any time in the future .", "`rx._x` contains experimental features and might be removed at any time in the future .",
) )
_x = SimpleNamespace( _EMITTED_PROMOTION_WARNINGS = set()
class ExperimentalNamespace(SimpleNamespace):
"""Namespace for experimental features."""
@property
def toast(self):
"""Temporary property returning the toast namespace.
Remove this property when toast is fully promoted.
Returns:
The toast namespace.
"""
if "toast" not in _EMITTED_PROMOTION_WARNINGS:
_EMITTED_PROMOTION_WARNINGS.add("toast")
warn(f"`rx._x.toast` was promoted to `rx.toast`.")
return toast
_x = ExperimentalNamespace(
asset=asset, asset=asset,
client_state=ClientStateVar.create, client_state=ClientStateVar.create,
hooks=hooks, hooks=hooks,
@ -25,5 +46,4 @@ _x = SimpleNamespace(
progress=progress, progress=progress,
PropsBase=PropsBase, PropsBase=PropsBase,
run_in_thread=run_in_thread, run_in_thread=run_in_thread,
toast=toast,
) )

View File

@ -488,7 +488,9 @@ def _generate_staticmethod_call_functiondef(
kwonlyargs=[], kwonlyargs=[],
kw_defaults=[], kw_defaults=[],
kwarg=ast.arg(arg="props"), kwarg=ast.arg(arg="props"),
defaults=[], defaults=[ast.Constant(value=default) for default in fullspec.defaults]
if fullspec.defaults
else [],
) )
definition = ast.FunctionDef( definition = ast.FunctionDef(
name="__call__", name="__call__",