reflex 0.7.1a3__py3-none-any.whl → 0.7.2a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of reflex might be problematic. Click here for more details.

Files changed (226) hide show
  1. reflex/.templates/jinja/web/utils/context.js.jinja2 +8 -8
  2. reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +3 -3
  3. reflex/admin.py +1 -2
  4. reflex/app.py +53 -50
  5. reflex/app_mixins/lifespan.py +2 -2
  6. reflex/app_mixins/middleware.py +1 -2
  7. reflex/assets.py +1 -2
  8. reflex/base.py +2 -2
  9. reflex/compiler/compiler.py +51 -16
  10. reflex/compiler/utils.py +4 -13
  11. reflex/components/base/app_wrap.pyi +7 -7
  12. reflex/components/base/bare.py +3 -3
  13. reflex/components/base/body.pyi +7 -7
  14. reflex/components/base/document.py +1 -3
  15. reflex/components/base/document.pyi +32 -32
  16. reflex/components/base/error_boundary.py +2 -4
  17. reflex/components/base/error_boundary.pyi +11 -13
  18. reflex/components/base/fragment.pyi +7 -7
  19. reflex/components/base/head.pyi +13 -13
  20. reflex/components/base/link.pyi +22 -22
  21. reflex/components/base/meta.py +5 -7
  22. reflex/components/base/meta.pyi +40 -40
  23. reflex/components/base/script.pyi +11 -14
  24. reflex/components/base/strict_mode.pyi +7 -7
  25. reflex/components/component.py +188 -113
  26. reflex/components/core/auto_scroll.py +8 -1
  27. reflex/components/core/auto_scroll.pyi +183 -210
  28. reflex/components/core/banner.py +2 -4
  29. reflex/components/core/banner.pyi +390 -444
  30. reflex/components/core/breakpoints.py +5 -5
  31. reflex/components/core/client_side_routing.pyi +14 -14
  32. reflex/components/core/clipboard.py +4 -4
  33. reflex/components/core/clipboard.pyi +12 -14
  34. reflex/components/core/cond.py +17 -25
  35. reflex/components/core/debounce.py +3 -3
  36. reflex/components/core/debounce.pyi +14 -14
  37. reflex/components/core/foreach.py +7 -2
  38. reflex/components/core/html.py +1 -3
  39. reflex/components/core/html.pyi +184 -213
  40. reflex/components/core/match.py +15 -19
  41. reflex/components/core/sticky.pyi +930 -1078
  42. reflex/components/core/upload.py +4 -4
  43. reflex/components/core/upload.pyi +62 -62
  44. reflex/components/datadisplay/code.py +6 -6
  45. reflex/components/datadisplay/code.pyi +1159 -1165
  46. reflex/components/datadisplay/dataeditor.py +49 -49
  47. reflex/components/datadisplay/dataeditor.pyi +95 -123
  48. reflex/components/datadisplay/logo.py +1 -3
  49. reflex/components/datadisplay/shiki_code_block.py +8 -10
  50. reflex/components/datadisplay/shiki_code_block.pyi +1678 -1720
  51. reflex/components/el/element.pyi +7 -7
  52. reflex/components/el/elements/base.pyi +183 -210
  53. reflex/components/el/elements/forms.py +23 -23
  54. reflex/components/el/elements/forms.pyi +2571 -2933
  55. reflex/components/el/elements/inline.py +4 -4
  56. reflex/components/el/elements/inline.pyi +5191 -5953
  57. reflex/components/el/elements/media.py +47 -47
  58. reflex/components/el/elements/media.pyi +4802 -5500
  59. reflex/components/el/elements/metadata.py +1 -3
  60. reflex/components/el/elements/metadata.pyi +782 -896
  61. reflex/components/el/elements/other.pyi +1278 -1467
  62. reflex/components/el/elements/scripts.pyi +580 -667
  63. reflex/components/el/elements/sectioning.pyi +2761 -3166
  64. reflex/components/el/elements/tables.pyi +1840 -2119
  65. reflex/components/el/elements/typography.pyi +2772 -3179
  66. reflex/components/gridjs/datatable.py +7 -7
  67. reflex/components/gridjs/datatable.pyi +19 -19
  68. reflex/components/lucide/icon.pyi +21 -21
  69. reflex/components/markdown/markdown.py +2 -2
  70. reflex/components/markdown/markdown.pyi +9 -9
  71. reflex/components/moment/moment.py +11 -12
  72. reflex/components/moment/moment.pyi +44 -47
  73. reflex/components/next/base.pyi +7 -7
  74. reflex/components/next/image.py +3 -3
  75. reflex/components/next/image.pyi +19 -21
  76. reflex/components/next/link.pyi +9 -9
  77. reflex/components/next/video.py +1 -3
  78. reflex/components/next/video.pyi +9 -9
  79. reflex/components/plotly/plotly.py +22 -45
  80. reflex/components/plotly/plotly.pyi +164 -164
  81. reflex/components/radix/primitives/accordion.py +14 -14
  82. reflex/components/radix/primitives/accordion.pyi +439 -487
  83. reflex/components/radix/primitives/base.py +1 -3
  84. reflex/components/radix/primitives/base.pyi +15 -15
  85. reflex/components/radix/primitives/drawer.py +3 -3
  86. reflex/components/radix/primitives/drawer.pyi +110 -116
  87. reflex/components/radix/primitives/form.py +1 -1
  88. reflex/components/radix/primitives/form.pyi +668 -752
  89. reflex/components/radix/primitives/progress.py +6 -6
  90. reflex/components/radix/primitives/progress.pyi +225 -243
  91. reflex/components/radix/primitives/slider.py +6 -6
  92. reflex/components/radix/primitives/slider.pyi +52 -55
  93. reflex/components/radix/themes/base.py +3 -6
  94. reflex/components/radix/themes/base.pyi +197 -303
  95. reflex/components/radix/themes/color_mode.py +5 -5
  96. reflex/components/radix/themes/color_mode.pyi +366 -436
  97. reflex/components/radix/themes/components/alert_dialog.pyi +229 -262
  98. reflex/components/radix/themes/components/aspect_ratio.py +1 -3
  99. reflex/components/radix/themes/components/aspect_ratio.pyi +8 -8
  100. reflex/components/radix/themes/components/avatar.pyi +79 -94
  101. reflex/components/radix/themes/components/badge.pyi +252 -295
  102. reflex/components/radix/themes/components/button.pyi +269 -314
  103. reflex/components/radix/themes/components/callout.py +2 -2
  104. reflex/components/radix/themes/components/callout.pyi +1116 -1290
  105. reflex/components/radix/themes/components/card.pyi +194 -229
  106. reflex/components/radix/themes/components/checkbox.pyi +243 -278
  107. reflex/components/radix/themes/components/checkbox_cards.py +3 -7
  108. reflex/components/radix/themes/components/checkbox_cards.pyi +101 -135
  109. reflex/components/radix/themes/components/checkbox_group.py +2 -2
  110. reflex/components/radix/themes/components/checkbox_group.pyi +83 -96
  111. reflex/components/radix/themes/components/context_menu.py +18 -15
  112. reflex/components/radix/themes/components/context_menu.pyi +408 -458
  113. reflex/components/radix/themes/components/data_list.pyi +122 -147
  114. reflex/components/radix/themes/components/dialog.pyi +231 -264
  115. reflex/components/radix/themes/components/dropdown_menu.py +16 -13
  116. reflex/components/radix/themes/components/dropdown_menu.pyi +223 -246
  117. reflex/components/radix/themes/components/hover_card.py +2 -2
  118. reflex/components/radix/themes/components/hover_card.pyi +237 -282
  119. reflex/components/radix/themes/components/icon_button.pyi +269 -314
  120. reflex/components/radix/themes/components/inset.py +8 -8
  121. reflex/components/radix/themes/components/inset.pyi +232 -292
  122. reflex/components/radix/themes/components/popover.py +2 -2
  123. reflex/components/radix/themes/components/popover.pyi +229 -271
  124. reflex/components/radix/themes/components/progress.pyi +80 -96
  125. reflex/components/radix/themes/components/radio.pyi +73 -86
  126. reflex/components/radix/themes/components/radio_cards.py +4 -8
  127. reflex/components/radix/themes/components/radio_cards.pyi +117 -154
  128. reflex/components/radix/themes/components/radio_group.py +3 -3
  129. reflex/components/radix/themes/components/radio_group.pyi +250 -291
  130. reflex/components/radix/themes/components/scroll_area.pyi +14 -20
  131. reflex/components/radix/themes/components/segmented_control.py +6 -6
  132. reflex/components/radix/themes/components/segmented_control.pyi +89 -108
  133. reflex/components/radix/themes/components/select.py +7 -7
  134. reflex/components/radix/themes/components/select.pyi +376 -444
  135. reflex/components/radix/themes/components/separator.pyi +79 -93
  136. reflex/components/radix/themes/components/skeleton.pyi +32 -26
  137. reflex/components/radix/themes/components/slider.py +8 -8
  138. reflex/components/radix/themes/components/slider.pyi +99 -122
  139. reflex/components/radix/themes/components/spinner.pyi +12 -19
  140. reflex/components/radix/themes/components/switch.pyi +84 -99
  141. reflex/components/radix/themes/components/table.py +9 -9
  142. reflex/components/radix/themes/components/table.pyi +1440 -1794
  143. reflex/components/radix/themes/components/tabs.py +4 -4
  144. reflex/components/radix/themes/components/tabs.pyi +120 -132
  145. reflex/components/radix/themes/components/text_area.pyi +281 -331
  146. reflex/components/radix/themes/components/text_field.py +2 -2
  147. reflex/components/radix/themes/components/text_field.pyi +639 -734
  148. reflex/components/radix/themes/components/tooltip.py +6 -6
  149. reflex/components/radix/themes/components/tooltip.pyi +34 -43
  150. reflex/components/radix/themes/layout/base.pyi +85 -182
  151. reflex/components/radix/themes/layout/box.pyi +183 -210
  152. reflex/components/radix/themes/layout/center.pyi +225 -286
  153. reflex/components/radix/themes/layout/container.pyi +191 -224
  154. reflex/components/radix/themes/layout/flex.py +2 -2
  155. reflex/components/radix/themes/layout/flex.pyi +225 -286
  156. reflex/components/radix/themes/layout/grid.py +2 -2
  157. reflex/components/radix/themes/layout/grid.pyi +245 -315
  158. reflex/components/radix/themes/layout/list.py +2 -2
  159. reflex/components/radix/themes/layout/list.pyi +712 -815
  160. reflex/components/radix/themes/layout/section.pyi +187 -221
  161. reflex/components/radix/themes/layout/spacer.pyi +225 -286
  162. reflex/components/radix/themes/layout/stack.pyi +625 -768
  163. reflex/components/radix/themes/typography/blockquote.pyi +257 -299
  164. reflex/components/radix/themes/typography/code.pyi +259 -304
  165. reflex/components/radix/themes/typography/heading.pyi +272 -324
  166. reflex/components/radix/themes/typography/link.pyi +302 -358
  167. reflex/components/radix/themes/typography/text.pyi +1669 -1945
  168. reflex/components/react_player/audio.pyi +20 -22
  169. reflex/components/react_player/react_player.pyi +19 -19
  170. reflex/components/react_player/video.pyi +20 -22
  171. reflex/components/recharts/cartesian.py +100 -97
  172. reflex/components/recharts/cartesian.pyi +891 -1007
  173. reflex/components/recharts/charts.py +42 -42
  174. reflex/components/recharts/charts.pyi +212 -249
  175. reflex/components/recharts/general.py +22 -21
  176. reflex/components/recharts/general.pyi +198 -223
  177. reflex/components/recharts/polar.py +42 -45
  178. reflex/components/recharts/polar.pyi +254 -288
  179. reflex/components/recharts/recharts.pyi +13 -13
  180. reflex/components/sonner/toast.py +20 -20
  181. reflex/components/sonner/toast.pyi +58 -61
  182. reflex/components/suneditor/editor.py +9 -9
  183. reflex/components/suneditor/editor.pyi +78 -83
  184. reflex/components/tags/cond_tag.py +2 -2
  185. reflex/components/tags/iter_tag.py +10 -14
  186. reflex/components/tags/match_tag.py +2 -2
  187. reflex/components/tags/tag.py +10 -10
  188. reflex/config.py +36 -35
  189. reflex/constants/__init__.py +56 -53
  190. reflex/custom_components/custom_components.py +6 -7
  191. reflex/event.py +38 -42
  192. reflex/experimental/client_state.py +2 -4
  193. reflex/experimental/layout.py +2 -2
  194. reflex/experimental/layout.pyi +579 -663
  195. reflex/istate/data.py +4 -5
  196. reflex/middleware/hydrate_middleware.py +2 -2
  197. reflex/middleware/middleware.py +2 -2
  198. reflex/model.py +3 -5
  199. reflex/page.py +2 -2
  200. reflex/reflex.py +9 -10
  201. reflex/state.py +77 -49
  202. reflex/style.py +9 -3
  203. reflex/testing.py +21 -24
  204. reflex/utils/console.py +1 -1
  205. reflex/utils/decorator.py +26 -1
  206. reflex/utils/exec.py +6 -11
  207. reflex/utils/export.py +2 -3
  208. reflex/utils/format.py +4 -4
  209. reflex/utils/imports.py +12 -12
  210. reflex/utils/prerequisites.py +35 -84
  211. reflex/utils/processes.py +5 -5
  212. reflex/utils/pyi_generator.py +33 -22
  213. reflex/utils/serializers.py +60 -15
  214. reflex/utils/types.py +237 -56
  215. reflex/vars/base.py +122 -72
  216. reflex/vars/datetime.py +2 -2
  217. reflex/vars/function.py +52 -55
  218. reflex/vars/number.py +59 -5
  219. reflex/vars/object.py +57 -26
  220. reflex/vars/sequence.py +983 -958
  221. {reflex-0.7.1a3.dist-info → reflex-0.7.2a1.dist-info}/METADATA +3 -6
  222. reflex-0.7.2a1.dist-info/RECORD +405 -0
  223. {reflex-0.7.1a3.dist-info → reflex-0.7.2a1.dist-info}/WHEEL +1 -1
  224. reflex-0.7.1a3.dist-info/RECORD +0 -405
  225. {reflex-0.7.1a3.dist-info → reflex-0.7.2a1.dist-info}/LICENSE +0 -0
  226. {reflex-0.7.1a3.dist-info → reflex-0.7.2a1.dist-info}/entry_points.txt +0 -0
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import copy
6
6
  import dataclasses
