19
19
Sequence ,
20
20
Set ,
21
21
Type ,
22
+ TypeVar ,
22
23
Union ,
23
24
get_args ,
24
25
get_origin ,
25
26
)
26
27
27
- from typing_extensions import Self
28
-
29
28
import reflex .state
30
29
from reflex .base import Base
31
30
from reflex .compiler .templates import STATEFUL_COMPONENT
@@ -210,6 +209,27 @@ def _components_from(
210
209
return ()
211
210
212
211
212
+ DEFAULT_TRIGGERS : dict [str , types .ArgsSpec | Sequence [types .ArgsSpec ]] = {
213
+ EventTriggers .ON_FOCUS : no_args_event_spec ,
214
+ EventTriggers .ON_BLUR : no_args_event_spec ,
215
+ EventTriggers .ON_CLICK : no_args_event_spec ,
216
+ EventTriggers .ON_CONTEXT_MENU : no_args_event_spec ,
217
+ EventTriggers .ON_DOUBLE_CLICK : no_args_event_spec ,
218
+ EventTriggers .ON_MOUSE_DOWN : no_args_event_spec ,
219
+ EventTriggers .ON_MOUSE_ENTER : no_args_event_spec ,
220
+ EventTriggers .ON_MOUSE_LEAVE : no_args_event_spec ,
221
+ EventTriggers .ON_MOUSE_MOVE : no_args_event_spec ,
222
+ EventTriggers .ON_MOUSE_OUT : no_args_event_spec ,
223
+ EventTriggers .ON_MOUSE_OVER : no_args_event_spec ,
224
+ EventTriggers .ON_MOUSE_UP : no_args_event_spec ,
225
+ EventTriggers .ON_SCROLL : no_args_event_spec ,
226
+ EventTriggers .ON_MOUNT : no_args_event_spec ,
227
+ EventTriggers .ON_UNMOUNT : no_args_event_spec ,
228
+ }
229
+
230
+ T = TypeVar ("T" , bound = "Component" )
231
+
232
+
213
233
class Component (BaseComponent , ABC ):
214
234
"""A component with style, event trigger and other props."""
215
235
@@ -364,12 +384,16 @@ def __init_subclass__(cls, **kwargs):
364
384
if field .name not in props :
365
385
continue
366
386
387
+ field_type = types .value_inside_optional (
388
+ types .get_field_type (cls , field .name )
389
+ )
390
+
367
391
# Set default values for any props.
368
- if types ._issubclass (field . type_ , Var ):
392
+ if types ._issubclass (field_type , Var ):
369
393
field .required = False
370
394
if field .default is not None :
371
395
field .default = LiteralVar .create (field .default )
372
- elif types ._issubclass (field . type_ , EventHandler ):
396
+ elif types ._issubclass (field_type , EventHandler ):
373
397
field .required = False
374
398
375
399
# Ensure renamed props from parent classes are applied to the subclass.
@@ -380,7 +404,7 @@ def __init_subclass__(cls, **kwargs):
380
404
inherited_rename_props .update (parent ._rename_props )
381
405
cls ._rename_props = inherited_rename_props
382
406
383
- def __init__ (self , * args , ** kwargs ):
407
+ def _post_init (self , * args , ** kwargs ):
384
408
"""Initialize the component.
385
409
386
410
Args:
@@ -393,16 +417,6 @@ def __init__(self, *args, **kwargs):
393
417
"""
394
418
# Set the id and children initially.
395
419
children = kwargs .get ("children" , [])
396
- initial_kwargs = {
397
- "id" : kwargs .get ("id" ),
398
- "children" : children ,
399
- ** {
400
- prop : LiteralVar .create (kwargs [prop ])
401
- for prop in self .get_initial_props ()
402
- if prop in kwargs
403
- },
404
- }
405
- super ().__init__ (** initial_kwargs )
406
420
407
421
self ._validate_component_children (children )
408
422
@@ -433,7 +447,9 @@ def __init__(self, *args, **kwargs):
433
447
field_type = EventChain
434
448
elif key in props :
435
449
# Set the field type.
436
- field_type = fields [key ].type_
450
+ field_type = types .value_inside_optional (
451
+ types .get_field_type (type (self ), key )
452
+ )
437
453
438
454
else :
439
455
continue
@@ -455,7 +471,10 @@ def determine_key(value: Any):
455
471
try :
456
472
kwargs [key ] = determine_key (value )
457
473
458
- expected_type = fields [key ].outer_type_ .__args__ [0 ]
474
+ expected_type = types .get_args (
475
+ types .get_field_type (type (self ), key )
476
+ )[0 ]
477
+
459
478
# validate literal fields.
460
479
types .validate_literal (
461
480
key , value , expected_type , type (self ).__name__
@@ -470,7 +489,7 @@ def determine_key(value: Any):
470
489
except TypeError :
471
490
# If it is not a valid var, check the base types.
472
491
passed_type = type (value )
473
- expected_type = fields [ key ]. outer_type_
492
+ expected_type = types . get_field_type ( type ( self ), key )
474
493
if types .is_union (passed_type ):
475
494
# We need to check all possible types in the union.
476
495
passed_types = (
@@ -552,7 +571,8 @@ def determine_key(value: Any):
552
571
kwargs ["class_name" ] = " " .join (class_name )
553
572
554
573
# Construct the component.
555
- super ().__init__ (* args , ** kwargs )
574
+ for key , value in kwargs .items ():
575
+ setattr (self , key , value )
556
576
557
577
def get_event_triggers (
558
578
self ,
@@ -562,34 +582,17 @@ def get_event_triggers(
562
582
Returns:
563
583
The event triggers.
564
584
"""
565
- default_triggers : dict [str , types .ArgsSpec | Sequence [types .ArgsSpec ]] = {
566
- EventTriggers .ON_FOCUS : no_args_event_spec ,
567
- EventTriggers .ON_BLUR : no_args_event_spec ,
568
- EventTriggers .ON_CLICK : no_args_event_spec ,
569
- EventTriggers .ON_CONTEXT_MENU : no_args_event_spec ,
570
- EventTriggers .ON_DOUBLE_CLICK : no_args_event_spec ,
571
- EventTriggers .ON_MOUSE_DOWN : no_args_event_spec ,
572
- EventTriggers .ON_MOUSE_ENTER : no_args_event_spec ,
573
- EventTriggers .ON_MOUSE_LEAVE : no_args_event_spec ,
574
- EventTriggers .ON_MOUSE_MOVE : no_args_event_spec ,
575
- EventTriggers .ON_MOUSE_OUT : no_args_event_spec ,
576
- EventTriggers .ON_MOUSE_OVER : no_args_event_spec ,
577
- EventTriggers .ON_MOUSE_UP : no_args_event_spec ,
578
- EventTriggers .ON_SCROLL : no_args_event_spec ,
579
- EventTriggers .ON_MOUNT : no_args_event_spec ,
580
- EventTriggers .ON_UNMOUNT : no_args_event_spec ,
581
- }
582
-
585
+ triggers = DEFAULT_TRIGGERS .copy ()
583
586
# Look for component specific triggers,
584
587
# e.g. variable declared as EventHandler types.
585
588
for field in self .get_fields ().values ():
586
- if types . _issubclass ( field .outer_type_ , EventHandler ) :
589
+ if field .type_ is EventHandler :
587
590
args_spec = None
588
591
annotation = field .annotation
589
592
if (metadata := getattr (annotation , "__metadata__" , None )) is not None :
590
593
args_spec = metadata [0 ]
591
- default_triggers [field .name ] = args_spec or (no_args_event_spec )
592
- return default_triggers
594
+ triggers [field .name ] = args_spec or (no_args_event_spec )
595
+ return triggers
593
596
594
597
def __repr__ (self ) -> str :
595
598
"""Represent the component in React.
@@ -703,9 +706,11 @@ def _get_component_prop_names(cls) -> Set[str]:
703
706
"""
704
707
return {
705
708
name
706
- for name , field in cls .get_fields (). items ()
709
+ for name in cls .get_fields ()
707
710
if name in cls .get_props ()
708
- and types ._issubclass (field .outer_type_ , Component )
711
+ and types ._issubclass (
712
+ types .value_inside_optional (types .get_field_type (cls , name )), Component
713
+ )
709
714
}
710
715
711
716
def _get_components_in_props (self ) -> Sequence [BaseComponent ]:
@@ -729,7 +734,7 @@ def _get_components_in_props(self) -> Sequence[BaseComponent]:
729
734
]
730
735
731
736
@classmethod
732
- def create (cls , * children , ** props ) -> Self :
737
+ def create (cls : Type [ T ] , * children , ** props ) -> T :
733
738
"""Create the component.
734
739
735
740
Args:
@@ -774,7 +779,22 @@ def validate_children(children: tuple | list):
774
779
for child in children
775
780
]
776
781
777
- return cls (children = children , ** props )
782
+ return cls ._create (children , ** props )
783
+
784
+ @classmethod
785
+ def _create (cls : Type [T ], children : list [Component ], ** props : Any ) -> T :
786
+ """Create the component.
787
+
788
+ Args:
789
+ children: The children of the component.
790
+ **props: The props of the component.
791
+
792
+ Returns:
793
+ The component.
794
+ """
795
+ comp = cls .construct (id = props .get ("id" ), children = children )
796
+ comp ._post_init (children = children , ** props )
797
+ return comp
778
798
779
799
def add_style (self ) -> dict [str , Any ] | None :
780
800
"""Add style to the component.
@@ -1659,7 +1679,7 @@ class CustomComponent(Component):
1659
1679
# The props of the component.
1660
1680
props : dict [str , Any ] = {}
1661
1681
1662
- def __init__ (self , ** kwargs ):
1682
+ def _post_init (self , ** kwargs ):
1663
1683
"""Initialize the custom component.
1664
1684
1665
1685
Args:
@@ -1702,7 +1722,7 @@ def get_args_spec(key: str) -> types.ArgsSpec | Sequence[types.ArgsSpec]:
1702
1722
)
1703
1723
)
1704
1724
1705
- super ().__init__ (
1725
+ super ()._post_init (
1706
1726
event_triggers = {
1707
1727
key : EventChain .create (
1708
1728
value = props [key ],
@@ -1863,7 +1883,9 @@ def custom_component(
1863
1883
def wrapper (* children , ** props ) -> CustomComponent :
1864
1884
# Remove the children from the props.
1865
1885
props .pop ("children" , None )
1866
- return CustomComponent (component_fn = component_fn , children = children , ** props )
1886
+ return CustomComponent ._create (
1887
+ children = list (children ), component_fn = component_fn , ** props
1888
+ )
1867
1889
1868
1890
return wrapper
1869
1891
0 commit comments