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"],
"app": ["App", "UploadFile"],
"base": ["Base"],
"components.component": ["Component", "NoSSRComponent", "memo"],
"components.component": [
"Component",
"NoSSRComponent",
"memo",
"ComponentNamespace",
],
"components.el.elements.media": ["image"],
"components.lucide": ["icon"],
**COMPONENTS_BASE_MAPPING,
@ -270,6 +275,7 @@ _MAPPING: dict = {
"data_editor",
"data_editor_theme",
],
"components.sonner.toast": ["toast"],
"components.datadisplay.logo": ["logo"],
"components.gridjs": ["data_table"],
"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 NoSSRComponent as NoSSRComponent
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.lucide import icon as icon
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.dataeditor import data_editor as data_editor
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.gridjs import data_table as data_table
from .components.moment import MomentDelta as MomentDelta

View File

@ -106,7 +106,7 @@ class ToastProps(PropsBase):
cancel: Optional[ToastAction]
# Custom id for the toast.
id: Optional[str]
id: Optional[Union[str, Var]]
# Removes the default styling, which allows for easier customization.
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).
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.
Args:
@ -137,7 +137,7 @@ class ToastProps(PropsBase):
Returns:
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)
# Keep these fields as ToastAction so they can be serialized specially
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.
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(
f"{toast_ref} = toast",
_var_is_local=True,
@ -219,7 +224,7 @@ class Toaster(Component):
}
),
)
return hook
return [hook]
@staticmethod
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
if props:
args = serialize(ToastProps(**props))
args = serialize(ToastProps(**props)) # type: ignore
toast = f"{toast_command}(`{message}`, {args})"
else:
toast = f"{toast_command}(`{message}`)"
toast_action = Var.create(toast, _var_is_string=False, _var_is_local=True)
return call_script(toast_action) # type: ignore
toast_action = Var.create_safe(toast, _var_is_string=False, _var_is_local=True)
return call_script(toast_action)
@staticmethod
def toast_info(message: str, **kwargs):
@ -295,7 +300,8 @@ class Toaster(Component):
"""
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.
Args:
@ -304,12 +310,22 @@ class Toaster(Component):
Returns:
The toast dismiss event.
"""
if id is None:
dismiss = f"{toast_ref}.dismiss()"
dismiss_var_data = None
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:
dismiss = f"{toast_ref}.dismiss({id})"
dismiss_action = Var.create(dismiss, _var_is_string=False, _var_is_local=True)
return call_script(dismiss_action) # type: ignore
dismiss = f"{toast_ref}.dismiss()"
dismiss_action = Var.create_safe(
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

View File

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

View File

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

View File

@ -17,7 +17,28 @@ warn(
"`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,
client_state=ClientStateVar.create,
hooks=hooks,
@ -25,5 +46,4 @@ _x = SimpleNamespace(
progress=progress,
PropsBase=PropsBase,
run_in_thread=run_in_thread,
toast=toast,
)

View File

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