7
+ import functools
7
8
  import inspect
8
9
  import typing
9
10
  from abc import ABC, abstractmethod
@@ -14,19 +15,19 @@ from typing import (
14
15
  Any,
15
16
  Callable,
16
17
  ClassVar,
17
- Dict,
18
18
  Iterator,
19
19
  List,
20
- Optional,
21
20
  Sequence,
22
21
  Set,
23
22
  Type,
23
+ TypeVar,
24
24
  Union,
25
25
  get_args,
26
26
  get_origin,
27
27
  )
28
28
 
29
- from typing_extensions import Self
29
+ import pydantic.v1
30
+ import pydantic.v1.fields
30
31
 
31
32
  import reflex.state
32
33
  from reflex.base import Base
@@ -54,7 +55,7 @@ from reflex.event import (
54
55
  no_args_event_spec,
55
56
  )
56
57
  from reflex.style import Style, format_as_emotion
57
- from reflex.utils import format, imports, types
58
+ from reflex.utils import console, format, imports, types
58
59
  from reflex.utils.imports import ImportDict, ImportVar, ParsedImportDict, parse_imports
59
60
  from reflex.vars import VarData
60
61
  from reflex.vars.base import (
@@ -76,19 +77,19 @@ class BaseComponent(Base, ABC):
76
77
  """
77
78
 
78
79
  # The children nested within the component.
79
- children: List[BaseComponent] = []
80
+ children: list[BaseComponent] = pydantic.v1.Field(default_factory=list)
80
81
 
81
82
  # The library that the component is based on.
82
- library: Optional[str] = None
83
+ library: str | None = pydantic.v1.Field(default_factory=lambda: None)
83
84
 
84
85
  # List here the non-react dependency needed by `library`
85
- lib_dependencies: List[str] = []
86
+ lib_dependencies: list[str] = pydantic.v1.Field(default_factory=list)
86
87
 
87
88
  # List here the dependencies that need to be transpiled by Next.js
88
- transpile_packages: List[str] = []
89
+ transpile_packages: list[str] = pydantic.v1.Field(default_factory=list)
89
90
 
90
91
  # The tag to use when rendering the component.
91
- tag: Optional[str] = None
92
+ tag: str | None = pydantic.v1.Field(default_factory=lambda: None)
92
93
 
93
94
  @abstractmethod
94
95
  def render(self) -> dict:
@@ -175,13 +176,23 @@ def evaluate_style_namespaces(style: ComponentStyle) -> dict:
175
176
 
176
177
 
177
178
  # Map from component to styling.
178
- ComponentStyle = Dict[
179
- Union[str, Type[BaseComponent], Callable, ComponentNamespace], Any
180
- ]
181
- ComponentChild = Union[types.PrimitiveType, Var, BaseComponent]
179
+ ComponentStyle = dict[str | Type[BaseComponent] | Callable | ComponentNamespace, Any]
180
+ ComponentChild = types.PrimitiveType | Var | BaseComponent
182
181
  ComponentChildTypes = (*types.PrimitiveTypes, Var, BaseComponent)
183
182
 
184
183
 
184
+ def _satisfies_type_hint(obj: Any, type_hint: Any) -> bool:
185
+ return types._isinstance(
186
+ obj,
187
+ type_hint,
188
+ nested=1,
189
+ treat_var_as_type=True,
190
+ treat_mutable_obj_as_immutable=(
191
+ isinstance(obj, Var) and not isinstance(obj, LiteralVar)
192
+ ),
193
+ )
194
+
195
+
185
196
  def satisfies_type_hint(obj: Any, type_hint: Any) -> bool:
186
197
  """Check if an object satisfies a type hint.
187
198
 
@@ -192,7 +203,23 @@ def satisfies_type_hint(obj: Any, type_hint: Any) -> bool:
192
203
  Returns:
193
204
  Whether the object satisfies the type hint.
194
205
  """
195
- return types._isinstance(obj, type_hint, nested=1)
206
+ if _satisfies_type_hint(obj, type_hint):
207
+ return True
208
+ if _satisfies_type_hint(obj, type_hint | None):
209
+ obj = (
210
+ obj
211
+ if not isinstance(obj, Var)
212
+ else (obj._var_value if isinstance(obj, LiteralVar) else obj)
213
+ )
214
+ console.deprecate(
215
+ "implicit-none-for-component-fields",
216
+ reason="Passing Vars with possible None values to component fields not explicitly marked as Optional is deprecated. "
217
+ + f"Passed {obj!s} of type {type(obj) if not isinstance(obj, Var) else obj._var_type} to {type_hint}.",
218
+ deprecation_version="0.7.2",
219
+ removal_version="0.8.0",
220
+ )
221
+ return True
222
+ return False
196
223
 
197
224
 
198
225
  def _components_from(
@@ -214,56 +241,81 @@ def _components_from(
214
241
  return ()
215
242
 
216
243
 
244
+ DEFAULT_TRIGGERS: dict[str, types.ArgsSpec | Sequence[types.ArgsSpec]] = {
245
+ EventTriggers.ON_FOCUS: no_args_event_spec,
246
+ EventTriggers.ON_BLUR: no_args_event_spec,
247
+ EventTriggers.ON_CLICK: no_args_event_spec,
248
+ EventTriggers.ON_CONTEXT_MENU: no_args_event_spec,
249
+ EventTriggers.ON_DOUBLE_CLICK: no_args_event_spec,
250
+ EventTriggers.ON_MOUSE_DOWN: no_args_event_spec,
251
+ EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
252
+ EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
253
+ EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
254
+ EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
255
+ EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
256
+ EventTriggers.ON_MOUSE_UP: no_args_event_spec,
257
+ EventTriggers.ON_SCROLL: no_args_event_spec,
258
+ EventTriggers.ON_MOUNT: no_args_event_spec,
259
+ EventTriggers.ON_UNMOUNT: no_args_event_spec,
260
+ }
261
+
262
+ T = TypeVar("T", bound="Component")
263
+
264
+
217
265
  class Component(BaseComponent, ABC):
218
266
  """A component with style, event trigger and other props."""
219
267
 
220
268
  # The style of the component.
221
- style: Style = Style()
269
+ style: Style = pydantic.v1.Field(default_factory=Style)
222
270
 
223
271
  # A mapping from event triggers to event chains.
224
- event_triggers: Dict[str, Union[EventChain, Var]] = {}
272
+ event_triggers: dict[str, EventChain | Var] = pydantic.v1.Field(
273
+ default_factory=dict
274
+ )
225
275
 
226
276
  # The alias for the tag.
227
- alias: Optional[str] = None
277
+ alias: str | None = pydantic.v1.Field(default_factory=lambda: None)
228
278
 
229
279
  # Whether the import is default or named.
230
- is_default: Optional[bool] = False
280
+ is_default: bool | None = pydantic.v1.Field(default_factory=lambda: False)
231
281
 
232
282
  # A unique key for the component.
233
- key: Any = None
283
+ key: Any = pydantic.v1.Field(default_factory=lambda: None)
234
284
 
235
285
  # The id for the component.
236
- id: Any = None
286
+ id: Any = pydantic.v1.Field(default_factory=lambda: None)
237
287
 
238
288
  # The class name for the component.
239
- class_name: Any = None
289
+ class_name: Any = pydantic.v1.Field(default_factory=lambda: None)
240
290
 
241
291
  # Special component props.
242
- special_props: List[Var] = []
292
+ special_props: list[Var] = pydantic.v1.Field(default_factory=list)
243
293
 
244
294
  # Whether the component should take the focus once the page is loaded
245
- autofocus: bool = False
295
+ autofocus: bool = pydantic.v1.Field(default_factory=lambda: False)
246
296
 
247
297
  # components that cannot be children
248
- _invalid_children: List[str] = []
298
+ _invalid_children: ClassVar[list[str]] = []
249
299
 
250
300
  # only components that are allowed as children
251
- _valid_children: List[str] = []
301
+ _valid_children: ClassVar[list[str]] = []
252
302
 
253
303
  # only components that are allowed as parent
254
- _valid_parents: List[str] = []
304
+ _valid_parents: ClassVar[list[str]] = []
255
305
 
256
306
  # props to change the name of
257
- _rename_props: Dict[str, str] = {}
307
+ _rename_props: ClassVar[dict[str, str]] = {}
258
308
 
259
309
  # custom attribute
260
- custom_attrs: Dict[str, Union[Var, Any]] = {}
310
+ custom_attrs: dict[str, Var | Any] = pydantic.v1.Field(default_factory=dict)
261
311
 
262
312
  # When to memoize this component and its children.
263
313
  _memoization_mode: MemoizationMode = MemoizationMode()
264
314
 
265
315
  # State class associated with this component instance
266
- State: Optional[Type[reflex.state.State]] = None
316
+ State: Type[reflex.state.State] | None = pydantic.v1.Field(
317
+ default_factory=lambda: None
318
+ )
267
319
 
268
320
  def add_imports(self) -> ImportDict | list[ImportDict]:
269
321
  """Add imports for the component.
@@ -369,11 +421,13 @@ class Component(BaseComponent, ABC):
369
421
  continue
370
422
 
371
423
  # Set default values for any props.
372
- if types._issubclass(field.type_, Var):
424
+ if field.type_ is Var:
373
425
  field.required = False
374
426
  if field.default is not None:
375
- field.default = LiteralVar.create(field.default)
376
- elif types._issubclass(field.type_, EventHandler):
427
+ field.default_factory = functools.partial(
428
+ LiteralVar.create, field.default
429
+ )
430
+ elif field.type_ is EventHandler:
377
431
  field.required = False
378
432
 
379
433
  # Ensure renamed props from parent classes are applied to the subclass.
@@ -384,7 +438,24 @@ class Component(BaseComponent, ABC):
384
438
  inherited_rename_props.update(parent._rename_props)
385
439
  cls._rename_props = inherited_rename_props
386
440
 
387
- def __init__(self, *args, **kwargs):
441
+ def __init__(self, **kwargs):
442
+ """Initialize the custom component.
443
+
444
+ Args:
445
+ **kwargs: The kwargs to pass to the component.
446
+ """
447
+ console.deprecate(
448
+ "component-direct-instantiation",
449
+ reason="Use the `create` method instead.",
450
+ deprecation_version="0.7.2",
451
+ removal_version="0.8.0",
452
+ )
453
+ super().__init__(
454
+ children=kwargs.get("children", []),
455
+ )
456
+ self._post_init(**kwargs)
457
+
458
+ def _post_init(self, *args, **kwargs):
388
459
  """Initialize the component.
389
460
 
390
461
  Args:
@@ -397,16 +468,6 @@ class Component(BaseComponent, ABC):
397
468
  """
398
469
  # Set the id and children initially.
399
470
  children = kwargs.get("children", [])
400
- initial_kwargs = {
401
- "id": kwargs.get("id"),
402
- "children": children,
403
- **{
404
- prop: LiteralVar.create(kwargs[prop])
405
- for prop in self.get_initial_props()
406
- if prop in kwargs
407
- },
408
- }
409
- super().__init__(**initial_kwargs)
410
471
 
411
472
  self._validate_component_children(children)
412
473
 
@@ -434,11 +495,10 @@ class Component(BaseComponent, ABC):
434
495
  )
