Browse Source

add noop event (#4288)

* add noop event

* fix pyi

* get it right pyright

* why

* remove silly events

* fix tests

* remove semi colon

* errors in merging
Khaleel Al-Adhami 6 tháng trước cách đây
mục cha
commit
ca81e623db
44 tập tin đã thay đổi với 453 bổ sung396 xóa
  1. 19 16
      reflex/.templates/web/utils/state.js
  2. 3 0
      reflex/__init__.py
  3. 3 0
      reflex/__init__.pyi
  4. 4 4
      reflex/components/base/script.py
  5. 18 18
      reflex/components/component.py
  6. 2 2
      reflex/components/core/clipboard.py
  7. 3 1
      reflex/components/core/clipboard.pyi
  8. 2 2
      reflex/components/core/debounce.py
  9. 4 4
      reflex/components/core/upload.py
  10. 19 17
      reflex/components/datadisplay/dataeditor.py
  11. 3 3
      reflex/components/datadisplay/shiki_code_block.py
  12. 2 2
      reflex/components/moment/moment.py
  13. 3 3
      reflex/components/next/image.py
  14. 8 8
      reflex/components/radix/primitives/drawer.py
  15. 2 2
      reflex/components/radix/primitives/form.py
  16. 5 5
      reflex/components/radix/themes/components/alert_dialog.py
  17. 3 3
      reflex/components/radix/themes/components/checkbox.py
  18. 13 13
      reflex/components/radix/themes/components/context_menu.py
  19. 7 7
      reflex/components/radix/themes/components/dialog.py
  20. 13 13
      reflex/components/radix/themes/components/dropdown_menu.py
  21. 2 2
      reflex/components/radix/themes/components/hover_card.py
  22. 8 8
      reflex/components/radix/themes/components/popover.py
  23. 2 2
      reflex/components/radix/themes/components/radio_cards.py
  24. 2 2
      reflex/components/radix/themes/components/radio_group.py
  25. 6 6
      reflex/components/radix/themes/components/select.py
  26. 4 4
      reflex/components/radix/themes/components/slider.py
  27. 4 4
      reflex/components/radix/themes/components/slider.pyi
  28. 2 2
      reflex/components/radix/themes/components/switch.py
  29. 2 2
      reflex/components/radix/themes/components/tabs.py
  30. 4 4
      reflex/components/radix/themes/components/tooltip.py
  31. 17 17
      reflex/components/react_player/react_player.py
  32. 45 45
      reflex/components/recharts/cartesian.py
  33. 22 22
      reflex/components/recharts/charts.py
  34. 10 10
      reflex/components/recharts/general.py
  35. 33 33
      reflex/components/recharts/polar.py
  36. 3 6
      reflex/components/sonner/toast.py
  37. 8 8
      reflex/components/suneditor/editor.py
  38. 97 60
      reflex/event.py
  39. 3 3
      reflex/experimental/client_state.py
  40. 2 2
      reflex/experimental/layout.py
  41. 3 9
      reflex/utils/format.py
  42. 8 8
      tests/units/components/test_component.py
  43. 3 3
      tests/units/components/test_component_future_annotations.py
  44. 27 11
      tests/units/test_event.py

+ 19 - 16
reflex/.templates/web/utils/state.js

@@ -178,11 +178,6 @@ export const applyEvent = async (event, socket) => {
     return false;
   }
 
-  if (event.name == "_console") {
-    console.log(event.payload.message);
-    return false;
-  }
-
   if (event.name == "_remove_cookie") {
     cookies.remove(event.payload.key, { ...event.payload.options });
     queueEventIfSocketExists(initialEvents(), socket);
@@ -213,12 +208,6 @@ export const applyEvent = async (event, socket) => {
     return false;
   }
 
-  if (event.name == "_set_clipboard") {
-    const content = event.payload.content;
-    navigator.clipboard.writeText(content);
-    return false;
-  }
-
   if (event.name == "_download") {
     const a = document.createElement("a");
     a.hidden = true;
@@ -233,11 +222,6 @@ export const applyEvent = async (event, socket) => {
     return false;
   }
 
-  if (event.name == "_alert") {
-    alert(event.payload.message);
-    return false;
-  }
-
   if (event.name == "_set_focus") {
     const ref =
       event.payload.ref in refs ? refs[event.payload.ref] : event.payload.ref;
@@ -254,6 +238,25 @@ export const applyEvent = async (event, socket) => {
     return false;
   }
 
+  if (event.name == "_call_function") {
+    try {
+      const eval_result = event.payload.function();
+      if (event.payload.callback) {
+        if (!!eval_result && typeof eval_result.then === "function") {
+          event.payload.callback(await eval_result);
+        } else {
+          event.payload.callback(eval_result);
+        }
+      }
+    } catch (e) {
+      console.log("_call_function", e);
+      if (window && window?.onerror) {
+        window.onerror(e.message, null, null, null, e);
+      }
+    }
+    return false;
+  }
+
   if (event.name == "_call_script") {
     try {
       const eval_result = eval(event.payload.javascript_code);

+ 3 - 0
reflex/__init__.py

@@ -303,10 +303,13 @@ _MAPPING: dict = {
         "EventHandler",
         "background",
         "call_script",
+        "call_function",
+        "run_script",
         "clear_local_storage",
         "clear_session_storage",
         "console_log",
         "download",
+        "noop",
         "prevent_default",
         "redirect",
         "remove_cookie",

+ 3 - 0
reflex/__init__.pyi

@@ -155,17 +155,20 @@ from .constants import Env as Env
 from .event import EventChain as EventChain
 from .event import EventHandler as EventHandler
 from .event import background as background
+from .event import call_function as call_function
 from .event import call_script as call_script
 from .event import clear_local_storage as clear_local_storage
 from .event import clear_session_storage as clear_session_storage
 from .event import console_log as console_log
 from .event import download as download
 from .event import event as event
+from .event import noop as noop
 from .event import prevent_default as prevent_default
 from .event import redirect as redirect
 from .event import remove_cookie as remove_cookie
 from .event import remove_local_storage as remove_local_storage
 from .event import remove_session_storage as remove_session_storage
+from .event import run_script as run_script
 from .event import scroll_to as scroll_to
 from .event import set_clipboard as set_clipboard
 from .event import set_focus as set_focus

+ 4 - 4
reflex/components/base/script.py

@@ -8,7 +8,7 @@ from __future__ import annotations
 from typing import Literal
 
 from reflex.components.component import Component
-from reflex.event import EventHandler, empty_event
+from reflex.event import EventHandler, no_args_event_spec
 from reflex.vars.base import LiteralVar, Var
 
 
@@ -35,13 +35,13 @@ class Script(Component):
     )
 
     # Triggered when the script is loading
-    on_load: EventHandler[empty_event]
+    on_load: EventHandler[no_args_event_spec]
 
     # Triggered when the script has loaded
-    on_ready: EventHandler[empty_event]
+    on_ready: EventHandler[no_args_event_spec]
 
     # Triggered when the script has errored
-    on_error: EventHandler[empty_event]
+    on_error: EventHandler[no_args_event_spec]
 
     @classmethod
     def create(cls, *children, **props) -> Component:

+ 18 - 18
reflex/components/component.py

@@ -47,8 +47,8 @@ from reflex.event import (
     EventVar,
     call_event_fn,
     call_event_handler,
-    empty_event,
     get_handler_args,
+    no_args_event_spec,
 )
 from reflex.style import Style, format_as_emotion
 from reflex.utils import format, imports, types
@@ -637,21 +637,21 @@ class Component(BaseComponent, ABC):
 
         """
         default_triggers = {
-            EventTriggers.ON_FOCUS: empty_event,
-            EventTriggers.ON_BLUR: empty_event,
-            EventTriggers.ON_CLICK: empty_event,
-            EventTriggers.ON_CONTEXT_MENU: empty_event,
-            EventTriggers.ON_DOUBLE_CLICK: empty_event,
-            EventTriggers.ON_MOUSE_DOWN: empty_event,
-            EventTriggers.ON_MOUSE_ENTER: empty_event,
-            EventTriggers.ON_MOUSE_LEAVE: empty_event,
-            EventTriggers.ON_MOUSE_MOVE: empty_event,
-            EventTriggers.ON_MOUSE_OUT: empty_event,
-            EventTriggers.ON_MOUSE_OVER: empty_event,
-            EventTriggers.ON_MOUSE_UP: empty_event,
-            EventTriggers.ON_SCROLL: empty_event,
-            EventTriggers.ON_MOUNT: empty_event,
-            EventTriggers.ON_UNMOUNT: empty_event,
+            EventTriggers.ON_FOCUS: no_args_event_spec,
+            EventTriggers.ON_BLUR: no_args_event_spec,
+            EventTriggers.ON_CLICK: no_args_event_spec,
+            EventTriggers.ON_CONTEXT_MENU: no_args_event_spec,
+            EventTriggers.ON_DOUBLE_CLICK: no_args_event_spec,
+            EventTriggers.ON_MOUSE_DOWN: no_args_event_spec,
+            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
+            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
+            EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
+            EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
+            EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
+            EventTriggers.ON_MOUSE_UP: no_args_event_spec,
+            EventTriggers.ON_SCROLL: no_args_event_spec,
+            EventTriggers.ON_MOUNT: no_args_event_spec,
+            EventTriggers.ON_UNMOUNT: no_args_event_spec,
         }
 
         # Look for component specific triggers,
@@ -662,7 +662,7 @@ class Component(BaseComponent, ABC):
                 annotation = field.annotation
                 if (metadata := getattr(annotation, "__metadata__", None)) is not None:
                     args_spec = metadata[0]
-                default_triggers[field.name] = args_spec or (empty_event)  # type: ignore
+                default_triggers[field.name] = args_spec or (no_args_event_spec)  # type: ignore
         return default_triggers
 
     def __repr__(self) -> str:
@@ -1723,7 +1723,7 @@ class CustomComponent(Component):
                 value = self._create_event_chain(
                     value=value,
                     args_spec=event_triggers_in_component_declaration.get(
-                        key, empty_event
+                        key, no_args_event_spec
                     ),
                     key=key,
                 )

+ 2 - 2
reflex/components/core/clipboard.py

@@ -6,7 +6,7 @@ from typing import Dict, List, Tuple, Union
 
 from reflex.components.base.fragment import Fragment
 from reflex.components.tags.tag import Tag
-from reflex.event import EventChain, EventHandler, identity_event
+from reflex.event import EventChain, EventHandler, passthrough_event_spec
 from reflex.utils.format import format_prop, wrap
 from reflex.utils.imports import ImportVar
 from reflex.vars import get_unique_variable_name
@@ -20,7 +20,7 @@ class Clipboard(Fragment):
     targets: Var[List[str]]
 
     # Called when the user pastes data into the document. Data is a list of tuples of (mime_type, data). Binary types will be base64 encoded as a data uri.
-    on_paste: EventHandler[identity_event(List[Tuple[str, str]])]
+    on_paste: EventHandler[passthrough_event_spec(List[Tuple[str, str]])]
 
     # Save the original event actions for the on_paste event.
     on_paste_event_actions: Var[Dict[str, Union[bool, int]]]

+ 3 - 1
reflex/components/core/clipboard.pyi

@@ -6,7 +6,9 @@
 from typing import Any, Dict, List, Optional, Union, overload
 
 from reflex.components.base.fragment import Fragment
-from reflex.event import EventType
+from reflex.event import (
+    EventType,
+)
 from reflex.style import Style
 from reflex.utils.imports import ImportVar
 from reflex.vars.base import Var

+ 2 - 2
reflex/components/core/debounce.py

@@ -6,7 +6,7 @@ from typing import Any, Type, Union
 
 from reflex.components.component import Component
 from reflex.constants import EventTriggers
-from reflex.event import EventHandler, empty_event
+from reflex.event import EventHandler, no_args_event_spec
 from reflex.vars import VarData
 from reflex.vars.base import Var
 
@@ -46,7 +46,7 @@ class DebounceInput(Component):
     element: Var[Type[Component]]
 
     # Fired when the input value changes
-    on_change: EventHandler[empty_event]
+    on_change: EventHandler[no_args_event_spec]
 
     @classmethod
     def create(cls, *children: Component, **props: Any) -> Component:

+ 4 - 4
reflex/components/core/upload.py

@@ -22,8 +22,8 @@ from reflex.event import (
     EventHandler,
     EventSpec,
     call_event_fn,
-    call_script,
     parse_args_spec,
+    run_script,
 )
 from reflex.utils import format
 from reflex.utils.imports import ImportVar
@@ -106,8 +106,8 @@ def clear_selected_files(id_: str = DEFAULT_UPLOAD_ID) -> EventSpec:
     """
     # UploadFilesProvider assigns a special function to clear selected files
     # into the shared global refs object to make it accessible outside a React
-    # component via `call_script` (otherwise backend could never clear files).
-    return call_script(f"refs['__clear_selected_files']({id_!r})")
+    # component via `run_script` (otherwise backend could never clear files).
+    return run_script(f"refs['__clear_selected_files']({id_!r})")
 
 
 def cancel_upload(upload_id: str) -> EventSpec:
@@ -119,7 +119,7 @@ def cancel_upload(upload_id: str) -> EventSpec:
     Returns:
         An event spec that cancels the upload when triggered.
     """
-    return call_script(
+    return run_script(
         f"upload_controllers[{str(LiteralVar.create(upload_id))}]?.abort()"
     )
 

+ 19 - 17
reflex/components/datadisplay/dataeditor.py

@@ -10,7 +10,7 @@ from typing_extensions import TypedDict
 from reflex.base import Base
 from reflex.components.component import Component, NoSSRComponent
 from reflex.components.literals import LiteralRowMarker
-from reflex.event import EventHandler, empty_event, identity_event
+from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
 from reflex.utils import console, format, types
 from reflex.utils.imports import ImportDict, ImportVar
 from reflex.utils.serializers import serializer
@@ -284,56 +284,58 @@ class DataEditor(NoSSRComponent):
     theme: Var[Union[DataEditorTheme, Dict]]
 
     # Fired when a cell is activated.
-    on_cell_activated: EventHandler[identity_event(Tuple[int, int])]
+    on_cell_activated: EventHandler[passthrough_event_spec(Tuple[int, int])]
 
     # Fired when a cell is clicked.
-    on_cell_clicked: EventHandler[identity_event(Tuple[int, int])]
+    on_cell_clicked: EventHandler[passthrough_event_spec(Tuple[int, int])]
 
     # Fired when a cell is right-clicked.
-    on_cell_context_menu: EventHandler[identity_event(Tuple[int, int])]
+    on_cell_context_menu: EventHandler[passthrough_event_spec(Tuple[int, int])]
 
     # Fired when a cell is edited.
-    on_cell_edited: EventHandler[identity_event(Tuple[int, int], GridCell)]
+    on_cell_edited: EventHandler[passthrough_event_spec(Tuple[int, int], GridCell)]
 
     # Fired when a group header is clicked.
-    on_group_header_clicked: EventHandler[identity_event(Tuple[int, int], GridCell)]
+    on_group_header_clicked: EventHandler[
+        passthrough_event_spec(Tuple[int, int], GridCell)
+    ]
 
     # Fired when a group header is right-clicked.
     on_group_header_context_menu: EventHandler[
-        identity_event(int, GroupHeaderClickedEventArgs)
+        passthrough_event_spec(int, GroupHeaderClickedEventArgs)
     ]
 
     # Fired when a group header is renamed.
-    on_group_header_renamed: EventHandler[identity_event(str, str)]
+    on_group_header_renamed: EventHandler[passthrough_event_spec(str, str)]
 
     # Fired when a header is clicked.
-    on_header_clicked: EventHandler[identity_event(Tuple[int, int])]
+    on_header_clicked: EventHandler[passthrough_event_spec(Tuple[int, int])]
 
     # Fired when a header is right-clicked.
-    on_header_context_menu: EventHandler[identity_event(Tuple[int, int])]
+    on_header_context_menu: EventHandler[passthrough_event_spec(Tuple[int, int])]
 
     # Fired when a header menu item is clicked.
-    on_header_menu_click: EventHandler[identity_event(int, Rectangle)]
+    on_header_menu_click: EventHandler[passthrough_event_spec(int, Rectangle)]
 
     # Fired when an item is hovered.
-    on_item_hovered: EventHandler[identity_event(Tuple[int, int])]
+    on_item_hovered: EventHandler[passthrough_event_spec(Tuple[int, int])]
 
     # Fired when a selection is deleted.
-    on_delete: EventHandler[identity_event(GridSelection)]
+    on_delete: EventHandler[passthrough_event_spec(GridSelection)]
 
     # Fired when editing is finished.
     on_finished_editing: EventHandler[
-        identity_event(Union[GridCell, None], tuple[int, int])
+        passthrough_event_spec(Union[GridCell, None], tuple[int, int])
     ]
 
     # Fired when a row is appended.
-    on_row_appended: EventHandler[empty_event]
+    on_row_appended: EventHandler[no_args_event_spec]
 
     # Fired when the selection is cleared.
-    on_selection_cleared: EventHandler[empty_event]
+    on_selection_cleared: EventHandler[no_args_event_spec]
 
     # Fired when a column is resized.
-    on_column_resize: EventHandler[identity_event(GridColumn, int)]
+    on_column_resize: EventHandler[passthrough_event_spec(GridColumn, int)]
 
     def add_imports(self) -> ImportDict:
         """Add imports for the component.

+ 3 - 3
reflex/components/datadisplay/shiki_code_block.py

@@ -14,7 +14,7 @@ from reflex.components.el.elements.forms import Button
 from reflex.components.lucide.icon import Icon
 from reflex.components.props import NoExtrasAllowedProps
 from reflex.components.radix.themes.layout.box import Box
-from reflex.event import call_script, set_clipboard
+from reflex.event import run_script, set_clipboard
 from reflex.style import Style
 from reflex.utils.exceptions import VarTypeError
 from reflex.utils.imports import ImportVar
@@ -30,7 +30,7 @@ def copy_script() -> Any:
     Returns:
         Any: The result of calling the script.
     """
-    return call_script(
+    return run_script(
         f"""
 // Event listener for the parent click
 document.addEventListener('click', function(event) {{
@@ -68,7 +68,7 @@ document.addEventListener('click', function(event) {{
     }} else {{
         // console.error('Parent element not found.');
     }}
-}});
+}})
 """
     )
 

+ 2 - 2
reflex/components/moment/moment.py

@@ -4,7 +4,7 @@ import dataclasses
 from typing import List, Optional
 
 from reflex.components.component import NoSSRComponent
-from reflex.event import EventHandler, identity_event
+from reflex.event import EventHandler, passthrough_event_spec
 from reflex.utils.imports import ImportDict
 from reflex.vars.base import LiteralVar, Var
 
@@ -96,7 +96,7 @@ class Moment(NoSSRComponent):
     locale: Var[str]
 
     # Fires when the date changes.
-    on_change: EventHandler[identity_event(str)]
+    on_change: EventHandler[passthrough_event_spec(str)]
 
     def add_imports(self) -> ImportDict:
         """Add the imports for the Moment component.

+ 3 - 3
reflex/components/next/image.py

@@ -2,7 +2,7 @@
 
 from typing import Any, Literal, Optional, Union
 
-from reflex.event import EventHandler, empty_event
+from reflex.event import EventHandler, no_args_event_spec
 from reflex.utils import types
 from reflex.vars.base import Var
 
@@ -56,10 +56,10 @@ class Image(NextComponent):
     blurDataURL: Var[str]
 
     # Fires when the image has loaded.
-    on_load: EventHandler[empty_event]
+    on_load: EventHandler[no_args_event_spec]
 
     # Fires when the image has an error.
-    on_error: EventHandler[empty_event]
+    on_error: EventHandler[no_args_event_spec]
 
     @classmethod
     def create(

+ 8 - 8
reflex/components/radix/primitives/drawer.py

@@ -10,7 +10,7 @@ from reflex.components.component import Component, ComponentNamespace
 from reflex.components.radix.primitives.base import RadixPrimitiveComponent
 from reflex.components.radix.themes.base import Theme
 from reflex.components.radix.themes.layout.flex import Flex
-from reflex.event import EventHandler, empty_event, identity_event
+from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
 from reflex.utils import console
 from reflex.vars.base import Var
 
@@ -40,7 +40,7 @@ class DrawerRoot(DrawerComponent):
     open: Var[bool]
 
     # Fires when the drawer is opened or closed.
-    on_open_change: EventHandler[identity_event(bool)]
+    on_open_change: EventHandler[passthrough_event_spec(bool)]
 
     # When `False`, it allows interaction with elements outside of the drawer without closing it. Defaults to `True`.
     modal: Var[bool]
@@ -49,7 +49,7 @@ class DrawerRoot(DrawerComponent):
     direction: Var[LiteralDirectionType]
 
     # Gets triggered after the open or close animation ends, it receives an open argument with the open state of the drawer by the time the function was triggered.
-    on_animation_end: EventHandler[identity_event(bool)]
+    on_animation_end: EventHandler[passthrough_event_spec(bool)]
 
     # When `False`, dragging, clicking outside, pressing esc, etc. will not close the drawer. Use this in combination with the open prop, otherwise you won't be able to open/close the drawer.
     dismissible: Var[bool]
@@ -141,19 +141,19 @@ class DrawerContent(DrawerComponent):
         return {"css": base_style}
 
     # Fired when the drawer content is opened. Deprecated.
-    on_open_auto_focus: EventHandler[empty_event]
+    on_open_auto_focus: EventHandler[no_args_event_spec]
 
     # Fired when the drawer content is closed. Deprecated.
-    on_close_auto_focus: EventHandler[empty_event]
+    on_close_auto_focus: EventHandler[no_args_event_spec]
 
     # Fired when the escape key is pressed. Deprecated.
-    on_escape_key_down: EventHandler[empty_event]
+    on_escape_key_down: EventHandler[no_args_event_spec]
 
     # Fired when the pointer is down outside the drawer content. Deprecated.
-    on_pointer_down_outside: EventHandler[empty_event]
+    on_pointer_down_outside: EventHandler[no_args_event_spec]
 
     # Fired when interacting outside the drawer content. Deprecated.
-    on_interact_outside: EventHandler[empty_event]
+    on_interact_outside: EventHandler[no_args_event_spec]
 
     @classmethod
     def create(cls, *children, **props):

+ 2 - 2
reflex/components/radix/primitives/form.py

@@ -8,7 +8,7 @@ from reflex.components.component import ComponentNamespace
 from reflex.components.core.debounce import DebounceInput
 from reflex.components.el.elements.forms import Form as HTMLForm
 from reflex.components.radix.themes.components.text_field import TextFieldRoot
-from reflex.event import EventHandler, empty_event
+from reflex.event import EventHandler, no_args_event_spec
 from reflex.vars.base import Var
 
 from .base import RadixPrimitiveComponentWithClassName
@@ -28,7 +28,7 @@ class FormRoot(FormComponent, HTMLForm):
     alias = "RadixFormRoot"
 
     # Fired when the errors are cleared.
-    on_clear_server_errors: EventHandler[empty_event]
+    on_clear_server_errors: EventHandler[no_args_event_spec]
 
     def add_style(self) -> dict[str, Any] | None:
         """Add style to the component.

+ 5 - 5
reflex/components/radix/themes/components/alert_dialog.py

@@ -5,7 +5,7 @@ from typing import Literal
 from reflex.components.component import ComponentNamespace
 from reflex.components.core.breakpoints import Responsive
 from reflex.components.el import elements
-from reflex.event import EventHandler, empty_event, identity_event
+from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
 from reflex.vars.base import Var
 
 from ..base import RadixThemesComponent, RadixThemesTriggerComponent
@@ -22,7 +22,7 @@ class AlertDialogRoot(RadixThemesComponent):
     open: Var[bool]
 
     # Fired when the open state changes.
-    on_open_change: EventHandler[identity_event(bool)]
+    on_open_change: EventHandler[passthrough_event_spec(bool)]
 
     # The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.
     default_open: Var[bool]
@@ -46,13 +46,13 @@ class AlertDialogContent(elements.Div, RadixThemesComponent):
     force_mount: Var[bool]
 
     # Fired when the dialog is opened.
-    on_open_auto_focus: EventHandler[empty_event]
+    on_open_auto_focus: EventHandler[no_args_event_spec]
 
     # Fired when the dialog is closed.
-    on_close_auto_focus: EventHandler[empty_event]
+    on_close_auto_focus: EventHandler[no_args_event_spec]
 
     # Fired when the escape key is pressed.
-    on_escape_key_down: EventHandler[empty_event]
+    on_escape_key_down: EventHandler[no_args_event_spec]
 
 
 class AlertDialogTitle(RadixThemesComponent):

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

@@ -6,7 +6,7 @@ from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.breakpoints import Responsive
 from reflex.components.radix.themes.layout.flex import Flex
 from reflex.components.radix.themes.typography.text import Text
-from reflex.event import EventHandler, identity_event
+from reflex.event import EventHandler, passthrough_event_spec
 from reflex.vars.base import LiteralVar, Var
 
 from ..base import (
@@ -61,7 +61,7 @@ class Checkbox(RadixThemesComponent):
     _rename_props = {"onChange": "onCheckedChange"}
 
     # Fired when the checkbox is checked or unchecked.
-    on_change: EventHandler[identity_event(bool)]
+    on_change: EventHandler[passthrough_event_spec(bool)]
 
 
 class HighLevelCheckbox(RadixThemesComponent):
@@ -112,7 +112,7 @@ class HighLevelCheckbox(RadixThemesComponent):
     _rename_props = {"onChange": "onCheckedChange"}
 
     # Fired when the checkbox is checked or unchecked.
-    on_change: EventHandler[identity_event(bool)]
+    on_change: EventHandler[passthrough_event_spec(bool)]
 
     @classmethod
     def create(cls, text: Var[str] = LiteralVar.create(""), **props) -> Component:

+ 13 - 13
reflex/components/radix/themes/components/context_menu.py

@@ -4,7 +4,7 @@ from typing import Dict, List, Literal, Union
 
 from reflex.components.component import ComponentNamespace
 from reflex.components.core.breakpoints import Responsive
-from reflex.event import EventHandler, empty_event, identity_event
+from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
 from reflex.vars.base import Var
 
 from ..base import (
@@ -39,7 +39,7 @@ class ContextMenuRoot(RadixThemesComponent):
     _invalid_children: List[str] = ["ContextMenuItem"]
 
     # Fired when the open state changes.
-    on_open_change: EventHandler[identity_event(bool)]
+    on_open_change: EventHandler[passthrough_event_spec(bool)]
 
     # The reading direction of submenus when applicable. If omitted, inherits globally from DirectionProvider or assumes LTR (left-to-right) reading mode.
     dir: Var[LiteralDirType]
@@ -109,19 +109,19 @@ class ContextMenuContent(RadixThemesComponent):
     hide_when_detached: Var[bool]
 
     # Fired when focus moves back after closing.
-    on_close_auto_focus: EventHandler[empty_event]
+    on_close_auto_focus: EventHandler[no_args_event_spec]
 
     # Fired when the escape key is pressed.
-    on_escape_key_down: EventHandler[empty_event]
+    on_escape_key_down: EventHandler[no_args_event_spec]
 
     # Fired when a pointer down event happens outside the context menu.
-    on_pointer_down_outside: EventHandler[empty_event]
+    on_pointer_down_outside: EventHandler[no_args_event_spec]
 
     # Fired when focus moves outside the context menu.
-    on_focus_outside: EventHandler[empty_event]
+    on_focus_outside: EventHandler[no_args_event_spec]
 
     # Fired when the pointer interacts outside the context menu.
-    on_interact_outside: EventHandler[empty_event]
+    on_interact_outside: EventHandler[no_args_event_spec]
 
 
 class ContextMenuSub(RadixThemesComponent):
@@ -136,7 +136,7 @@ class ContextMenuSub(RadixThemesComponent):
     default_open: Var[bool]
 
     # Fired when the open state changes.
-    on_open_change: EventHandler[identity_event(bool)]
+    on_open_change: EventHandler[passthrough_event_spec(bool)]
 
 
 class ContextMenuSubTrigger(RadixThemesComponent):
@@ -191,16 +191,16 @@ class ContextMenuSubContent(RadixThemesComponent):
     _valid_parents: List[str] = ["ContextMenuSub"]
 
     # Fired when the escape key is pressed.
-    on_escape_key_down: EventHandler[empty_event]
+    on_escape_key_down: EventHandler[no_args_event_spec]
 
     # Fired when a pointer down event happens outside the context menu.
-    on_pointer_down_outside: EventHandler[empty_event]
+    on_pointer_down_outside: EventHandler[no_args_event_spec]
 
     # Fired when focus moves outside the context menu.
-    on_focus_outside: EventHandler[empty_event]
+    on_focus_outside: EventHandler[no_args_event_spec]
 
     # Fired when interacting outside the context menu.
-    on_interact_outside: EventHandler[empty_event]
+    on_interact_outside: EventHandler[no_args_event_spec]
 
 
 class ContextMenuItem(RadixThemesComponent):
@@ -226,7 +226,7 @@ class ContextMenuItem(RadixThemesComponent):
     _valid_parents: List[str] = ["ContextMenuContent", "ContextMenuSubContent"]
 
     # Fired when the item is selected.
-    on_select: EventHandler[empty_event]
+    on_select: EventHandler[no_args_event_spec]
 
 
 class ContextMenuSeparator(RadixThemesComponent):

+ 7 - 7
reflex/components/radix/themes/components/dialog.py

@@ -5,7 +5,7 @@ from typing import Literal
 from reflex.components.component import ComponentNamespace
 from reflex.components.core.breakpoints import Responsive
 from reflex.components.el import elements
-from reflex.event import EventHandler, empty_event, identity_event
+from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
 from reflex.vars.base import Var
 
 from ..base import (
@@ -23,7 +23,7 @@ class DialogRoot(RadixThemesComponent):
     open: Var[bool]
 
     # Fired when the open state changes.
-    on_open_change: EventHandler[identity_event(bool)]
+    on_open_change: EventHandler[passthrough_event_spec(bool)]
 
     # The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.
     default_open: Var[bool]
@@ -50,19 +50,19 @@ class DialogContent(elements.Div, RadixThemesComponent):
     size: Var[Responsive[Literal["1", "2", "3", "4"]]]
 
     # Fired when the dialog is opened.
-    on_open_auto_focus: EventHandler[empty_event]
+    on_open_auto_focus: EventHandler[no_args_event_spec]
 
     # Fired when the dialog is closed.
-    on_close_auto_focus: EventHandler[empty_event]
+    on_close_auto_focus: EventHandler[no_args_event_spec]
 
     # Fired when the escape key is pressed.
-    on_escape_key_down: EventHandler[empty_event]
+    on_escape_key_down: EventHandler[no_args_event_spec]
 
     # Fired when the pointer is down outside the dialog.
-    on_pointer_down_outside: EventHandler[empty_event]
+    on_pointer_down_outside: EventHandler[no_args_event_spec]
 
     # Fired when the pointer interacts outside the dialog.
-    on_interact_outside: EventHandler[empty_event]
+    on_interact_outside: EventHandler[no_args_event_spec]
 
 
 class DialogDescription(RadixThemesComponent):

+ 13 - 13
reflex/components/radix/themes/components/dropdown_menu.py

@@ -4,7 +4,7 @@ from typing import Dict, List, Literal, Union
 
 from reflex.components.component import ComponentNamespace
 from reflex.components.core.breakpoints import Responsive
-from reflex.event import EventHandler, empty_event, identity_event
+from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
 from reflex.vars.base import Var
 
 from ..base import (
@@ -49,7 +49,7 @@ class DropdownMenuRoot(RadixThemesComponent):
     _invalid_children: List[str] = ["DropdownMenuItem"]
 
     # Fired when the open state changes.
-    on_open_change: EventHandler[identity_event(bool)]
+    on_open_change: EventHandler[passthrough_event_spec(bool)]
 
 
 class DropdownMenuTrigger(RadixThemesTriggerComponent):
@@ -116,19 +116,19 @@ class DropdownMenuContent(RadixThemesComponent):
     hide_when_detached: Var[bool]
 
     # Fired when the dialog is closed.
-    on_close_auto_focus: EventHandler[empty_event]
+    on_close_auto_focus: EventHandler[no_args_event_spec]
 
     # Fired when the escape key is pressed.
-    on_escape_key_down: EventHandler[empty_event]
+    on_escape_key_down: EventHandler[no_args_event_spec]
 
     # Fired when the pointer is down outside the dialog.
-    on_pointer_down_outside: EventHandler[empty_event]
+    on_pointer_down_outside: EventHandler[no_args_event_spec]
 
     # Fired when focus moves outside the dialog.
-    on_focus_outside: EventHandler[empty_event]
+    on_focus_outside: EventHandler[no_args_event_spec]
 
     # Fired when the pointer interacts outside the dialog.
-    on_interact_outside: EventHandler[empty_event]
+    on_interact_outside: EventHandler[no_args_event_spec]
 
 
 class DropdownMenuSubTrigger(RadixThemesTriggerComponent):
@@ -160,7 +160,7 @@ class DropdownMenuSub(RadixThemesComponent):
     default_open: Var[bool]
 
     # Fired when the open state changes.
-    on_open_change: EventHandler[identity_event(bool)]
+    on_open_change: EventHandler[passthrough_event_spec(bool)]
 
 
 class DropdownMenuSubContent(RadixThemesComponent):
@@ -198,16 +198,16 @@ class DropdownMenuSubContent(RadixThemesComponent):
     _valid_parents: List[str] = ["DropdownMenuSub"]
 
     # Fired when the escape key is pressed.
-    on_escape_key_down: EventHandler[empty_event]
+    on_escape_key_down: EventHandler[no_args_event_spec]
 
     # Fired when the pointer is down outside the dialog.
-    on_pointer_down_outside: EventHandler[empty_event]
+    on_pointer_down_outside: EventHandler[no_args_event_spec]
 
     # Fired when focus moves outside the dialog.
-    on_focus_outside: EventHandler[empty_event]
+    on_focus_outside: EventHandler[no_args_event_spec]
 
     # Fired when the pointer interacts outside the dialog.
-    on_interact_outside: EventHandler[empty_event]
+    on_interact_outside: EventHandler[no_args_event_spec]
 
 
 class DropdownMenuItem(RadixThemesComponent):
@@ -233,7 +233,7 @@ class DropdownMenuItem(RadixThemesComponent):
     _valid_parents: List[str] = ["DropdownMenuContent", "DropdownMenuSubContent"]
 
     # Fired when the item is selected.
-    on_select: EventHandler[empty_event]
+    on_select: EventHandler[no_args_event_spec]
 
 
 class DropdownMenuSeparator(RadixThemesComponent):

+ 2 - 2
reflex/components/radix/themes/components/hover_card.py

@@ -5,7 +5,7 @@ from typing import Dict, Literal, Union
 from reflex.components.component import ComponentNamespace
 from reflex.components.core.breakpoints import Responsive
 from reflex.components.el import elements
-from reflex.event import EventHandler, identity_event
+from reflex.event import EventHandler, passthrough_event_spec
 from reflex.vars.base import Var
 
 from ..base import (
@@ -32,7 +32,7 @@ class HoverCardRoot(RadixThemesComponent):
     close_delay: Var[int]
 
     # Fired when the open state changes.
-    on_open_change: EventHandler[identity_event(bool)]
+    on_open_change: EventHandler[passthrough_event_spec(bool)]
 
 
 class HoverCardTrigger(RadixThemesTriggerComponent):

+ 8 - 8
reflex/components/radix/themes/components/popover.py

@@ -5,7 +5,7 @@ from typing import Dict, Literal, Union
 from reflex.components.component import ComponentNamespace
 from reflex.components.core.breakpoints import Responsive
 from reflex.components.el import elements
-from reflex.event import EventHandler, empty_event, identity_event
+from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
 from reflex.vars.base import Var
 
 from ..base import (
@@ -26,7 +26,7 @@ class PopoverRoot(RadixThemesComponent):
     modal: Var[bool]
 
     # Fired when the open state changes.
-    on_open_change: EventHandler[identity_event(bool)]
+    on_open_change: EventHandler[passthrough_event_spec(bool)]
 
     # The open state of the popover when it is initially rendered. Use when you do not need to control its open state.
     default_open: Var[bool]
@@ -71,22 +71,22 @@ class PopoverContent(elements.Div, RadixThemesComponent):
     hide_when_detached: Var[bool]
 
     # Fired when the dialog is opened.
-    on_open_auto_focus: EventHandler[empty_event]
+    on_open_auto_focus: EventHandler[no_args_event_spec]
 
     # Fired when the dialog is closed.
-    on_close_auto_focus: EventHandler[empty_event]
+    on_close_auto_focus: EventHandler[no_args_event_spec]
 
     # Fired when the escape key is pressed.
-    on_escape_key_down: EventHandler[empty_event]
+    on_escape_key_down: EventHandler[no_args_event_spec]
 
     # Fired when the pointer is down outside the dialog.
-    on_pointer_down_outside: EventHandler[empty_event]
+    on_pointer_down_outside: EventHandler[no_args_event_spec]
 
     # Fired when focus moves outside the dialog.
-    on_focus_outside: EventHandler[empty_event]
+    on_focus_outside: EventHandler[no_args_event_spec]
 
     # Fired when the pointer interacts outside the dialog.
-    on_interact_outside: EventHandler[empty_event]
+    on_interact_outside: EventHandler[no_args_event_spec]
 
 
 class PopoverClose(RadixThemesTriggerComponent):

+ 2 - 2
reflex/components/radix/themes/components/radio_cards.py

@@ -4,7 +4,7 @@ from types import SimpleNamespace
 from typing import Literal, Union
 
 from reflex.components.core.breakpoints import Responsive
-from reflex.event import EventHandler, identity_event
+from reflex.event import EventHandler, passthrough_event_spec
 from reflex.vars.base import Var
 
 from ..base import LiteralAccentColor, RadixThemesComponent
@@ -65,7 +65,7 @@ class RadioCardsRoot(RadixThemesComponent):
     loop: Var[bool]
 
     # Event handler called when the value changes.
-    on_value_change: EventHandler[identity_event(str)]
+    on_value_change: EventHandler[passthrough_event_spec(str)]
 
 
 class RadioCardsItem(RadixThemesComponent):

+ 2 - 2
reflex/components/radix/themes/components/radio_group.py

@@ -9,7 +9,7 @@ from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.breakpoints import Responsive
 from reflex.components.radix.themes.layout.flex import Flex
 from reflex.components.radix.themes.typography.text import Text
-from reflex.event import EventHandler, identity_event
+from reflex.event import EventHandler, passthrough_event_spec
 from reflex.utils import types
 from reflex.vars.base import LiteralVar, Var
 from reflex.vars.sequence import StringVar
@@ -59,7 +59,7 @@ class RadioGroupRoot(RadixThemesComponent):
     _rename_props = {"onChange": "onValueChange"}
 
     # Fired when the value of the radio group changes.
-    on_change: EventHandler[identity_event(str)]
+    on_change: EventHandler[passthrough_event_spec(str)]
 
 
 class RadioGroupItem(RadixThemesComponent):

+ 6 - 6
reflex/components/radix/themes/components/select.py

@@ -5,7 +5,7 @@ from typing import List, Literal, Union
 import reflex as rx
 from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.breakpoints import Responsive
-from reflex.event import empty_event, identity_event
+from reflex.event import no_args_event_spec, passthrough_event_spec
 from reflex.vars.base import Var
 
 from ..base import (
@@ -48,10 +48,10 @@ class SelectRoot(RadixThemesComponent):
     _rename_props = {"onChange": "onValueChange"}
 
     # Fired when the value of the select changes.
-    on_change: rx.EventHandler[identity_event(str)]
+    on_change: rx.EventHandler[passthrough_event_spec(str)]
 
     # Fired when the select is opened or closed.
-    on_open_change: rx.EventHandler[identity_event(bool)]
+    on_open_change: rx.EventHandler[passthrough_event_spec(bool)]
 
 
 class SelectTrigger(RadixThemesComponent):
@@ -104,13 +104,13 @@ class SelectContent(RadixThemesComponent):
     align_offset: Var[int]
 
     # Fired when the select content is closed.
-    on_close_auto_focus: rx.EventHandler[empty_event]
+    on_close_auto_focus: rx.EventHandler[no_args_event_spec]
 
     # Fired when the escape key is pressed.
-    on_escape_key_down: rx.EventHandler[empty_event]
+    on_escape_key_down: rx.EventHandler[no_args_event_spec]
 
     # Fired when a pointer down event happens outside the select content.
-    on_pointer_down_outside: rx.EventHandler[empty_event]
+    on_pointer_down_outside: rx.EventHandler[no_args_event_spec]
 
 
 class SelectGroup(RadixThemesComponent):

+ 4 - 4
reflex/components/radix/themes/components/slider.py

@@ -6,7 +6,7 @@ from typing import List, Literal, Optional, Union
 
 from reflex.components.component import Component
 from reflex.components.core.breakpoints import Responsive
-from reflex.event import EventHandler, identity_event
+from reflex.event import EventHandler, passthrough_event_spec
 from reflex.vars.base import Var
 
 from ..base import (
@@ -15,9 +15,9 @@ from ..base import (
 )
 
 on_value_event_spec = (
-    identity_event(list[Union[int, float]]),
-    identity_event(list[int]),
-    identity_event(list[float]),
+    passthrough_event_spec(list[Union[int, float]]),
+    passthrough_event_spec(list[int]),
+    passthrough_event_spec(list[float]),
 )
 
 

+ 4 - 4
reflex/components/radix/themes/components/slider.pyi

@@ -6,16 +6,16 @@
 from typing import Any, Dict, List, Literal, Optional, Union, overload
 
 from reflex.components.core.breakpoints import Breakpoints
-from reflex.event import EventType, identity_event
+from reflex.event import EventType, passthrough_event_spec
 from reflex.style import Style
 from reflex.vars.base import Var
 
 from ..base import RadixThemesComponent
 
 on_value_event_spec = (
-    identity_event(list[Union[int, float]]),
-    identity_event(list[int]),
-    identity_event(list[float]),
+    passthrough_event_spec(list[Union[int, float]]),
+    passthrough_event_spec(list[int]),
+    passthrough_event_spec(list[float]),
 )
 
 class Slider(RadixThemesComponent):

+ 2 - 2
reflex/components/radix/themes/components/switch.py

@@ -3,7 +3,7 @@
 from typing import Literal
 
 from reflex.components.core.breakpoints import Responsive
-from reflex.event import EventHandler, identity_event
+from reflex.event import EventHandler, passthrough_event_spec
 from reflex.vars.base import Var
 
 from ..base import (
@@ -59,7 +59,7 @@ class Switch(RadixThemesComponent):
     _rename_props = {"onChange": "onCheckedChange"}
 
     # Fired when the value of the switch changes
-    on_change: EventHandler[identity_event(bool)]
+    on_change: EventHandler[passthrough_event_spec(bool)]
 
 
 switch = Switch.create

+ 2 - 2
reflex/components/radix/themes/components/tabs.py

@@ -7,7 +7,7 @@ from typing import Any, Dict, List, Literal
 from reflex.components.component import Component, ComponentNamespace
 from reflex.components.core.breakpoints import Responsive
 from reflex.components.core.colors import color
-from reflex.event import EventHandler, identity_event
+from reflex.event import EventHandler, passthrough_event_spec
 from reflex.vars.base import Var
 
 from ..base import (
@@ -42,7 +42,7 @@ class TabsRoot(RadixThemesComponent):
     _rename_props = {"onChange": "onValueChange"}
 
     # Fired when the value of the tabs changes.
-    on_change: EventHandler[identity_event(str)]
+    on_change: EventHandler[passthrough_event_spec(str)]
 
     def add_style(self) -> Dict[str, Any] | None:
         """Add style for the component.

+ 4 - 4
reflex/components/radix/themes/components/tooltip.py

@@ -3,7 +3,7 @@
 from typing import Dict, Literal, Union
 
 from reflex.components.component import Component
-from reflex.event import EventHandler, empty_event, identity_event
+from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
 from reflex.utils import format
 from reflex.vars.base import Var
 
@@ -85,13 +85,13 @@ class Tooltip(RadixThemesComponent):
     aria_label: Var[str]
 
     # Fired when the open state changes.
-    on_open_change: EventHandler[identity_event(bool)]
+    on_open_change: EventHandler[passthrough_event_spec(bool)]
 
     # Fired when the escape key is pressed.
-    on_escape_key_down: EventHandler[empty_event]
+    on_escape_key_down: EventHandler[no_args_event_spec]
 
     # Fired when the pointer is down outside the tooltip.
-    on_pointer_down_outside: EventHandler[empty_event]
+    on_pointer_down_outside: EventHandler[no_args_event_spec]
 
     @classmethod
     def create(cls, *children, **props) -> Component:

+ 17 - 17
reflex/components/react_player/react_player.py

@@ -5,7 +5,7 @@ from __future__ import annotations
 from typing_extensions import TypedDict
 
 from reflex.components.component import NoSSRComponent
-from reflex.event import EventHandler, empty_event, identity_event
+from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
 from reflex.vars.base import Var
 
 
@@ -57,49 +57,49 @@ class ReactPlayer(NoSSRComponent):
     height: Var[str]
 
     # Called when media is loaded and ready to play. If playing is set to true, media will play immediately.
-    on_ready: EventHandler[empty_event]
+    on_ready: EventHandler[no_args_event_spec]
 
     # Called when media starts playing.
-    on_start: EventHandler[empty_event]
+    on_start: EventHandler[no_args_event_spec]
 
     # Called when media starts or resumes playing after pausing or buffering.
-    on_play: EventHandler[empty_event]
+    on_play: EventHandler[no_args_event_spec]
 
     # Callback containing played and loaded progress as a fraction, and playedSeconds and loadedSeconds in seconds. eg { played: 0.12, playedSeconds: 11.3, loaded: 0.34, loadedSeconds: 16.7 }
-    on_progress: EventHandler[identity_event(Progress)]
+    on_progress: EventHandler[passthrough_event_spec(Progress)]
 
     # Callback containing duration of the media, in seconds.
-    on_duration: EventHandler[identity_event(float)]
+    on_duration: EventHandler[passthrough_event_spec(float)]
 
     # Called when media is paused.
-    on_pause: EventHandler[empty_event]
+    on_pause: EventHandler[no_args_event_spec]
 
     # Called when media starts buffering.
-    on_buffer: EventHandler[empty_event]
+    on_buffer: EventHandler[no_args_event_spec]
 
     # Called when media has finished buffering. Works for files, YouTube and Facebook.
-    on_buffer_end: EventHandler[empty_event]
+    on_buffer_end: EventHandler[no_args_event_spec]
 
     # Called when media seeks with seconds parameter.
-    on_seek: EventHandler[identity_event(float)]
+    on_seek: EventHandler[passthrough_event_spec(float)]
 
     # Called when playback rate of the player changed. Only supported by YouTube, Vimeo (if enabled), Wistia, and file paths.
-    on_playback_rate_change: EventHandler[empty_event]
+    on_playback_rate_change: EventHandler[no_args_event_spec]
 
     # Called when playback quality of the player changed. Only supported by YouTube (if enabled).
-    on_playback_quality_change: EventHandler[empty_event]
+    on_playback_quality_change: EventHandler[no_args_event_spec]
 
     # Called when media finishes playing. Does not fire when loop is set to true.
-    on_ended: EventHandler[empty_event]
+    on_ended: EventHandler[no_args_event_spec]
 
     # Called when an error occurs whilst attempting to play media.
-    on_error: EventHandler[empty_event]
+    on_error: EventHandler[no_args_event_spec]
 
     # Called when user clicks the light mode preview.
-    on_click_preview: EventHandler[empty_event]
+    on_click_preview: EventHandler[no_args_event_spec]
 
     # Called when picture-in-picture mode is enabled.
-    on_enable_pip: EventHandler[empty_event]
+    on_enable_pip: EventHandler[no_args_event_spec]
 
     # Called when picture-in-picture mode is disabled.
-    on_disable_pip: EventHandler[empty_event]
+    on_disable_pip: EventHandler[no_args_event_spec]

+ 45 - 45
reflex/components/recharts/cartesian.py

@@ -6,7 +6,7 @@ from typing import Any, Dict, List, Union
 
 from reflex.constants import EventTriggers
 from reflex.constants.colors import Color
-from reflex.event import EventHandler, empty_event
+from reflex.event import EventHandler, no_args_event_spec
 from reflex.vars.base import LiteralVar, Var
 
 from .recharts import (
@@ -109,25 +109,25 @@ class Axis(Recharts):
     text_anchor: Var[LiteralTextAnchor]
 
     # The customized event handler of click on the ticks of this axis
-    on_click: EventHandler[empty_event]
+    on_click: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousedown on the ticks of this axis
-    on_mouse_down: EventHandler[empty_event]
+    on_mouse_down: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseup on the ticks of this axis
-    on_mouse_up: EventHandler[empty_event]
+    on_mouse_up: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousemove on the ticks of this axis
-    on_mouse_move: EventHandler[empty_event]
+    on_mouse_move: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseout on the ticks of this axis
-    on_mouse_out: EventHandler[empty_event]
+    on_mouse_out: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseenter on the ticks of this axis
-    on_mouse_enter: EventHandler[empty_event]
+    on_mouse_enter: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseleave on the ticks of this axis
-    on_mouse_leave: EventHandler[empty_event]
+    on_mouse_leave: EventHandler[no_args_event_spec]
 
 
 class XAxis(Axis):
@@ -252,7 +252,7 @@ class Brush(Recharts):
             A dict mapping the event trigger to the var that is passed to the handler.
         """
         return {
-            EventTriggers.ON_CHANGE: empty_event,
+            EventTriggers.ON_CHANGE: no_args_event_spec,
         }
 
 
@@ -293,34 +293,34 @@ class Cartesian(Recharts):
     name: Var[Union[str, int]]
 
     # The customized event handler of animation start
-    on_animation_start: EventHandler[empty_event]
+    on_animation_start: EventHandler[no_args_event_spec]
 
     # The customized event handler of animation end
-    on_animation_end: EventHandler[empty_event]
+    on_animation_end: EventHandler[no_args_event_spec]
 
     # The customized event handler of click on the component in this group
-    on_click: EventHandler[empty_event]
+    on_click: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousedown on the component in this group
-    on_mouse_down: EventHandler[empty_event]
+    on_mouse_down: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseup on the component in this group
-    on_mouse_up: EventHandler[empty_event]
+    on_mouse_up: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousemove on the component in this group
-    on_mouse_move: EventHandler[empty_event]
+    on_mouse_move: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseover on the component in this group
-    on_mouse_over: EventHandler[empty_event]
+    on_mouse_over: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseout on the component in this group
-    on_mouse_out: EventHandler[empty_event]
+    on_mouse_out: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseenter on the component in this group
-    on_mouse_enter: EventHandler[empty_event]
+    on_mouse_enter: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseleave on the component in this group
-    on_mouse_leave: EventHandler[empty_event]
+    on_mouse_leave: EventHandler[no_args_event_spec]
 
 
 class Area(Cartesian):
@@ -526,28 +526,28 @@ class Scatter(Recharts):
     animation_easing: Var[LiteralAnimationEasing]
 
     # The customized event handler of click on the component in this group
-    on_click: EventHandler[empty_event]
+    on_click: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousedown on the component in this group
-    on_mouse_down: EventHandler[empty_event]
+    on_mouse_down: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseup on the component in this group
-    on_mouse_up: EventHandler[empty_event]
+    on_mouse_up: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousemove on the component in this group
-    on_mouse_move: EventHandler[empty_event]
+    on_mouse_move: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseover on the component in this group
-    on_mouse_over: EventHandler[empty_event]
+    on_mouse_over: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseout on the component in this group
-    on_mouse_out: EventHandler[empty_event]
+    on_mouse_out: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseenter on the component in this group
-    on_mouse_enter: EventHandler[empty_event]
+    on_mouse_enter: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseleave on the component in this group
-    on_mouse_leave: EventHandler[empty_event]
+    on_mouse_leave: EventHandler[no_args_event_spec]
 
 
 class Funnel(Recharts):
@@ -591,34 +591,34 @@ class Funnel(Recharts):
     _valid_children: List[str] = ["LabelList", "Cell"]
 
     # The customized event handler of animation start
-    on_animation_start: EventHandler[empty_event]
+    on_animation_start: EventHandler[no_args_event_spec]
 
     # The customized event handler of animation end
-    on_animation_end: EventHandler[empty_event]
+    on_animation_end: EventHandler[no_args_event_spec]
 
     # The customized event handler of click on the component in this group
-    on_click: EventHandler[empty_event]
+    on_click: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousedown on the component in this group
-    on_mouse_down: EventHandler[empty_event]
+    on_mouse_down: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseup on the component in this group
-    on_mouse_up: EventHandler[empty_event]
+    on_mouse_up: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousemove on the component in this group
-    on_mouse_move: EventHandler[empty_event]
+    on_mouse_move: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseover on the component in this group
-    on_mouse_over: EventHandler[empty_event]
+    on_mouse_over: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseout on the component in this group
-    on_mouse_out: EventHandler[empty_event]
+    on_mouse_out: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseenter on the component in this group
-    on_mouse_enter: EventHandler[empty_event]
+    on_mouse_enter: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseleave on the component in this group
-    on_mouse_leave: EventHandler[empty_event]
+    on_mouse_leave: EventHandler[no_args_event_spec]
 
 
 class ErrorBar(Recharts):
@@ -715,28 +715,28 @@ class ReferenceDot(Reference):
     _valid_children: List[str] = ["Label"]
 
     # The customized event handler of click on the component in this chart
-    on_click: EventHandler[empty_event]
+    on_click: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousedown on the component in this chart
-    on_mouse_down: EventHandler[empty_event]
+    on_mouse_down: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseup on the component in this chart
-    on_mouse_up: EventHandler[empty_event]
+    on_mouse_up: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseover on the component in this chart
-    on_mouse_over: EventHandler[empty_event]
+    on_mouse_over: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseout on the component in this chart
-    on_mouse_out: EventHandler[empty_event]
+    on_mouse_out: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseenter on the component in this chart
-    on_mouse_enter: EventHandler[empty_event]
+    on_mouse_enter: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousemove on the component in this chart
-    on_mouse_move: EventHandler[empty_event]
+    on_mouse_move: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseleave on the component in this chart
-    on_mouse_leave: EventHandler[empty_event]
+    on_mouse_leave: EventHandler[no_args_event_spec]
 
 
 class ReferenceArea(Recharts):

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

@@ -8,7 +8,7 @@ from reflex.components.component import Component
 from reflex.components.recharts.general import ResponsiveContainer
 from reflex.constants import EventTriggers
 from reflex.constants.colors import Color
-from reflex.event import EventHandler, empty_event
+from reflex.event import EventHandler, no_args_event_spec
 from reflex.vars.base import Var
 
 from .recharts import (
@@ -31,16 +31,16 @@ class ChartBase(RechartsCharts):
     height: Var[Union[str, int]] = "100%"  # type: ignore
 
     # The customized event handler of click on the component in this chart
-    on_click: EventHandler[empty_event]
+    on_click: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseenter on the component in this chart
-    on_mouse_enter: EventHandler[empty_event]
+    on_mouse_enter: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousemove on the component in this chart
-    on_mouse_move: EventHandler[empty_event]
+    on_mouse_move: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseleave on the component in this chart
-    on_mouse_leave: EventHandler[empty_event]
+    on_mouse_leave: EventHandler[no_args_event_spec]
 
     @staticmethod
     def _ensure_valid_dimension(name: str, value: Any) -> None:
@@ -270,16 +270,16 @@ class PieChart(ChartBase):
     ]
 
     # The customized event handler of mousedown on the sectors in this group
-    on_mouse_down: EventHandler[empty_event]
+    on_mouse_down: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseup on the sectors in this group
-    on_mouse_up: EventHandler[empty_event]
+    on_mouse_up: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseover on the sectors in this group
-    on_mouse_over: EventHandler[empty_event]
+    on_mouse_over: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseout on the sectors in this group
-    on_mouse_out: EventHandler[empty_event]
+    on_mouse_out: EventHandler[no_args_event_spec]
 
 
 class RadarChart(ChartBase):
@@ -330,9 +330,9 @@ class RadarChart(ChartBase):
             A dict mapping the event trigger to the var that is passed to the handler.
         """
         return {
-            EventTriggers.ON_CLICK: empty_event,
-            EventTriggers.ON_MOUSE_ENTER: empty_event,
-            EventTriggers.ON_MOUSE_LEAVE: empty_event,
+            EventTriggers.ON_CLICK: no_args_event_spec,
+            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
+            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
         }
 
 
@@ -419,14 +419,14 @@ class ScatterChart(ChartBase):
             A dict mapping the event trigger to the var that is passed to the handler.
         """
         return {
-            EventTriggers.ON_CLICK: empty_event,
-            EventTriggers.ON_MOUSE_DOWN: empty_event,
-            EventTriggers.ON_MOUSE_UP: empty_event,
-            EventTriggers.ON_MOUSE_MOVE: empty_event,
-            EventTriggers.ON_MOUSE_OVER: empty_event,
-            EventTriggers.ON_MOUSE_OUT: empty_event,
-            EventTriggers.ON_MOUSE_ENTER: empty_event,
-            EventTriggers.ON_MOUSE_LEAVE: empty_event,
+            EventTriggers.ON_CLICK: no_args_event_spec,
+            EventTriggers.ON_MOUSE_DOWN: no_args_event_spec,
+            EventTriggers.ON_MOUSE_UP: no_args_event_spec,
+            EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
+            EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
+            EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
+            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
+            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
         }
 
 
@@ -488,10 +488,10 @@ class Treemap(RechartsCharts):
     animation_easing: Var[LiteralAnimationEasing]
 
     # The customized event handler of animation start
-    on_animation_start: EventHandler[empty_event]
+    on_animation_start: EventHandler[no_args_event_spec]
 
     # The customized event handler of animation end
-    on_animation_end: EventHandler[empty_event]
+    on_animation_end: EventHandler[no_args_event_spec]
 
     @classmethod
     def create(cls, *children, **props) -> Component:

+ 10 - 10
reflex/components/recharts/general.py

@@ -6,7 +6,7 @@ from typing import Any, Dict, List, Union
 
 from reflex.components.component import MemoizationLeaf
 from reflex.constants.colors import Color
-from reflex.event import EventHandler, empty_event
+from reflex.event import EventHandler, no_args_event_spec
 from reflex.vars.base import LiteralVar, Var
 
 from .recharts import (
@@ -46,7 +46,7 @@ class ResponsiveContainer(Recharts, MemoizationLeaf):
     debounce: Var[int]
 
     # If specified provides a callback providing the updated chart width and height values.
-    on_resize: EventHandler[empty_event]
+    on_resize: EventHandler[no_args_event_spec]
 
     # Valid children components
     _valid_children: List[str] = [
@@ -104,28 +104,28 @@ class Legend(Recharts):
     margin: Var[Dict[str, Any]]
 
     # The customized event handler of click on the items in this group
-    on_click: EventHandler[empty_event]
+    on_click: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousedown on the items in this group
-    on_mouse_down: EventHandler[empty_event]
+    on_mouse_down: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseup on the items in this group
-    on_mouse_up: EventHandler[empty_event]
+    on_mouse_up: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousemove on the items in this group
-    on_mouse_move: EventHandler[empty_event]
+    on_mouse_move: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseover on the items in this group
-    on_mouse_over: EventHandler[empty_event]
+    on_mouse_over: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseout on the items in this group
-    on_mouse_out: EventHandler[empty_event]
+    on_mouse_out: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseenter on the items in this group
-    on_mouse_enter: EventHandler[empty_event]
+    on_mouse_enter: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseleave on the items in this group
-    on_mouse_leave: EventHandler[empty_event]
+    on_mouse_leave: EventHandler[no_args_event_spec]
 
 
 class GraphingTooltip(Recharts):

+ 33 - 33
reflex/components/recharts/polar.py

@@ -6,7 +6,7 @@ from typing import Any, Dict, List, Union
 
 from reflex.constants import EventTriggers
 from reflex.constants.colors import Color
-from reflex.event import EventHandler, empty_event
+from reflex.event import EventHandler, no_args_event_spec
 from reflex.vars.base import LiteralVar, Var
 
 from .recharts import (
@@ -103,14 +103,14 @@ class Pie(Recharts):
             A dict mapping the event trigger to the var that is passed to the handler.
         """
         return {
-            EventTriggers.ON_ANIMATION_START: empty_event,
-            EventTriggers.ON_ANIMATION_END: empty_event,
-            EventTriggers.ON_CLICK: empty_event,
-            EventTriggers.ON_MOUSE_MOVE: empty_event,
-            EventTriggers.ON_MOUSE_OVER: empty_event,
-            EventTriggers.ON_MOUSE_OUT: empty_event,
-            EventTriggers.ON_MOUSE_ENTER: empty_event,
-            EventTriggers.ON_MOUSE_LEAVE: empty_event,
+            EventTriggers.ON_ANIMATION_START: no_args_event_spec,
+            EventTriggers.ON_ANIMATION_END: no_args_event_spec,
+            EventTriggers.ON_CLICK: no_args_event_spec,
+            EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
+            EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
+            EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
+            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
+            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
         }
 
 
@@ -167,8 +167,8 @@ class Radar(Recharts):
             A dict mapping the event trigger to the var that is passed to the handler.
         """
         return {
-            EventTriggers.ON_ANIMATION_START: empty_event,
-            EventTriggers.ON_ANIMATION_END: empty_event,
+            EventTriggers.ON_ANIMATION_START: no_args_event_spec,
+            EventTriggers.ON_ANIMATION_END: no_args_event_spec,
         }
 
 
@@ -219,14 +219,14 @@ class RadialBar(Recharts):
             A dict mapping the event trigger to the var that is passed to the handler.
         """
         return {
-            EventTriggers.ON_CLICK: empty_event,
-            EventTriggers.ON_MOUSE_MOVE: empty_event,
-            EventTriggers.ON_MOUSE_OVER: empty_event,
-            EventTriggers.ON_MOUSE_OUT: empty_event,
-            EventTriggers.ON_MOUSE_ENTER: empty_event,
-            EventTriggers.ON_MOUSE_LEAVE: empty_event,
-            EventTriggers.ON_ANIMATION_START: empty_event,
-            EventTriggers.ON_ANIMATION_END: empty_event,
+            EventTriggers.ON_CLICK: no_args_event_spec,
+            EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
+            EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
+            EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
+            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
+            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
+            EventTriggers.ON_ANIMATION_START: no_args_event_spec,
+            EventTriggers.ON_ANIMATION_END: no_args_event_spec,
         }
 
 
@@ -277,28 +277,28 @@ class PolarAngleAxis(Recharts):
     _valid_children: List[str] = ["Label"]
 
     # The customized event handler of click on the ticks of this axis.
-    on_click: EventHandler[empty_event]
+    on_click: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousedown on the the ticks of this axis.
-    on_mouse_down: EventHandler[empty_event]
+    on_mouse_down: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseup on the ticks of this axis.
-    on_mouse_up: EventHandler[empty_event]
+    on_mouse_up: EventHandler[no_args_event_spec]
 
     # The customized event handler of mousemove on the ticks of this axis.
-    on_mouse_move: EventHandler[empty_event]
+    on_mouse_move: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseover on the ticks of this axis.
-    on_mouse_over: EventHandler[empty_event]
+    on_mouse_over: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseout on the ticks of this axis.
-    on_mouse_out: EventHandler[empty_event]
+    on_mouse_out: EventHandler[no_args_event_spec]
 
     # The customized event handler of moustenter on the ticks of this axis.
-    on_mouse_enter: EventHandler[empty_event]
+    on_mouse_enter: EventHandler[no_args_event_spec]
 
     # The customized event handler of mouseleave on the ticks of this axis.
-    on_mouse_leave: EventHandler[empty_event]
+    on_mouse_leave: EventHandler[no_args_event_spec]
 
 
 class PolarGrid(Recharts):
@@ -392,12 +392,12 @@ class PolarRadiusAxis(Recharts):
             A dict mapping the event trigger to the var that is passed to the handler.
         """
         return {
-            EventTriggers.ON_CLICK: empty_event,
-            EventTriggers.ON_MOUSE_MOVE: empty_event,
-            EventTriggers.ON_MOUSE_OVER: empty_event,
-            EventTriggers.ON_MOUSE_OUT: empty_event,
-            EventTriggers.ON_MOUSE_ENTER: empty_event,
-            EventTriggers.ON_MOUSE_LEAVE: empty_event,
+            EventTriggers.ON_CLICK: no_args_event_spec,
+            EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
+            EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
+            EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
+            EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
+            EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
         }
 
 

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

@@ -8,10 +8,7 @@ from reflex.base import Base
 from reflex.components.component import Component, ComponentNamespace
 from reflex.components.lucide.icon import Icon
 from reflex.components.props import NoExtrasAllowedProps, PropsBase
-from reflex.event import (
-    EventSpec,
-    call_script,
-)
+from reflex.event import EventSpec, run_script
 from reflex.style import Style, resolved_color_mode
 from reflex.utils import format
 from reflex.utils.imports import ImportVar
@@ -260,7 +257,7 @@ class Toaster(Component):
             toast = f"{toast_command}(`{message}`)"
 
         toast_action = Var(_js_expr=toast)
-        return call_script(toast_action)
+        return run_script(toast_action)
 
     @staticmethod
     def toast_info(message: str = "", **kwargs):
@@ -336,7 +333,7 @@ class Toaster(Component):
         dismiss_action = Var(
             _js_expr=dismiss, _var_data=VarData.merge(dismiss_var_data)
         )
-        return call_script(dismiss_action)
+        return run_script(dismiss_action)
 
     @classmethod
     def create(cls, *children, **props) -> Component:

+ 8 - 8
reflex/components/suneditor/editor.py

@@ -7,7 +7,7 @@ from typing import Dict, List, Literal, Optional, Tuple, Union
 
 from reflex.base import Base
 from reflex.components.component import Component, NoSSRComponent
-from reflex.event import EventHandler, empty_event, identity_event
+from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
 from reflex.utils.format import to_camel_case
 from reflex.utils.imports import ImportDict, ImportVar
 from reflex.vars.base import Var
@@ -207,31 +207,31 @@ class Editor(NoSSRComponent):
     disable_toolbar: Var[bool]
 
     # Fired when the editor content changes.
-    on_change: EventHandler[identity_event(str)]
+    on_change: EventHandler[passthrough_event_spec(str)]
 
     # Fired when the something is inputted in the editor.
-    on_input: EventHandler[empty_event]
+    on_input: EventHandler[no_args_event_spec]
 
     # Fired when the editor loses focus.
     on_blur: EventHandler[on_blur_spec]
 
     # Fired when the editor is loaded.
-    on_load: EventHandler[identity_event(bool)]
+    on_load: EventHandler[passthrough_event_spec(bool)]
 
     # Fired when the editor content is copied.
-    on_copy: EventHandler[empty_event]
+    on_copy: EventHandler[no_args_event_spec]
 
     # Fired when the editor content is cut.
-    on_cut: EventHandler[empty_event]
+    on_cut: EventHandler[no_args_event_spec]
 
     # Fired when the editor content is pasted.
     on_paste: EventHandler[on_paste_spec]
 
     # Fired when the code view is toggled.
-    toggle_code_view: EventHandler[identity_event(bool)]
+    toggle_code_view: EventHandler[passthrough_event_spec(bool)]
 
     # Fired when the full screen mode is toggled.
-    toggle_full_screen: EventHandler[identity_event(bool)]
+    toggle_full_screen: EventHandler[passthrough_event_spec(bool)]
 
     def add_imports(self) -> ImportDict:
         """Add imports for the Editor component.

+ 97 - 60
reflex/event.py

@@ -466,7 +466,7 @@ def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[Var[str]]:
     return (e.key,)
 
 
-def empty_event() -> Tuple[()]:
+def no_args_event_spec() -> Tuple[()]:
     """Empty event handler.
 
     Returns:
@@ -476,43 +476,14 @@ def empty_event() -> Tuple[()]:
 
 
 # These chains can be used for their side effects when no other events are desired.
-stop_propagation = EventChain(events=[], args_spec=empty_event).stop_propagation
-prevent_default = EventChain(events=[], args_spec=empty_event).prevent_default
+stop_propagation = EventChain(events=[], args_spec=no_args_event_spec).stop_propagation
+prevent_default = EventChain(events=[], args_spec=no_args_event_spec).prevent_default
 
 
 T = TypeVar("T")
 U = TypeVar("U")
 
 
-# def identity_event(event_type: Type[T]) -> Callable[[Var[T]], Tuple[Var[T]]]:
-#     """A helper function that returns the input event as output.
-
-#     Args:
-#         event_type: The type of the event.
-
-#     Returns:
-#         A function that returns the input event as output.
-#     """
-
-#     def inner(ev: Var[T]) -> Tuple[Var[T]]:
-#         return (ev,)
-
-#     inner.__signature__ = inspect.signature(inner).replace(  # type: ignore
-#         parameters=[
-#             inspect.Parameter(
-#                 "ev",
-#                 kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
-#                 annotation=Var[event_type],
-#             )
-#         ],
-#         return_annotation=Tuple[Var[event_type]],
-#     )
-#     inner.__annotations__["ev"] = Var[event_type]
-#     inner.__annotations__["return"] = Tuple[Var[event_type]]
-
-#     return inner
-
-
 class IdentityEventReturn(Generic[T], Protocol):
     """Protocol for an identity event return."""
 
@@ -529,20 +500,22 @@ class IdentityEventReturn(Generic[T], Protocol):
 
 
 @overload
-def identity_event(event_type: Type[T], /) -> Callable[[Var[T]], Tuple[Var[T]]]: ...  # type: ignore
+def passthrough_event_spec(
+    event_type: Type[T], /
+) -> Callable[[Var[T]], Tuple[Var[T]]]: ...  # type: ignore
 
 
 @overload
-def identity_event(
+def passthrough_event_spec(
     event_type_1: Type[T], event_type2: Type[U], /
 ) -> Callable[[Var[T], Var[U]], Tuple[Var[T], Var[U]]]: ...
 
 
 @overload
-def identity_event(*event_types: Type[T]) -> IdentityEventReturn[T]: ...
+def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]: ...
 
 
-def identity_event(*event_types: Type[T]) -> IdentityEventReturn[T]:  # type: ignore
+def passthrough_event_spec(*event_types: Type[T]) -> IdentityEventReturn[T]:  # type: ignore
     """A helper function that returns the input event as output.
 
     Args:
@@ -733,7 +706,16 @@ def console_log(message: str | Var[str]) -> EventSpec:
     Returns:
         An event to log the message.
     """
-    return server_side("_console", get_fn_signature(console_log), message=message)
+    return run_script(Var("console").to(dict).log.to(FunctionVar).call(message))
+
+
+def noop() -> EventSpec:
+    """Do nothing.
+
+    Returns:
+        An event to do nothing.
+    """
+    return run_script(Var.create(None))
 
 
 def back() -> EventSpec:
@@ -742,7 +724,9 @@ def back() -> EventSpec:
     Returns:
         An event to go back one page.
     """
-    return call_script("window.history.back()")
+    return run_script(
+        Var("window").to(dict).history.to(dict).back.to(FunctionVar).call()
+    )
 
 
 def window_alert(message: str | Var[str]) -> EventSpec:
@@ -754,7 +738,7 @@ def window_alert(message: str | Var[str]) -> EventSpec:
     Returns:
         An event to alert the message.
     """
-    return server_side("_alert", get_fn_signature(window_alert), message=message)
+    return run_script(Var("window").to(dict).alert.to(FunctionVar).call(message))
 
 
 def set_focus(ref: str) -> EventSpec:
@@ -785,12 +769,12 @@ def scroll_to(elem_id: str, align_to_top: bool | Var[bool] = True) -> EventSpec:
     """
     get_element_by_id = FunctionStringVar.create("document.getElementById")
 
-    return call_script(
+    return run_script(
         get_element_by_id(elem_id)
         .call(elem_id)
         .to(ObjectVar)
         .scrollIntoView.to(FunctionVar)
-        .call(align_to_top)
+        .call(align_to_top),
     )
 
 
@@ -897,10 +881,12 @@ def set_clipboard(content: str) -> EventSpec:
     Returns:
         EventSpec: An event to set some content in the clipboard.
     """
-    return server_side(
-        "_set_clipboard",
-        get_fn_signature(set_clipboard),
-        content=content,
+    return run_script(
+        Var("navigator")
+        .to(dict)
+        .clipboard.to(dict)
+        .writeText.to(FunctionVar)
+        .call(content)
     )
 
 
@@ -987,13 +973,7 @@ def _callback_arg_spec(eval_result):
 
 def call_script(
     javascript_code: str | Var[str],
-    callback: (
-        EventSpec
-        | EventHandler
-        | Callable
-        | List[EventSpec | EventHandler | Callable]
-        | None
-    ) = None,
+    callback: EventType | None = None,
 ) -> EventSpec:
     """Create an event handler that executes arbitrary javascript code.
 
@@ -1007,12 +987,10 @@ def call_script(
     callback_kwargs = {}
     if callback is not None:
         callback_kwargs = {
-            "callback": str(
-                format.format_queue_events(
-                    callback,
-                    args_spec=lambda result: [result],
-                ),
-            ),
+            "callback": format.format_queue_events(
+                callback,
+                args_spec=lambda result: [result],
+            )._js_expr,
         }
     if isinstance(javascript_code, str):
         # When there is VarData, include it and eval the JS code inline on the client.
@@ -1032,6 +1010,62 @@ def call_script(
     )
 
 
+def call_function(
+    javascript_code: str | Var,
+    callback: EventType | None = None,
+) -> EventSpec:
+    """Create an event handler that executes arbitrary javascript code.
+
+    Args:
+        javascript_code: The code to execute.
+        callback: EventHandler that will receive the result of evaluating the javascript code.
+
+    Returns:
+        EventSpec: An event that will execute the client side javascript.
+    """
+    callback_kwargs = {}
+    if callback is not None:
+        callback_kwargs = {
+            "callback": format.format_queue_events(
+                callback,
+                args_spec=lambda result: [result],
+            ),
+        }
+
+    javascript_code = (
+        Var(javascript_code) if isinstance(javascript_code, str) else javascript_code
+    )
+
+    return server_side(
+        "_call_function",
+        get_fn_signature(call_function),
+        function=javascript_code,
+        **callback_kwargs,
+    )
+
+
+def run_script(
+    javascript_code: str | Var,
+    callback: EventType | None = None,
+) -> EventSpec:
+    """Create an event handler that executes arbitrary javascript code.
+
+    Args:
+        javascript_code: The code to execute.
+        callback: EventHandler that will receive the result of evaluating the javascript code.
+
+    Returns:
+        EventSpec: An event that will execute the client side javascript.
+    """
+    javascript_code = (
+        Var(javascript_code) if isinstance(javascript_code, str) else javascript_code
+    )
+
+    return call_function(
+        ArgsFunctionOperation.create(tuple(), javascript_code), callback
+    )
+
+
 def get_event(state, event):
     """Get the event from the given state.
 
@@ -1822,13 +1856,14 @@ class EventNamespace(types.SimpleNamespace):
     check_fn_match_arg_spec = staticmethod(check_fn_match_arg_spec)
     resolve_annotation = staticmethod(resolve_annotation)
     parse_args_spec = staticmethod(parse_args_spec)
-    identity_event = staticmethod(identity_event)
+    passthrough_event_spec = staticmethod(passthrough_event_spec)
     input_event = staticmethod(input_event)
     key_event = staticmethod(key_event)
-    empty_event = staticmethod(empty_event)
+    no_args_event_spec = staticmethod(no_args_event_spec)
     server_side = staticmethod(server_side)
     redirect = staticmethod(redirect)
     console_log = staticmethod(console_log)
+    noop = staticmethod(noop)
     back = staticmethod(back)
     window_alert = staticmethod(window_alert)
     set_focus = staticmethod(set_focus)
@@ -1842,6 +1877,8 @@ class EventNamespace(types.SimpleNamespace):
     set_clipboard = staticmethod(set_clipboard)
     download = staticmethod(download)
     call_script = staticmethod(call_script)
+    call_function = staticmethod(call_function)
+    run_script = staticmethod(run_script)
 
 
 event = EventNamespace()

+ 3 - 3
reflex/experimental/client_state.py

@@ -8,7 +8,7 @@ import sys
 from typing import Any, Callable, Union
 
 from reflex import constants
-from reflex.event import EventChain, EventHandler, EventSpec, call_script
+from reflex.event import EventChain, EventHandler, EventSpec, run_script
 from reflex.utils.imports import ImportVar
 from reflex.vars import (
     VarData,
@@ -227,7 +227,7 @@ class ClientStateVar(Var):
         """
         if not self._global_ref:
             raise ValueError("ClientStateVar must be global to retrieve the value.")
-        return call_script(_client_state_ref(self._getter_name), callback=callback)
+        return run_script(_client_state_ref(self._getter_name), callback=callback)
 
     def push(self, value: Any) -> EventSpec:
         """Push a value to the client state variable from the backend.
@@ -245,4 +245,4 @@ class ClientStateVar(Var):
         """
         if not self._global_ref:
             raise ValueError("ClientStateVar must be global to push the value.")
-        return call_script(f"{_client_state_ref(self._setter_name)}({value})")
+        return run_script(f"{_client_state_ref(self._setter_name)}({value})")

+ 2 - 2
reflex/experimental/layout.py

@@ -12,7 +12,7 @@ from reflex.components.radix.themes.components.icon_button import IconButton
 from reflex.components.radix.themes.layout.box import Box
 from reflex.components.radix.themes.layout.container import Container
 from reflex.components.radix.themes.layout.stack import HStack
-from reflex.event import call_script
+from reflex.event import run_script
 from reflex.experimental import hooks
 from reflex.state import ComponentState
 from reflex.style import Style
@@ -173,7 +173,7 @@ class SidebarTrigger(Fragment):
         else:
             open, toggle = (
                 Var(_js_expr="open"),
-                call_script(Var(_js_expr="setOpen(!open)")),
+                run_script("setOpen(!open)"),
             )
 
         trigger_props["left"] = cond(open, f"calc({sidebar_width} - 32px)", "0")

+ 3 - 9
reflex/utils/format.py

@@ -6,7 +6,7 @@ import inspect
 import json
 import os
 import re
-from typing import TYPE_CHECKING, Any, Callable, List, Optional, Union
+from typing import TYPE_CHECKING, Any, List, Optional, Union
 
 from reflex import constants
 from reflex.utils import exceptions
@@ -14,7 +14,7 @@ from reflex.utils.console import deprecate
 
 if TYPE_CHECKING:
     from reflex.components.component import ComponentStyle
-    from reflex.event import ArgsSpec, EventChain, EventHandler, EventSpec
+    from reflex.event import ArgsSpec, EventChain, EventHandler, EventSpec, EventType
 
 WRAP_MAP = {
     "{": "}",
@@ -533,13 +533,7 @@ def format_event_chain(
 
 
 def format_queue_events(
-    events: (
-        EventSpec
-        | EventHandler
-        | Callable
-        | List[EventSpec | EventHandler | Callable]
-        | None
-    ) = None,
+    events: EventType | None = None,
     args_spec: Optional[ArgsSpec] = None,
 ) -> Var[EventChain]:
     """Format a list of event handler / event spec as a javascript callback.

+ 8 - 8
tests/units/components/test_component.py

@@ -19,10 +19,10 @@ from reflex.constants import EventTriggers
 from reflex.event import (
     EventChain,
     EventHandler,
-    empty_event,
-    identity_event,
     input_event,
+    no_args_event_spec,
     parse_args_spec,
+    passthrough_event_spec,
 )
 from reflex.state import BaseState
 from reflex.style import Style
@@ -111,10 +111,10 @@ def component2() -> Type[Component]:
             """
             return {
                 **super().get_event_triggers(),
-                "on_open": identity_event(bool),
-                "on_close": identity_event(bool),
-                "on_user_visited_count_changed": identity_event(int),
-                "on_user_list_changed": identity_event(List[str]),
+                "on_open": passthrough_event_spec(bool),
+                "on_close": passthrough_event_spec(bool),
+                "on_user_visited_count_changed": passthrough_event_spec(int),
+                "on_user_list_changed": passthrough_event_spec(List[str]),
             }
 
         def _get_imports(self) -> ParsedImportDict:
@@ -1821,8 +1821,8 @@ def test_custom_component_declare_event_handlers_in_fields():
     class TestComponent(Component):
         on_a: EventHandler[lambda e0: [e0]]
         on_b: EventHandler[input_event]
-        on_c: EventHandler[empty_event]
-        on_d: EventHandler[empty_event]
+        on_c: EventHandler[no_args_event_spec]
+        on_d: EventHandler[no_args_event_spec]
         on_e: EventHandler
         on_f: EventHandler[lambda a, b, c: [c, b, a]]
 

+ 3 - 3
tests/units/components/test_component_future_annotations.py

@@ -3,7 +3,7 @@ from __future__ import annotations
 from typing import Any
 
 from reflex.components.component import Component
-from reflex.event import EventHandler, empty_event, input_event
+from reflex.event import EventHandler, input_event, no_args_event_spec
 
 
 # This is a repeat of its namesake in test_component.py.
@@ -26,8 +26,8 @@ def test_custom_component_declare_event_handlers_in_fields():
     class TestComponent(Component):
         on_a: EventHandler[lambda e0: [e0]]
         on_b: EventHandler[input_event]
-        on_c: EventHandler[empty_event]
-        on_d: EventHandler[empty_event]
+        on_c: EventHandler[no_args_event_spec]
+        on_d: EventHandler[no_args_event_spec]
 
     custom_component = ReferenceComponent.create()
     test_component = TestComponent.create()

+ 27 - 11
tests/units/test_event.py

@@ -1,4 +1,4 @@
-from typing import List
+from typing import Callable, List
 
 import pytest
 
@@ -216,24 +216,40 @@ def test_event_console_log():
     """Test the event console log function."""
     spec = event.console_log("message")
     assert isinstance(spec, EventSpec)
-    assert spec.handler.fn.__qualname__ == "_console"
-    assert spec.args[0][0].equals(Var(_js_expr="message"))
-    assert spec.args[0][1].equals(LiteralVar.create("message"))
-    assert format.format_event(spec) == 'Event("_console", {message:"message"})'
+    assert spec.handler.fn.__qualname__ == "_call_function"
+    assert spec.args[0][0].equals(Var(_js_expr="function"))
+    assert spec.args[0][1].equals(
+        Var('(() => ((console["log"]("message"))))', _var_type=Callable)
+    )
+    assert (
+        format.format_event(spec)
+        == 'Event("_call_function", {function:(() => ((console["log"]("message"))))})'
+    )
     spec = event.console_log(Var(_js_expr="message"))
-    assert format.format_event(spec) == 'Event("_console", {message:message})'
+    assert (
+        format.format_event(spec)
+        == 'Event("_call_function", {function:(() => ((console["log"](message))))})'
+    )
 
 
 def test_event_window_alert():
     """Test the event window alert function."""
     spec = event.window_alert("message")
     assert isinstance(spec, EventSpec)
-    assert spec.handler.fn.__qualname__ == "_alert"
-    assert spec.args[0][0].equals(Var(_js_expr="message"))
-    assert spec.args[0][1].equals(LiteralVar.create("message"))
-    assert format.format_event(spec) == 'Event("_alert", {message:"message"})'
+    assert spec.handler.fn.__qualname__ == "_call_function"
+    assert spec.args[0][0].equals(Var(_js_expr="function"))
+    assert spec.args[0][1].equals(
+        Var('(() => ((window["alert"]("message"))))', _var_type=Callable)
+    )
+    assert (
+        format.format_event(spec)
+        == 'Event("_call_function", {function:(() => ((window["alert"]("message"))))})'
+    )
     spec = event.window_alert(Var(_js_expr="message"))
-    assert format.format_event(spec) == 'Event("_alert", {message:message})'
+    assert (
+        format.format_event(spec)
+        == 'Event("_call_function", {function:(() => ((window["alert"](message))))})'
+    )
 
 
 def test_set_focus():