diff --git a/reflex/components/base/script.py b/reflex/components/base/script.py index 0eba03f49..eb37d53e7 100644 --- a/reflex/components/base/script.py +++ b/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 +from reflex.event import EventHandler, empty_event from reflex.vars.base import LiteralVar, Var @@ -35,13 +35,13 @@ class Script(Component): ) # Triggered when the script is loading - on_load: EventHandler[lambda: []] + on_load: EventHandler[empty_event] # Triggered when the script has loaded - on_ready: EventHandler[lambda: []] + on_ready: EventHandler[empty_event] # Triggered when the script has errored - on_error: EventHandler[lambda: []] + on_error: EventHandler[empty_event] @classmethod def create(cls, *children, **props) -> Component: diff --git a/reflex/components/datadisplay/dataeditor.py b/reflex/components/datadisplay/dataeditor.py index 1c778f52a..ab84ad3f7 100644 --- a/reflex/components/datadisplay/dataeditor.py +++ b/reflex/components/datadisplay/dataeditor.py @@ -8,7 +8,7 @@ from typing import Any, Dict, List, Literal, Optional, Union from reflex.base import Base from reflex.components.component import Component, NoSSRComponent from reflex.components.literals import LiteralRowMarker -from reflex.event import EventHandler +from reflex.event import EventHandler, empty_event from reflex.utils import console, format, types from reflex.utils.imports import ImportDict, ImportVar from reflex.utils.serializers import serializer @@ -262,10 +262,10 @@ class DataEditor(NoSSRComponent): on_finished_editing: EventHandler[lambda new_value, movement: [new_value, movement]] # Fired when a row is appended. - on_row_appended: EventHandler[lambda: []] + on_row_appended: EventHandler[empty_event] # Fired when the selection is cleared. - on_selection_cleared: EventHandler[lambda: []] + on_selection_cleared: EventHandler[empty_event] # Fired when a column is resized. on_column_resize: EventHandler[lambda col, width: [col, width]] diff --git a/reflex/components/el/elements/forms.py b/reflex/components/el/elements/forms.py index 1963f8b37..05168e66c 100644 --- a/reflex/components/el/elements/forms.py +++ b/reflex/components/el/elements/forms.py @@ -10,7 +10,13 @@ from jinja2 import Environment from reflex.components.el.element import Element from reflex.components.tags.tag import Tag from reflex.constants import Dirs, EventTriggers -from reflex.event import EventChain, EventHandler, prevent_default +from reflex.event import ( + EventChain, + EventHandler, + input_event, + key_event, + prevent_default, +) from reflex.utils.imports import ImportDict from reflex.vars import VarData from reflex.vars.base import LiteralVar, Var @@ -345,19 +351,19 @@ class Input(BaseHTML): value: Var[Union[str, int, float]] # Fired when the input value changes - on_change: EventHandler[lambda e0: [e0.target.value]] + on_change: EventHandler[input_event] # Fired when the input gains focus - on_focus: EventHandler[lambda e0: [e0.target.value]] + on_focus: EventHandler[input_event] # Fired when the input loses focus - on_blur: EventHandler[lambda e0: [e0.target.value]] + on_blur: EventHandler[input_event] # Fired when a key is pressed down - on_key_down: EventHandler[lambda e0: [e0.key]] + on_key_down: EventHandler[key_event] # Fired when a key is released - on_key_up: EventHandler[lambda e0: [e0.key]] + on_key_up: EventHandler[key_event] class Label(BaseHTML): @@ -496,7 +502,7 @@ class Select(BaseHTML): size: Var[Union[str, int, bool]] # Fired when the select value changes - on_change: EventHandler[lambda e0: [e0.target.value]] + on_change: EventHandler[input_event] AUTO_HEIGHT_JS = """ @@ -586,19 +592,19 @@ class Textarea(BaseHTML): wrap: Var[Union[str, int, bool]] # Fired when the input value changes - on_change: EventHandler[lambda e0: [e0.target.value]] + on_change: EventHandler[input_event] # Fired when the input gains focus - on_focus: EventHandler[lambda e0: [e0.target.value]] + on_focus: EventHandler[input_event] # Fired when the input loses focus - on_blur: EventHandler[lambda e0: [e0.target.value]] + on_blur: EventHandler[input_event] # Fired when a key is pressed down - on_key_down: EventHandler[lambda e0: [e0.key]] + on_key_down: EventHandler[key_event] # Fired when a key is released - on_key_up: EventHandler[lambda e0: [e0.key]] + on_key_up: EventHandler[key_event] def _exclude_props(self) -> list[str]: return super()._exclude_props() + [ diff --git a/reflex/components/next/image.py b/reflex/components/next/image.py index 9e2f71821..fe74b0935 100644 --- a/reflex/components/next/image.py +++ b/reflex/components/next/image.py @@ -2,7 +2,7 @@ from typing import Any, Literal, Optional, Union -from reflex.event import EventHandler +from reflex.event import EventHandler, empty_event 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[lambda: []] + on_load: EventHandler[empty_event] # Fires when the image has an error. - on_error: EventHandler[lambda: []] + on_error: EventHandler[empty_event] @classmethod def create( diff --git a/reflex/components/radix/primitives/drawer.py b/reflex/components/radix/primitives/drawer.py index b814e878f..f0efa7e18 100644 --- a/reflex/components/radix/primitives/drawer.py +++ b/reflex/components/radix/primitives/drawer.py @@ -11,6 +11,7 @@ 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 +from reflex.utils import console from reflex.vars.base import Var @@ -127,20 +128,20 @@ class DrawerContent(DrawerComponent): base_style.update(style) return {"css": base_style} - # Fired when the drawer content is opened. - on_open_auto_focus: EventHandler[lambda e0: [e0.target.value]] + # Fired when the drawer content is opened. Deprecated. + on_open_auto_focus: EventHandler[lambda e0: []] - # Fired when the drawer content is closed. - on_close_auto_focus: EventHandler[lambda e0: [e0.target.value]] + # Fired when the drawer content is closed. Deprecated. + on_close_auto_focus: EventHandler[lambda e0: []] - # Fired when the escape key is pressed. - on_escape_key_down: EventHandler[lambda e0: [e0.target.value]] + # Fired when the escape key is pressed. Deprecated. + on_escape_key_down: EventHandler[lambda e0: []] - # Fired when the pointer is down outside the drawer content. - on_pointer_down_outside: EventHandler[lambda e0: [e0.target.value]] + # Fired when the pointer is down outside the drawer content. Deprecated. + on_pointer_down_outside: EventHandler[lambda e0: []] - # Fired when interacting outside the drawer content. - on_interact_outside: EventHandler[lambda e0: [e0.target.value]] + # Fired when interacting outside the drawer content. Deprecated. + on_interact_outside: EventHandler[lambda e0: []] @classmethod def create(cls, *children, **props): @@ -157,6 +158,23 @@ class DrawerContent(DrawerComponent): Returns: The drawer content. """ + deprecated_properties = [ + "on_open_auto_focus", + "on_close_auto_focus", + "on_escape_key_down", + "on_pointer_down_outside", + "on_interact_outside", + ] + + for prop in deprecated_properties: + if prop in props: + console.deprecate( + feature_name="drawer content events", + reason=f"The `{prop}` event is deprecated and will be removed in 0.7.0.", + deprecation_version="0.6.3", + removal_version="0.7.0", + ) + comp = super().create(*children, **props) return Theme.create(comp) diff --git a/reflex/components/radix/primitives/form.py b/reflex/components/radix/primitives/form.py index 895f6dbeb..4d4be7e40 100644 --- a/reflex/components/radix/primitives/form.py +++ b/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 +from reflex.event import EventHandler, empty_event 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[lambda: []] + on_clear_server_errors: EventHandler[empty_event] def add_style(self) -> dict[str, Any] | None: """Add style to the component. diff --git a/reflex/components/radix/themes/components/dropdown_menu.py b/reflex/components/radix/themes/components/dropdown_menu.py index 5ed1f9f64..c853619dd 100644 --- a/reflex/components/radix/themes/components/dropdown_menu.py +++ b/reflex/components/radix/themes/components/dropdown_menu.py @@ -164,7 +164,7 @@ class DropdownMenuSub(RadixThemesComponent): default_open: Var[bool] # Fired when the open state changes. - on_open_change: EventHandler[lambda e0: [e0.target.value]] + on_open_change: EventHandler[lambda e0: [e0]] class DropdownMenuSubContent(RadixThemesComponent): @@ -240,7 +240,7 @@ class DropdownMenuItem(RadixThemesComponent): _valid_parents: List[str] = ["DropdownMenuContent", "DropdownMenuSubContent"] # Fired when the item is selected. - on_select: EventHandler[lambda e0: [e0.target.value]] + on_select: EventHandler[lambda e0: []] class DropdownMenuSeparator(RadixThemesComponent): diff --git a/reflex/components/radix/themes/components/text_area.py b/reflex/components/radix/themes/components/text_area.py index 8b3b531cb..9f006c2e3 100644 --- a/reflex/components/radix/themes/components/text_area.py +++ b/reflex/components/radix/themes/components/text_area.py @@ -6,7 +6,6 @@ from reflex.components.component import Component from reflex.components.core.breakpoints import Responsive from reflex.components.core.debounce import DebounceInput from reflex.components.el import elements -from reflex.event import EventHandler from reflex.vars.base import Var from ..base import ( @@ -82,21 +81,6 @@ class TextArea(RadixThemesComponent, elements.Textarea): # How the text in the textarea is to be wrapped when submitting the form wrap: Var[str] - # Fired when the value of the textarea changes. - on_change: EventHandler[lambda e0: [e0.target.value]] - - # Fired when the textarea is focused. - on_focus: EventHandler[lambda e0: [e0.target.value]] - - # Fired when the textarea is blurred. - on_blur: EventHandler[lambda e0: [e0.target.value]] - - # Fired when a key is pressed down. - on_key_down: EventHandler[lambda e0: [e0.key]] - - # Fired when a key is released. - on_key_up: EventHandler[lambda e0: [e0.key]] - @classmethod def create(cls, *children, **props) -> Component: """Create an Input component. diff --git a/reflex/components/radix/themes/components/text_field.py b/reflex/components/radix/themes/components/text_field.py index 6c3372985..4277e93e0 100644 --- a/reflex/components/radix/themes/components/text_field.py +++ b/reflex/components/radix/themes/components/text_field.py @@ -8,7 +8,7 @@ from reflex.components.component import Component, ComponentNamespace from reflex.components.core.breakpoints import Responsive from reflex.components.core.debounce import DebounceInput from reflex.components.el import elements -from reflex.event import EventHandler +from reflex.event import EventHandler, input_event, key_event from reflex.vars.base import Var from ..base import ( @@ -72,19 +72,19 @@ class TextFieldRoot(elements.Div, RadixThemesComponent): value: Var[Union[str, int, float]] # Fired when the value of the textarea changes. - on_change: EventHandler[lambda e0: [e0.target.value]] + on_change: EventHandler[input_event] # Fired when the textarea is focused. - on_focus: EventHandler[lambda e0: [e0.target.value]] + on_focus: EventHandler[input_event] # Fired when the textarea is blurred. - on_blur: EventHandler[lambda e0: [e0.target.value]] + on_blur: EventHandler[input_event] # Fired when a key is pressed down. - on_key_down: EventHandler[lambda e0: [e0.key]] + on_key_down: EventHandler[key_event] # Fired when a key is released. - on_key_up: EventHandler[lambda e0: [e0.key]] + on_key_up: EventHandler[key_event] @classmethod def create(cls, *children, **props) -> Component: diff --git a/reflex/components/radix/themes/components/tooltip.py b/reflex/components/radix/themes/components/tooltip.py index f39de68a8..7fd181465 100644 --- a/reflex/components/radix/themes/components/tooltip.py +++ b/reflex/components/radix/themes/components/tooltip.py @@ -85,13 +85,13 @@ class Tooltip(RadixThemesComponent): aria_label: Var[str] # Fired when the open state changes. - on_open_change: EventHandler[lambda e0: [e0.target.value]] + on_open_change: EventHandler[lambda e0: [e0]] # Fired when the escape key is pressed. - on_escape_key_down: EventHandler[lambda e0: [e0.target.value]] + on_escape_key_down: EventHandler[lambda e0: []] # Fired when the pointer is down outside the tooltip. - on_pointer_down_outside: EventHandler[lambda e0: [e0.target.value]] + on_pointer_down_outside: EventHandler[lambda e0: []] @classmethod def create(cls, *children, **props) -> Component: diff --git a/reflex/components/react_player/react_player.py b/reflex/components/react_player/react_player.py index db5d9e77c..9da878b64 100644 --- a/reflex/components/react_player/react_player.py +++ b/reflex/components/react_player/react_player.py @@ -3,7 +3,7 @@ from __future__ import annotations from reflex.components.component import NoSSRComponent -from reflex.event import EventHandler +from reflex.event import EventHandler, empty_event from reflex.vars.base import Var @@ -46,13 +46,13 @@ 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[lambda: []] + on_ready: EventHandler[empty_event] # Called when media starts playing. - on_start: EventHandler[lambda: []] + on_start: EventHandler[empty_event] # Called when media starts or resumes playing after pausing or buffering. - on_play: EventHandler[lambda: []] + on_play: EventHandler[empty_event] # 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[lambda progress: [progress]] @@ -61,13 +61,13 @@ class ReactPlayer(NoSSRComponent): on_duration: EventHandler[lambda seconds: [seconds]] # Called when media is paused. - on_pause: EventHandler[lambda: []] + on_pause: EventHandler[empty_event] # Called when media starts buffering. - on_buffer: EventHandler[lambda: []] + on_buffer: EventHandler[empty_event] # Called when media has finished buffering. Works for files, YouTube and Facebook. - on_buffer_end: EventHandler[lambda: []] + on_buffer_end: EventHandler[empty_event] # Called when media seeks with seconds parameter. on_seek: EventHandler[lambda seconds: [seconds]] @@ -79,16 +79,16 @@ class ReactPlayer(NoSSRComponent): on_playback_quality_change: EventHandler[lambda e0: []] # Called when media finishes playing. Does not fire when loop is set to true. - on_ended: EventHandler[lambda: []] + on_ended: EventHandler[empty_event] # Called when an error occurs whilst attempting to play media. - on_error: EventHandler[lambda: []] + on_error: EventHandler[empty_event] # Called when user clicks the light mode preview. - on_click_preview: EventHandler[lambda: []] + on_click_preview: EventHandler[empty_event] # Called when picture-in-picture mode is enabled. - on_enable_pip: EventHandler[lambda: []] + on_enable_pip: EventHandler[empty_event] # Called when picture-in-picture mode is disabled. - on_disable_pip: EventHandler[lambda: []] + on_disable_pip: EventHandler[empty_event] diff --git a/reflex/components/recharts/cartesian.py b/reflex/components/recharts/cartesian.py index 67474126d..e4028053e 100644 --- a/reflex/components/recharts/cartesian.py +++ b/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 +from reflex.event import EventHandler, empty_event from reflex.vars.base import LiteralVar, Var from .recharts import ( @@ -101,25 +101,25 @@ class Axis(Recharts): text_anchor: Var[str] # 'start', 'middle', 'end' # The customized event handler of click on the ticks of this axis - on_click: EventHandler[lambda: []] + on_click: EventHandler[empty_event] # The customized event handler of mousedown on the ticks of this axis - on_mouse_down: EventHandler[lambda: []] + on_mouse_down: EventHandler[empty_event] # The customized event handler of mouseup on the ticks of this axis - on_mouse_up: EventHandler[lambda: []] + on_mouse_up: EventHandler[empty_event] # The customized event handler of mousemove on the ticks of this axis - on_mouse_move: EventHandler[lambda: []] + on_mouse_move: EventHandler[empty_event] # The customized event handler of mouseout on the ticks of this axis - on_mouse_out: EventHandler[lambda: []] + on_mouse_out: EventHandler[empty_event] # The customized event handler of mouseenter on the ticks of this axis - on_mouse_enter: EventHandler[lambda: []] + on_mouse_enter: EventHandler[empty_event] # The customized event handler of mouseleave on the ticks of this axis - on_mouse_leave: EventHandler[lambda: []] + on_mouse_leave: EventHandler[empty_event] class XAxis(Axis): @@ -267,28 +267,28 @@ class Cartesian(Recharts): legend_type: Var[LiteralLegendType] # The customized event handler of click on the component in this group - on_click: EventHandler[lambda: []] + on_click: EventHandler[empty_event] # The customized event handler of mousedown on the component in this group - on_mouse_down: EventHandler[lambda: []] + on_mouse_down: EventHandler[empty_event] # The customized event handler of mouseup on the component in this group - on_mouse_up: EventHandler[lambda: []] + on_mouse_up: EventHandler[empty_event] # The customized event handler of mousemove on the component in this group - on_mouse_move: EventHandler[lambda: []] + on_mouse_move: EventHandler[empty_event] # The customized event handler of mouseover on the component in this group - on_mouse_over: EventHandler[lambda: []] + on_mouse_over: EventHandler[empty_event] # The customized event handler of mouseout on the component in this group - on_mouse_out: EventHandler[lambda: []] + on_mouse_out: EventHandler[empty_event] # The customized event handler of mouseenter on the component in this group - on_mouse_enter: EventHandler[lambda: []] + on_mouse_enter: EventHandler[empty_event] # The customized event handler of mouseleave on the component in this group - on_mouse_leave: EventHandler[lambda: []] + on_mouse_leave: EventHandler[empty_event] class Area(Cartesian): @@ -494,28 +494,28 @@ class Scatter(Recharts): animation_easing: Var[LiteralAnimationEasing] # The customized event handler of click on the component in this group - on_click: EventHandler[lambda: []] + on_click: EventHandler[empty_event] # The customized event handler of mousedown on the component in this group - on_mouse_down: EventHandler[lambda: []] + on_mouse_down: EventHandler[empty_event] # The customized event handler of mouseup on the component in this group - on_mouse_up: EventHandler[lambda: []] + on_mouse_up: EventHandler[empty_event] # The customized event handler of mousemove on the component in this group - on_mouse_move: EventHandler[lambda: []] + on_mouse_move: EventHandler[empty_event] # The customized event handler of mouseover on the component in this group - on_mouse_over: EventHandler[lambda: []] + on_mouse_over: EventHandler[empty_event] # The customized event handler of mouseout on the component in this group - on_mouse_out: EventHandler[lambda: []] + on_mouse_out: EventHandler[empty_event] # The customized event handler of mouseenter on the component in this group - on_mouse_enter: EventHandler[lambda: []] + on_mouse_enter: EventHandler[empty_event] # The customized event handler of mouseleave on the component in this group - on_mouse_leave: EventHandler[lambda: []] + on_mouse_leave: EventHandler[empty_event] class Funnel(Recharts): @@ -556,34 +556,34 @@ class Funnel(Recharts): _valid_children: List[str] = ["LabelList", "Cell"] # The customized event handler of animation start - on_animation_start: EventHandler[lambda: []] + on_animation_start: EventHandler[empty_event] # The customized event handler of animation end - on_animation_end: EventHandler[lambda: []] + on_animation_end: EventHandler[empty_event] # The customized event handler of click on the component in this group - on_click: EventHandler[lambda: []] + on_click: EventHandler[empty_event] # The customized event handler of mousedown on the component in this group - on_mouse_down: EventHandler[lambda: []] + on_mouse_down: EventHandler[empty_event] # The customized event handler of mouseup on the component in this group - on_mouse_up: EventHandler[lambda: []] + on_mouse_up: EventHandler[empty_event] # The customized event handler of mousemove on the component in this group - on_mouse_move: EventHandler[lambda: []] + on_mouse_move: EventHandler[empty_event] # The customized event handler of mouseover on the component in this group - on_mouse_over: EventHandler[lambda: []] + on_mouse_over: EventHandler[empty_event] # The customized event handler of mouseout on the component in this group - on_mouse_out: EventHandler[lambda: []] + on_mouse_out: EventHandler[empty_event] # The customized event handler of mouseenter on the component in this group - on_mouse_enter: EventHandler[lambda: []] + on_mouse_enter: EventHandler[empty_event] # The customized event handler of mouseleave on the component in this group - on_mouse_leave: EventHandler[lambda: []] + on_mouse_leave: EventHandler[empty_event] class ErrorBar(Recharts): @@ -680,28 +680,28 @@ class ReferenceDot(Reference): _valid_children: List[str] = ["Label"] # The customized event handler of click on the component in this chart - on_click: EventHandler[lambda: []] + on_click: EventHandler[empty_event] # The customized event handler of mousedown on the component in this chart - on_mouse_down: EventHandler[lambda: []] + on_mouse_down: EventHandler[empty_event] # The customized event handler of mouseup on the component in this chart - on_mouse_up: EventHandler[lambda: []] + on_mouse_up: EventHandler[empty_event] # The customized event handler of mouseover on the component in this chart - on_mouse_over: EventHandler[lambda: []] + on_mouse_over: EventHandler[empty_event] # The customized event handler of mouseout on the component in this chart - on_mouse_out: EventHandler[lambda: []] + on_mouse_out: EventHandler[empty_event] # The customized event handler of mouseenter on the component in this chart - on_mouse_enter: EventHandler[lambda: []] + on_mouse_enter: EventHandler[empty_event] # The customized event handler of mousemove on the component in this chart - on_mouse_move: EventHandler[lambda: []] + on_mouse_move: EventHandler[empty_event] # The customized event handler of mouseleave on the component in this chart - on_mouse_leave: EventHandler[lambda: []] + on_mouse_leave: EventHandler[empty_event] class ReferenceArea(Recharts): diff --git a/reflex/components/recharts/charts.py b/reflex/components/recharts/charts.py index d1fd419a7..d4785f6c4 100644 --- a/reflex/components/recharts/charts.py +++ b/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 +from reflex.event import EventHandler, empty_event 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[lambda: []] + on_click: EventHandler[empty_event] # The customized event handler of mouseenter on the component in this chart - on_mouse_enter: EventHandler[lambda: []] + on_mouse_enter: EventHandler[empty_event] # The customized event handler of mousemove on the component in this chart - on_mouse_move: EventHandler[lambda: []] + on_mouse_move: EventHandler[empty_event] # The customized event handler of mouseleave on the component in this chart - on_mouse_leave: EventHandler[lambda: []] + on_mouse_leave: EventHandler[empty_event] @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[lambda: []] + on_mouse_down: EventHandler[empty_event] # The customized event handler of mouseup on the sectors in this group - on_mouse_up: EventHandler[lambda: []] + on_mouse_up: EventHandler[empty_event] # The customized event handler of mouseover on the sectors in this group - on_mouse_over: EventHandler[lambda: []] + on_mouse_over: EventHandler[empty_event] # The customized event handler of mouseout on the sectors in this group - on_mouse_out: EventHandler[lambda: []] + on_mouse_out: EventHandler[empty_event] class RadarChart(ChartBase): @@ -488,10 +488,10 @@ class Treemap(RechartsCharts): animation_easing: Var[LiteralAnimationEasing] # The customized event handler of animation start - on_animation_start: EventHandler[lambda: []] + on_animation_start: EventHandler[empty_event] # The customized event handler of animation end - on_animation_end: EventHandler[lambda: []] + on_animation_end: EventHandler[empty_event] @classmethod def create(cls, *children, **props) -> Component: diff --git a/reflex/components/recharts/general.py b/reflex/components/recharts/general.py index 270707a82..641e1562a 100644 --- a/reflex/components/recharts/general.py +++ b/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 +from reflex.event import EventHandler, empty_event 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[lambda: []] + on_resize: EventHandler[empty_event] # 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[lambda: []] + on_click: EventHandler[empty_event] # The customized event handler of mousedown on the items in this group - on_mouse_down: EventHandler[lambda: []] + on_mouse_down: EventHandler[empty_event] # The customized event handler of mouseup on the items in this group - on_mouse_up: EventHandler[lambda: []] + on_mouse_up: EventHandler[empty_event] # The customized event handler of mousemove on the items in this group - on_mouse_move: EventHandler[lambda: []] + on_mouse_move: EventHandler[empty_event] # The customized event handler of mouseover on the items in this group - on_mouse_over: EventHandler[lambda: []] + on_mouse_over: EventHandler[empty_event] # The customized event handler of mouseout on the items in this group - on_mouse_out: EventHandler[lambda: []] + on_mouse_out: EventHandler[empty_event] # The customized event handler of mouseenter on the items in this group - on_mouse_enter: EventHandler[lambda: []] + on_mouse_enter: EventHandler[empty_event] # The customized event handler of mouseleave on the items in this group - on_mouse_leave: EventHandler[lambda: []] + on_mouse_leave: EventHandler[empty_event] class GraphingTooltip(Recharts): diff --git a/reflex/components/recharts/polar.py b/reflex/components/recharts/polar.py index 5e95fb1cd..828000447 100644 --- a/reflex/components/recharts/polar.py +++ b/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 +from reflex.event import EventHandler, empty_event from reflex.vars.base import LiteralVar, Var from .recharts import ( @@ -253,28 +253,28 @@ class PolarAngleAxis(Recharts): _valid_children: List[str] = ["Label"] # The customized event handler of click on the ticks of this axis. - on_click: EventHandler[lambda: []] + on_click: EventHandler[empty_event] # The customized event handler of mousedown on the the ticks of this axis. - on_mouse_down: EventHandler[lambda: []] + on_mouse_down: EventHandler[empty_event] # The customized event handler of mouseup on the ticks of this axis. - on_mouse_up: EventHandler[lambda: []] + on_mouse_up: EventHandler[empty_event] # The customized event handler of mousemove on the ticks of this axis. - on_mouse_move: EventHandler[lambda: []] + on_mouse_move: EventHandler[empty_event] # The customized event handler of mouseover on the ticks of this axis. - on_mouse_over: EventHandler[lambda: []] + on_mouse_over: EventHandler[empty_event] # The customized event handler of mouseout on the ticks of this axis. - on_mouse_out: EventHandler[lambda: []] + on_mouse_out: EventHandler[empty_event] # The customized event handler of moustenter on the ticks of this axis. - on_mouse_enter: EventHandler[lambda: []] + on_mouse_enter: EventHandler[empty_event] # The customized event handler of mouseleave on the ticks of this axis. - on_mouse_leave: EventHandler[lambda: []] + on_mouse_leave: EventHandler[empty_event] class PolarGrid(Recharts): diff --git a/reflex/event.py b/reflex/event.py index 7384cf5bf..d2bebaa3f 100644 --- a/reflex/event.py +++ b/reflex/event.py @@ -24,7 +24,7 @@ from typing import ( from typing_extensions import get_args, get_origin from reflex import constants -from reflex.utils import format +from reflex.utils import console, format from reflex.utils.exceptions import EventFnArgMismatch, EventHandlerArgMismatch from reflex.utils.types import ArgsSpec, GenericType from reflex.vars import VarData @@ -399,23 +399,63 @@ prevent_default = EventChain(events=[], args_spec=lambda: []).prevent_default init=True, frozen=True, ) -class Target: - """A Javascript event target.""" +class JavascriptHTMLInputElement: + """Interface for a Javascript HTMLInputElement https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement.""" - checked: bool = False - value: Any = None + value: str = "" @dataclasses.dataclass( init=True, frozen=True, ) -class FrontendEvent: - """A Javascript event.""" +class JavascriptInputEvent: + """Interface for a Javascript InputEvent https://developer.mozilla.org/en-US/docs/Web/API/InputEvent.""" + + target: JavascriptHTMLInputElement = JavascriptHTMLInputElement() + + +@dataclasses.dataclass( + init=True, + frozen=True, +) +class JavasciptKeyboardEvent: + """Interface for a Javascript KeyboardEvent https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent.""" - target: Target = Target() key: str = "" - value: Any = None + + +def input_event(e: Var[JavascriptInputEvent]) -> Tuple[str]: + """Get the value from an input event. + + Args: + e: The input event. + + Returns: + The value from the input event. + """ + return (e.target.value,) + + +def key_event(e: Var[JavasciptKeyboardEvent]) -> Tuple[str]: + """Get the key from a keyboard event. + + Args: + e: The keyboard event. + + Returns: + The key from the keyboard event. + """ + return (e.key,) + + +def empty_event() -> Tuple[()]: + """Empty event handler. + + Returns: + An empty tuple. + """ + return tuple() # type: ignore @dataclasses.dataclass( @@ -946,6 +986,28 @@ def unwrap_var_annotation(annotation: GenericType): return annotation +def resolve_annotation(annotations: dict[str, Any], arg_name: str): + """Resolve the annotation for the given argument name. + + Args: + annotations: The annotations. + arg_name: The argument name. + + Returns: + The resolved annotation. + """ + annotation = annotations.get(arg_name) + if annotation is None: + console.deprecate( + feature_name="Unannotated event handler arguments", + reason="Provide type annotations for event handler arguments.", + deprecation_version="0.6.3", + removal_version="0.7.0", + ) + return JavascriptInputEvent + return annotation + + def parse_args_spec(arg_spec: ArgsSpec): """Parse the args provided in the ArgsSpec of an event trigger. @@ -961,7 +1023,7 @@ def parse_args_spec(arg_spec: ArgsSpec): return arg_spec( *[ Var(f"_{l_arg}").to( - unwrap_var_annotation(annotations.get(l_arg, FrontendEvent)) + unwrap_var_annotation(resolve_annotation(annotations, l_arg)) ) for l_arg in spec.args ] diff --git a/tests/units/components/test_component.py b/tests/units/components/test_component.py index 5e94db052..b54ce1bbe 100644 --- a/tests/units/components/test_component.py +++ b/tests/units/components/test_component.py @@ -16,7 +16,13 @@ from reflex.components.component import ( ) from reflex.components.radix.themes.layout.box import Box from reflex.constants import EventTriggers -from reflex.event import EventChain, EventHandler, parse_args_spec +from reflex.event import ( + EventChain, + EventHandler, + empty_event, + input_event, + parse_args_spec, +) from reflex.state import BaseState from reflex.style import Style from reflex.utils import imports @@ -1778,7 +1784,7 @@ def test_custom_component_declare_event_handlers_in_fields(): return { **super().get_event_triggers(), "on_a": lambda e0: [e0], - "on_b": lambda e0: [e0.target.value], + "on_b": input_event, "on_c": lambda e0: [], "on_d": lambda: [], "on_e": lambda: [], @@ -1787,9 +1793,9 @@ def test_custom_component_declare_event_handlers_in_fields(): class TestComponent(Component): on_a: EventHandler[lambda e0: [e0]] - on_b: EventHandler[lambda e0: [e0.target.value]] + on_b: EventHandler[input_event] on_c: EventHandler[lambda e0: []] - on_d: EventHandler[lambda: []] + on_d: EventHandler[empty_event] on_e: EventHandler on_f: EventHandler[lambda a, b, c: [c, b, a]] diff --git a/tests/units/components/test_component_future_annotations.py b/tests/units/components/test_component_future_annotations.py index 37aeb813a..791fef7c9 100644 --- a/tests/units/components/test_component_future_annotations.py +++ b/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 +from reflex.event import EventHandler, empty_event, input_event # This is a repeat of its namesake in test_component.py. @@ -25,9 +25,9 @@ def test_custom_component_declare_event_handlers_in_fields(): class TestComponent(Component): on_a: EventHandler[lambda e0: [e0]] - on_b: EventHandler[lambda e0: [e0.target.value]] + on_b: EventHandler[input_event] on_c: EventHandler[lambda e0: []] - on_d: EventHandler[lambda: []] + on_d: EventHandler[empty_event] custom_component = ReferenceComponent.create() test_component = TestComponent.create() diff --git a/tests/units/utils/test_format.py b/tests/units/utils/test_format.py index d7b0c791e..17485d52e 100644 --- a/tests/units/utils/test_format.py +++ b/tests/units/utils/test_format.py @@ -8,7 +8,7 @@ import plotly.graph_objects as go import pytest from reflex.components.tags.tag import Tag -from reflex.event import EventChain, EventHandler, EventSpec, FrontendEvent +from reflex.event import EventChain, EventHandler, EventSpec, JavascriptInputEvent from reflex.style import Style from reflex.utils import format from reflex.utils.serializers import serialize_figure @@ -387,7 +387,7 @@ def test_format_match( Var( _js_expr="_e", ) - .to(ObjectVar, FrontendEvent) + .to(ObjectVar, JavascriptInputEvent) .target.value, ), ),