435
496
  if key in component_specific_triggers:
436
497
  # Event triggers are bound to event chains.
437
- field_type = EventChain
498
+ is_var = False
438
499
  elif key in props:
439
500
  # Set the field type.
440
- field_type = fields[key].type_
441
-
501
+ is_var = field.type_ is Var if (field := fields.get(key)) else False
442
502
  else:
443
503
  continue
444
504
 
@@ -453,13 +513,14 @@ class Component(BaseComponent, ABC):
453
513
  return key
454
514
 
455
515
  # Check whether the key is a component prop.
456
- if types._issubclass(field_type, Var):
457
- # Used to store the passed types if var type is a union.
458
- passed_types = None
516
+ if is_var:
459
517
  try:
460
518
  kwargs[key] = determine_key(value)
461
519
 
462
- expected_type = fields[key].outer_type_.__args__[0]
520
+ expected_type = types.get_args(
521
+ types.get_field_type(type(self), key)
522
+ )[0]
523
+
463
524
  # validate literal fields.
464
525
  types.validate_literal(
465
526
  key, value, expected_type, type(self).__name__
@@ -474,22 +535,9 @@ class Component(BaseComponent, ABC):
474
535
  except TypeError:
475
536
  # If it is not a valid var, check the base types.
476
537
  passed_type = type(value)
477
- expected_type = fields[key].outer_type_
478
- if types.is_union(passed_type):
479
- # We need to check all possible types in the union.
480
- passed_types = (
481
- arg for arg in passed_type.__args__ if arg is not type(None)
482
- )
483
- if (
484
- # If the passed var is a union, check if all possible types are valid.
485
- passed_types
486
- and not all(
487
- types._issubclass(pt, expected_type) for pt in passed_types
488
- )
489
- ) or (
490
- # Else just check if the passed var type is valid.
491
- not passed_types and not satisfies_type_hint(value, expected_type)
492
- ):
538
+ expected_type = types.get_field_type(type(self), key)
539
+
540
+ if not satisfies_type_hint(value, expected_type):
493
541
  value_name = value._js_expr if isinstance(value, Var) else value
494
542
 
495
543
  additional_info = (
@@ -537,9 +585,15 @@ class Component(BaseComponent, ABC):
537
585
  "&": style,
538
586
  }
539
587
 
588
+ fields_style = self.get_fields()["style"]
589
+
540
590
  kwargs["style"] = Style(
541
591
  {
542
- **self.get_fields()["style"].default,
592
+ **(
593
+ fields_style.default_factory()
594
+ if fields_style.default_factory
595
+ else fields_style.default
596
+ ),
543
597
  **style,
544
598
  **{attr: value for attr, value in kwargs.items() if attr not in fields},
545
599
  }
@@ -550,50 +604,34 @@ class Component(BaseComponent, ABC):
550
604
  if isinstance(class_name, (List, tuple)):
551
605
  if any(isinstance(c, Var) for c in class_name):
552
606
  kwargs["class_name"] = LiteralArrayVar.create(
553
- class_name, _var_type=List[str]
607
+ class_name, _var_type=list[str]
554
608
  ).join(" ")
555
609
  else:
556
610
  kwargs["class_name"] = " ".join(class_name)
557
611
 
558
612
  # Construct the component.
559
- super().__init__(*args, **kwargs)
613
+ for key, value in kwargs.items():
614
+ setattr(self, key, value)
560
615
 
561
616
  def get_event_triggers(
562
617
  self,
563
- ) -> Dict[str, types.ArgsSpec | Sequence[types.ArgsSpec]]:
618
+ ) -> dict[str, types.ArgsSpec | Sequence[types.ArgsSpec]]:
564
619
  """Get the event triggers for the component.
565
620
 
566
621
  Returns:
567
622
  The event triggers.
568
623
  """
569
- default_triggers: Dict[str, types.ArgsSpec | Sequence[types.ArgsSpec]] = {
570
- EventTriggers.ON_FOCUS: no_args_event_spec,
571
- EventTriggers.ON_BLUR: no_args_event_spec,
572
- EventTriggers.ON_CLICK: no_args_event_spec,
573
- EventTriggers.ON_CONTEXT_MENU: no_args_event_spec,
574
- EventTriggers.ON_DOUBLE_CLICK: no_args_event_spec,
575
- EventTriggers.ON_MOUSE_DOWN: no_args_event_spec,
576
- EventTriggers.ON_MOUSE_ENTER: no_args_event_spec,
577
- EventTriggers.ON_MOUSE_LEAVE: no_args_event_spec,
578
- EventTriggers.ON_MOUSE_MOVE: no_args_event_spec,
579
- EventTriggers.ON_MOUSE_OUT: no_args_event_spec,
580
- EventTriggers.ON_MOUSE_OVER: no_args_event_spec,
581
- EventTriggers.ON_MOUSE_UP: no_args_event_spec,
582
- EventTriggers.ON_SCROLL: no_args_event_spec,
583
- EventTriggers.ON_MOUNT: no_args_event_spec,
584
- EventTriggers.ON_UNMOUNT: no_args_event_spec,
585
- }
586
-
624
+ triggers = DEFAULT_TRIGGERS.copy()
587
625
  # Look for component specific triggers,
588
626
  # e.g. variable declared as EventHandler types.
589
627
  for field in self.get_fields().values():
590
- if types._issubclass(field.outer_type_, EventHandler):
628
+ if field.type_ is EventHandler:
591
629
  args_spec = None
592
630
  annotation = field.annotation
593
631
  if (metadata := getattr(annotation, "__metadata__", None)) is not None:
594
632
  args_spec = metadata[0]
595
- default_triggers[field.name] = args_spec or (no_args_event_spec)
596
- return default_triggers
633
+ triggers[field.name] = args_spec or (no_args_event_spec)
634
+ return triggers
597
635
 
598
636
  def __repr__(self) -> str:
599
637
  """Represent the component in React.
@@ -670,7 +708,7 @@ class Component(BaseComponent, ABC):
670
708
 
671
709
  @classmethod
672
710
  @lru_cache(maxsize=None)
673
- def get_props(cls) -> Set[str]:
711
+ def get_props(cls) -> set[str]:
674
712
  """Get the unique fields for the component.
675
713
 
676
714
  Returns:
@@ -680,7 +718,7 @@ class Component(BaseComponent, ABC):
680
718
 
681
719
  @classmethod
682
720
  @lru_cache(maxsize=None)
683
- def get_initial_props(cls) -> Set[str]:
721
+ def get_initial_props(cls) -> set[str]:
684
722
  """Get the initial props to set for the component.
685
723
 
686
724
  Returns:
@@ -707,9 +745,11 @@ class Component(BaseComponent, ABC):
707
745
  """
708
746
  return {
709
747
  name
710
- for name, field in cls.get_fields().items()
748
+ for name in cls.get_fields()
711
749
  if name in cls.get_props()
712
- and types._issubclass(field.outer_type_, Component)
750
+ and types._issubclass(
751
+ types.value_inside_optional(types.get_field_type(cls, name)), Component
752
+ )
713
753
  }
714
754
 
715
755
  def _get_components_in_props(self) -> Sequence[BaseComponent]:
@@ -733,7 +773,7 @@ class Component(BaseComponent, ABC):
733
773
  ]
