fix events

This commit is contained in:
Khaleel Al-Adhami 2025-02-14 17:21:32 -08:00
parent 7d50500e06
commit 620136fe68

View File

@ -4,6 +4,7 @@ from __future__ import annotations
import copy import copy
import dataclasses import dataclasses
import inspect
import typing import typing
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from functools import lru_cache, wraps from functools import lru_cache, wraps
@ -21,6 +22,8 @@ from typing import (
Set, Set,
Type, Type,
Union, Union,
get_args,
get_origin,
) )
from typing_extensions import Self from typing_extensions import Self
@ -43,6 +46,7 @@ from reflex.constants import (
from reflex.constants.compiler import SpecialAttributes from reflex.constants.compiler import SpecialAttributes
from reflex.constants.state import FRONTEND_EVENT_STATE from reflex.constants.state import FRONTEND_EVENT_STATE
from reflex.event import ( from reflex.event import (
EventActionsMixin,
EventCallback, EventCallback,
EventChain, EventChain,
EventHandler, EventHandler,
@ -508,7 +512,7 @@ class Component(BaseComponent, ABC):
# Remove any keys that were added as events. # Remove any keys that were added as events.
for key in kwargs["event_triggers"]: for key in kwargs["event_triggers"]:
del kwargs[key] kwargs.pop(key, None)
# Place data_ and aria_ attributes into custom_attrs # Place data_ and aria_ attributes into custom_attrs
special_attributes = tuple( special_attributes = tuple(
@ -1672,11 +1676,51 @@ class CustomComponent(Component):
props = {key: value for key, value in kwargs.items() if key in props_types} props = {key: value for key, value in kwargs.items() if key in props_types}
kwargs = {key: value for key, value in kwargs.items() if key not in props_types} kwargs = {key: value for key, value in kwargs.items() if key not in props_types}
event_types = {
key
for key in props
if (
(get_origin((annotation := props_types.get(key))) or annotation)
== EventHandler
)
}
def get_args_spec(key: str) -> types.ArgsSpec | Sequence[types.ArgsSpec]:
type_ = props_types[key]
return (
args[0]
if (args := get_args(type_))
else (
annotation_args[1]
if get_origin(
(
annotation := inspect.getfullargspec(
component_fn
).annotations[key]
)
)
is typing.Annotated
and (annotation_args := get_args(annotation))
else no_args_event_spec
)
)
super().__init__( super().__init__(
event_triggers={
key: EventChain.create(
value=props[key],
args_spec=get_args_spec(key),
key=key,
)
for key in event_types
},
**kwargs, **kwargs,
) )
to_camel_cased_props = {format.to_camel_case(key) for key in props} to_camel_cased_props = {
format.to_camel_case(key) for key in props if key not in event_types
}
self.get_props = lambda: to_camel_cased_props # pyright: ignore [reportIncompatibleVariableOverride] self.get_props = lambda: to_camel_cased_props # pyright: ignore [reportIncompatibleVariableOverride]
# Unset the style. # Unset the style.
@ -1685,9 +1729,6 @@ class CustomComponent(Component):
# Set the tag to the name of the function. # Set the tag to the name of the function.
self.tag = format.to_title_case(self.component_fn.__name__) self.tag = format.to_title_case(self.component_fn.__name__)
# Get the event triggers defined in the component declaration.
event_triggers_in_component_declaration = self.get_event_triggers()
for key, value in props.items(): for key, value in props.items():
# Skip kwargs that are not props. # Skip kwargs that are not props.
if key not in props_types: if key not in props_types:
@ -1699,20 +1740,14 @@ class CustomComponent(Component):
type_ = props_types[key] type_ = props_types[key]
# Handle event chains. # Handle event chains.
if types._issubclass(type_, EventChain): if types._issubclass(type_, EventActionsMixin):
value = EventChain.create( inspect.getfullargspec(component_fn).annotations[key]
value=value, self.props[camel_cased_key] = EventChain.create(
args_spec=event_triggers_in_component_declaration.get( value=value, args_spec=get_args_spec(key), key=key
key, no_args_event_spec
),
key=key,
) )
self.props[camel_cased_key] = value
continue continue
value = LiteralVar.create(value) value = LiteralVar.create(value)
# Set the prop.
self.props[camel_cased_key] = value self.props[camel_cased_key] = value
setattr(self, camel_cased_key, value) setattr(self, camel_cased_key, value)
@ -1793,7 +1828,15 @@ class CustomComponent(Component):
return [ return [
Var( Var(
_js_expr=name, _js_expr=name,
_var_type=(prop._var_type if isinstance(prop, Var) else type(prop)), _var_type=(
prop._var_type
if isinstance(prop, Var)
else (
type(prop)
if not isinstance(prop, EventActionsMixin)
else EventChain
)
),
).guess_type() ).guess_type()
for name, prop in self.props.items() for name, prop in self.props.items()
] ]