734
774
 
735
775
  @classmethod
736
- def create(cls, *children, **props) -> Self:
776
+ def create(cls: Type[T], *children, **props) -> T:
737
777
  """Create the component.
738
778
 
739
779
  Args:
@@ -765,7 +805,7 @@ class Component(BaseComponent, ABC):
765
805
  # Validate all the children.
766
806
  validate_children(children)
767
807
 
768
- children = [
808
+ children_normalized = [
769
809
  (
770
810
  child
771
811
  if isinstance(child, Component)
@@ -778,7 +818,40 @@ class Component(BaseComponent, ABC):
778
818
  for child in children
779
819
  ]
780
820
 
781
- return cls(children=children, **props)
821
+ return cls._create(children_normalized, **props)
822
+
823
+ @classmethod
824
+ def _create(cls: Type[T], children: Sequence[BaseComponent], **props: Any) -> T:
825
+ """Create the component.
826
+
827
+ Args:
828
+ children: The children of the component.
829
+ **props: The props of the component.
830
+
831
+ Returns:
832
+ The component.
833
+ """
834
+ comp = cls.construct(id=props.get("id"), children=list(children))
835
+ comp._post_init(children=list(children), **props)
836
+ return comp
837
+
838
+ @classmethod
839
+ def _unsafe_create(
840
+ cls: Type[T], children: Sequence[BaseComponent], **props: Any
841
+ ) -> T:
842
+ """Create the component without running post_init.
843
+
844
+ Args:
845
+ children: The children of the component.
846
+ **props: The props of the component.
847
+
848
+ Returns:
849
+ The component.
850
+ """
851
+ comp = cls.construct(id=props.get("id"), children=list(children))
852
+ for prop, value in props.items():
853
+ setattr(comp, prop, value)
854
+ return comp
782
855
 
783
856
  def add_style(self) -> dict[str, Any] | None:
784
857
  """Add style to the component.
@@ -829,7 +902,7 @@ class Component(BaseComponent, ABC):
829
902
  return component_style
830
903
 
831
904
  def _add_style_recursive(
832
- self, style: ComponentStyle, theme: Optional[Component] = None
905
+ self, style: ComponentStyle, theme: Component | None = None
833
906
  ) -> Component:
834
907
  """Add additional style to the component and its children.
835
908
 
@@ -928,7 +1001,7 @@ class Component(BaseComponent, ABC):
928
1001
  if prop.startswith(old_prop):
929
1002
  rendered_dict["props"][ix] = prop.replace(old_prop, new_prop, 1)
930
1003
 
931
- def _validate_component_children(self, children: List[Component]):
1004
+ def _validate_component_children(self, children: list[Component]):
932
1005
  """Validate the children components.
933
1006
 
934
1007
  Args:
@@ -962,8 +1035,8 @@ class Component(BaseComponent, ABC):
962
1035
  validate_child(c)
963
1036
 
964
1037
  if isinstance(child, Cond):
965
- validate_child(child.comp1)
966
- validate_child(child.comp2)
1038
+ validate_child(child.children[0])
1039
+ validate_child(child.children[1])
967
1040
 
968
1041
  if isinstance(child, Match):
969
1042
  for cases in child.match_cases:
@@ -1038,7 +1111,7 @@ class Component(BaseComponent, ABC):
1038
1111
  Each var referenced by the component (props, styles, event handlers).
1039
1112
  """
1040
1113
  ignore_ids = ignore_ids or set()
1041
- vars: List[Var] | None = getattr(self, "__vars", None)
1114
+ vars: list[Var] | None = getattr(self, "__vars", None)
1042
1115
  if vars is not None:
1043
1116
  yield from vars
1044
1117
  vars = self.__vars = []
@@ -1211,7 +1284,7 @@ class Component(BaseComponent, ABC):
1211
1284
  """
1212
1285
  return None
1213
1286
 
1214
- def _get_all_dynamic_imports(self) -> Set[str]:
1287
+ def _get_all_dynamic_imports(self) -> set[str]:
1215
1288
  """Get dynamic imports for the component and its children.
1216
1289
 
1217
1290
  Returns:
@@ -1578,7 +1651,7 @@ class Component(BaseComponent, ABC):
1578
1651
 
1579
1652
  def _get_all_custom_components(
1580
1653
  self, seen: set[str] | None = None
1581
- ) -> Set[CustomComponent]:
1654
+ ) -> set[CustomComponent]:
1582
1655
  """Get all the custom components used by the component.
1583
1656
 
1584
1657
  Args:
@@ -1661,9 +1734,9 @@ class CustomComponent(Component):
1661
1734
  component_fn: Callable[..., Component] = Component.create
1662
1735
 
1663
1736
  # The props of the component.
1664
- props: Dict[str, Any] = {}
1737
+ props: dict[str, Any] = {}
1665
1738
 
1666
- def __init__(self, **kwargs):
1739
+ def _post_init(self, **kwargs):
1667
1740
  """Initialize the custom component.
1668
1741
 
1669
1742
  Args:
@@ -1706,7 +1779,7 @@ class CustomComponent(Component):
1706
1779
  )
1707
1780
  )
1708
1781
 
1709
- super().__init__(
1782
+ super()._post_init(
1710
1783
  event_triggers={
1711
1784
  key: EventChain.create(
1712
1785
  value=props[key],
@@ -1740,7 +1813,7 @@ class CustomComponent(Component):
1740
1813
  type_ = props_types[key]
1741
1814
 
1742
1815
  # Handle event chains.
1743
- if types._issubclass(type_, EventActionsMixin):
1816
+ if type_ is EventHandler:
1744
1817
  inspect.getfullargspec(component_fn).annotations[key]
1745
1818
  self.props[camel_cased_key] = EventChain.create(
1746
1819
  value=value, args_spec=get_args_spec(key), key=key
@@ -1780,7 +1853,7 @@ class CustomComponent(Component):
1780
1853
  return hash(self.tag)
1781
1854
 
1782
1855
  @classmethod
1783
- def get_props(cls) -> Set[str]:
1856
+ def get_props(cls) -> set[str]:
1784
1857
  """Get the props for the component.
1785
1858
 
1786
1859
  Returns:
@@ -1790,7 +1863,7 @@ class CustomComponent(Component):
1790
1863
 
1791
1864
  def _get_all_custom_components(
1792
1865
  self, seen: set[str] | None = None
1793
- ) -> Set[CustomComponent]:
1866
+ ) -> set[CustomComponent]:
1794
1867
  """Get all the custom components used by the component.
1795
1868
 
1796
1869
  Args:
@@ -1867,7 +1940,9 @@ def custom_component(
1867
1940
  def wrapper(*children, **props) -> CustomComponent:
1868
1941
  # Remove the children from the props.
1869
1942
  props.pop("children", None)
1870
- return CustomComponent(component_fn=component_fn, children=children, **props)
1943
+ return CustomComponent._create(
1944
+ children=list(children), component_fn=component_fn, **props
1945
+ )
1871
1946
 
1872
1947
  return wrapper
1873
1948
 
@@ -1942,7 +2017,7 @@ class StatefulComponent(BaseComponent):
1942
2017
  """
1943
2018
 
1944
2019
  # A lookup table to caching memoized component instances.
1945
- tag_to_stateful_component: ClassVar[Dict[str, StatefulComponent]] = {}
2020
+ tag_to_stateful_component: ClassVar[dict[str, StatefulComponent]] = {}
1946
2021
 
1947
2022
  # Reference to the original component that was memoized into this component.
1948
2023
  component: Component
@@ -2,6 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import dataclasses
6
+
5
7
  from reflex.components.el.elements.typography import Div
6
8
  from reflex.constants.compiler import MemoizationDisposition, MemoizationMode
7
9
  from reflex.utils.imports import ImportDict
@@ -28,7 +30,12 @@ class AutoScroll(Div):
28
30
  """
29
31
  props.setdefault("overflow", "auto")
30
32
  props.setdefault("id", get_unique_variable_name())
31
- return super().create(*children, **props)
33
+ component = super().create(*children, **props)
34
+ if "key" in props:
35
+ component._memoization_mode = dataclasses.replace(
36
+ component._memoization_mode, recursive=True
37
+ )
38
+ return component
32
39
 
33
40
  def add_imports(self) -> ImportDict | list[ImportDict]:
34
41
  """Add imports required for the component.