reflex 0.7.13a1__py3-none-any.whl → 0.7.14__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 (263) hide show
  1. reflex/.templates/apps/blank/code/blank.py +0 -2
  2. reflex/app.py +100 -92
  3. reflex/app_mixins/lifespan.py +2 -3
  4. reflex/app_mixins/middleware.py +1 -0
  5. reflex/app_mixins/mixin.py +0 -1
  6. reflex/assets.py +7 -4
  7. reflex/base.py +3 -2
  8. reflex/compiler/compiler.py +79 -65
  9. reflex/compiler/utils.py +8 -6
  10. reflex/components/base/app_wrap.pyi +0 -1
  11. reflex/components/base/bare.py +22 -12
  12. reflex/components/base/body.pyi +0 -1
  13. reflex/components/base/document.pyi +0 -5
  14. reflex/components/base/error_boundary.pyi +0 -1
  15. reflex/components/base/fragment.pyi +0 -1
  16. reflex/components/base/head.pyi +0 -2
  17. reflex/components/base/link.pyi +0 -2
  18. reflex/components/base/meta.py +2 -1
  19. reflex/components/base/meta.pyi +0 -4
  20. reflex/components/base/script.py +2 -1
  21. reflex/components/base/script.pyi +0 -1
  22. reflex/components/base/strict_mode.pyi +0 -1
  23. reflex/components/component.py +85 -45
  24. reflex/components/core/auto_scroll.pyi +0 -1
  25. reflex/components/core/banner.py +1 -1
  26. reflex/components/core/banner.pyi +0 -6
  27. reflex/components/core/breakpoints.py +9 -11
  28. reflex/components/core/client_side_routing.pyi +0 -2
  29. reflex/components/core/clipboard.pyi +0 -1
  30. reflex/components/core/colors.py +10 -7
  31. reflex/components/core/cond.py +4 -2
  32. reflex/components/core/debounce.py +5 -3
  33. reflex/components/core/debounce.pyi +0 -1
  34. reflex/components/core/foreach.py +8 -6
  35. reflex/components/core/html.py +3 -3
  36. reflex/components/core/html.pyi +0 -1
  37. reflex/components/core/match.py +19 -17
  38. reflex/components/core/sticky.pyi +0 -4
  39. reflex/components/core/upload.py +1 -1
  40. reflex/components/core/upload.pyi +0 -5
  41. reflex/components/datadisplay/code.py +1 -2
  42. reflex/components/datadisplay/code.pyi +0 -2
  43. reflex/components/datadisplay/dataeditor.py +7 -10
  44. reflex/components/datadisplay/dataeditor.pyi +0 -1
  45. reflex/components/datadisplay/logo.py +3 -4
  46. reflex/components/datadisplay/shiki_code_block.py +8 -11
  47. reflex/components/datadisplay/shiki_code_block.pyi +0 -3
  48. reflex/components/dynamic.py +2 -3
  49. reflex/components/el/__init__.pyi +2 -0
  50. reflex/components/el/element.pyi +0 -1
  51. reflex/components/el/elements/__init__.py +1 -0
  52. reflex/components/el/elements/__init__.pyi +3 -0
  53. reflex/components/el/elements/base.pyi +0 -1
  54. reflex/components/el/elements/forms.py +14 -15
  55. reflex/components/el/elements/forms.pyi +15 -32
  56. reflex/components/el/elements/inline.pyi +0 -28
  57. reflex/components/el/elements/media.py +26 -0
  58. reflex/components/el/elements/media.pyi +259 -25
  59. reflex/components/el/elements/metadata.py +0 -1
  60. reflex/components/el/elements/metadata.pyi +0 -6
  61. reflex/components/el/elements/other.pyi +0 -7
  62. reflex/components/el/elements/scripts.pyi +0 -3
  63. reflex/components/el/elements/sectioning.pyi +0 -15
  64. reflex/components/el/elements/tables.pyi +0 -10
  65. reflex/components/el/elements/typography.pyi +0 -15
  66. reflex/components/gridjs/datatable.py +10 -13
  67. reflex/components/gridjs/datatable.pyi +0 -2
  68. reflex/components/lucide/icon.py +10 -9
  69. reflex/components/lucide/icon.pyi +0 -3
  70. reflex/components/markdown/markdown.py +6 -8
  71. reflex/components/markdown/markdown.pyi +0 -1
  72. reflex/components/moment/moment.pyi +0 -1
  73. reflex/components/next/base.py +0 -2
  74. reflex/components/next/base.pyi +0 -3
  75. reflex/components/next/image.pyi +0 -1
  76. reflex/components/next/link.pyi +0 -1
  77. reflex/components/next/video.pyi +0 -1
  78. reflex/components/plotly/plotly.pyi +0 -9
  79. reflex/components/props.py +4 -3
  80. reflex/components/radix/primitives/accordion.py +1 -1
  81. reflex/components/radix/primitives/accordion.pyi +0 -7
  82. reflex/components/radix/primitives/base.py +1 -3
  83. reflex/components/radix/primitives/base.pyi +0 -2
  84. reflex/components/radix/primitives/drawer.py +1 -1
  85. reflex/components/radix/primitives/drawer.pyi +0 -11
  86. reflex/components/radix/primitives/form.py +5 -9
  87. reflex/components/radix/primitives/form.pyi +0 -12
  88. reflex/components/radix/primitives/progress.py +1 -1
  89. reflex/components/radix/primitives/progress.pyi +0 -5
  90. reflex/components/radix/primitives/slider.py +1 -1
  91. reflex/components/radix/primitives/slider.pyi +0 -5
  92. reflex/components/radix/themes/base.pyi +0 -8
  93. reflex/components/radix/themes/color_mode.pyi +0 -3
  94. reflex/components/radix/themes/components/alert_dialog.py +4 -2
  95. reflex/components/radix/themes/components/alert_dialog.pyi +4 -9
  96. reflex/components/radix/themes/components/aspect_ratio.py +1 -2
  97. reflex/components/radix/themes/components/aspect_ratio.pyi +1 -3
  98. reflex/components/radix/themes/components/avatar.py +5 -2
  99. reflex/components/radix/themes/components/avatar.pyi +1 -3
  100. reflex/components/radix/themes/components/badge.py +5 -2
  101. reflex/components/radix/themes/components/badge.pyi +1 -3
  102. reflex/components/radix/themes/components/button.py +2 -3
  103. reflex/components/radix/themes/components/button.pyi +1 -3
  104. reflex/components/radix/themes/components/callout.py +1 -2
  105. reflex/components/radix/themes/components/callout.pyi +1 -7
  106. reflex/components/radix/themes/components/card.py +1 -2
  107. reflex/components/radix/themes/components/card.pyi +1 -3
  108. reflex/components/radix/themes/components/checkbox.py +7 -4
  109. reflex/components/radix/themes/components/checkbox.pyi +1 -5
  110. reflex/components/radix/themes/components/checkbox_cards.py +1 -2
  111. reflex/components/radix/themes/components/checkbox_cards.pyi +1 -4
  112. reflex/components/radix/themes/components/checkbox_group.py +1 -2
  113. reflex/components/radix/themes/components/checkbox_group.pyi +1 -4
  114. reflex/components/radix/themes/components/context_menu.py +1 -1
  115. reflex/components/radix/themes/components/context_menu.pyi +1 -14
  116. reflex/components/radix/themes/components/data_list.py +1 -2
  117. reflex/components/radix/themes/components/data_list.pyi +1 -6
  118. reflex/components/radix/themes/components/dialog.py +4 -2
  119. reflex/components/radix/themes/components/dialog.pyi +4 -9
  120. reflex/components/radix/themes/components/dropdown_menu.py +5 -2
  121. reflex/components/radix/themes/components/dropdown_menu.pyi +4 -10
  122. reflex/components/radix/themes/components/hover_card.py +4 -2
  123. reflex/components/radix/themes/components/hover_card.pyi +4 -6
  124. reflex/components/radix/themes/components/icon_button.py +7 -8
  125. reflex/components/radix/themes/components/icon_button.pyi +1 -3
  126. reflex/components/radix/themes/components/inset.py +1 -2
  127. reflex/components/radix/themes/components/inset.pyi +1 -3
  128. reflex/components/radix/themes/components/popover.py +4 -2
  129. reflex/components/radix/themes/components/popover.pyi +4 -6
  130. reflex/components/radix/themes/components/progress.py +1 -2
  131. reflex/components/radix/themes/components/progress.pyi +1 -3
  132. reflex/components/radix/themes/components/radio.py +1 -2
  133. reflex/components/radix/themes/components/radio.pyi +1 -3
  134. reflex/components/radix/themes/components/radio_cards.py +1 -2
  135. reflex/components/radix/themes/components/radio_cards.pyi +1 -4
  136. reflex/components/radix/themes/components/radio_group.py +7 -5
  137. reflex/components/radix/themes/components/radio_group.pyi +1 -6
  138. reflex/components/radix/themes/components/scroll_area.py +1 -2
  139. reflex/components/radix/themes/components/scroll_area.pyi +1 -3
  140. reflex/components/radix/themes/components/segmented_control.py +1 -2
  141. reflex/components/radix/themes/components/segmented_control.pyi +1 -4
  142. reflex/components/radix/themes/components/select.py +5 -2
  143. reflex/components/radix/themes/components/select.pyi +1 -11
  144. reflex/components/radix/themes/components/separator.py +1 -2
  145. reflex/components/radix/themes/components/separator.pyi +1 -3
  146. reflex/components/radix/themes/components/skeleton.py +1 -2
  147. reflex/components/radix/themes/components/skeleton.pyi +1 -3
  148. reflex/components/radix/themes/components/slider.py +1 -2
  149. reflex/components/radix/themes/components/slider.pyi +1 -3
  150. reflex/components/radix/themes/components/spinner.py +1 -2
  151. reflex/components/radix/themes/components/spinner.pyi +1 -3
  152. reflex/components/radix/themes/components/switch.py +1 -2
  153. reflex/components/radix/themes/components/switch.pyi +1 -3
  154. reflex/components/radix/themes/components/table.py +1 -2
  155. reflex/components/radix/themes/components/table.pyi +1 -9
  156. reflex/components/radix/themes/components/tabs.py +1 -2
  157. reflex/components/radix/themes/components/tabs.pyi +1 -7
  158. reflex/components/radix/themes/components/text_area.py +5 -2
  159. reflex/components/radix/themes/components/text_area.pyi +2 -4
  160. reflex/components/radix/themes/components/text_field.py +5 -2
  161. reflex/components/radix/themes/components/text_field.pyi +1 -5
  162. reflex/components/radix/themes/components/tooltip.py +1 -2
  163. reflex/components/radix/themes/components/tooltip.pyi +1 -3
  164. reflex/components/radix/themes/layout/base.py +5 -2
  165. reflex/components/radix/themes/layout/base.pyi +5 -3
  166. reflex/components/radix/themes/layout/box.py +1 -2
  167. reflex/components/radix/themes/layout/box.pyi +1 -3
  168. reflex/components/radix/themes/layout/center.pyi +0 -1
  169. reflex/components/radix/themes/layout/container.py +1 -2
  170. reflex/components/radix/themes/layout/container.pyi +1 -3
  171. reflex/components/radix/themes/layout/flex.py +6 -2
  172. reflex/components/radix/themes/layout/flex.pyi +1 -3
  173. reflex/components/radix/themes/layout/grid.py +6 -2
  174. reflex/components/radix/themes/layout/grid.pyi +1 -3
  175. reflex/components/radix/themes/layout/list.py +2 -1
  176. reflex/components/radix/themes/layout/list.pyi +0 -5
  177. reflex/components/radix/themes/layout/section.py +1 -2
  178. reflex/components/radix/themes/layout/section.pyi +1 -3
  179. reflex/components/radix/themes/layout/spacer.pyi +0 -1
  180. reflex/components/radix/themes/layout/stack.py +1 -1
  181. reflex/components/radix/themes/layout/stack.pyi +0 -3
  182. reflex/components/radix/themes/typography/blockquote.py +1 -1
  183. reflex/components/radix/themes/typography/blockquote.pyi +1 -3
  184. reflex/components/radix/themes/typography/code.py +5 -1
  185. reflex/components/radix/themes/typography/code.pyi +1 -3
  186. reflex/components/radix/themes/typography/heading.py +1 -1
  187. reflex/components/radix/themes/typography/heading.pyi +1 -3
  188. reflex/components/radix/themes/typography/link.py +3 -2
  189. reflex/components/radix/themes/typography/link.pyi +1 -3
  190. reflex/components/radix/themes/typography/text.py +1 -1
  191. reflex/components/radix/themes/typography/text.pyi +1 -9
  192. reflex/components/react_player/audio.py +0 -2
  193. reflex/components/react_player/audio.pyi +0 -3
  194. reflex/components/react_player/react_player.pyi +0 -1
  195. reflex/components/react_player/video.py +0 -2
  196. reflex/components/react_player/video.pyi +0 -3
  197. reflex/components/recharts/__init__.py +1 -1
  198. reflex/components/recharts/__init__.pyi +1 -1
  199. reflex/components/recharts/cartesian.py +20 -25
  200. reflex/components/recharts/cartesian.pyi +20 -37
  201. reflex/components/recharts/charts.py +2 -1
  202. reflex/components/recharts/charts.pyi +0 -12
  203. reflex/components/recharts/general.pyi +0 -6
  204. reflex/components/recharts/polar.py +5 -4
  205. reflex/components/recharts/polar.pyi +4 -10
  206. reflex/components/recharts/recharts.py +12 -10
  207. reflex/components/recharts/recharts.pyi +10 -11
  208. reflex/components/sonner/toast.py +2 -2
  209. reflex/components/sonner/toast.pyi +0 -2
  210. reflex/components/suneditor/editor.py +2 -1
  211. reflex/components/suneditor/editor.pyi +0 -1
  212. reflex/components/tags/iter_tag.py +4 -2
  213. reflex/config.py +41 -615
  214. reflex/constants/base.py +6 -6
  215. reflex/constants/compiler.py +8 -6
  216. reflex/constants/installer.py +25 -16
  217. reflex/custom_components/custom_components.py +1 -2
  218. reflex/environment.py +606 -0
  219. reflex/event.py +58 -60
  220. reflex/experimental/__init__.py +2 -2
  221. reflex/experimental/client_state.py +9 -4
  222. reflex/experimental/layout.pyi +0 -5
  223. reflex/istate/manager.py +17 -20
  224. reflex/istate/proxy.py +19 -12
  225. reflex/model.py +8 -5
  226. reflex/plugins/base.py +8 -0
  227. reflex/plugins/tailwind_v3.py +8 -0
  228. reflex/plugins/tailwind_v4.py +9 -0
  229. reflex/reflex.py +11 -12
  230. reflex/route.py +7 -9
  231. reflex/state.py +67 -71
  232. reflex/style.py +3 -1
  233. reflex/testing.py +49 -30
  234. reflex/utils/build.py +2 -1
  235. reflex/utils/console.py +70 -17
  236. reflex/utils/exec.py +113 -39
  237. reflex/utils/export.py +2 -1
  238. reflex/utils/format.py +21 -24
  239. reflex/utils/imports.py +4 -3
  240. reflex/utils/lazy_loader.py +3 -3
  241. reflex/utils/misc.py +2 -1
  242. reflex/utils/net.py +2 -2
  243. reflex/utils/path_ops.py +4 -2
  244. reflex/utils/prerequisites.py +69 -39
  245. reflex/utils/processes.py +5 -7
  246. reflex/utils/pyi_generator.py +46 -41
  247. reflex/utils/redir.py +1 -1
  248. reflex/utils/registry.py +1 -1
  249. reflex/utils/serializers.py +4 -4
  250. reflex/utils/telemetry.py +36 -3
  251. reflex/utils/types.py +16 -13
  252. reflex/vars/base.py +96 -109
  253. reflex/vars/datetime.py +2 -1
  254. reflex/vars/dep_tracking.py +19 -28
  255. reflex/vars/number.py +6 -7
  256. reflex/vars/object.py +5 -6
  257. reflex/vars/sequence.py +11 -11
  258. {reflex-0.7.13a1.dist-info → reflex-0.7.14.dist-info}/METADATA +1 -1
  259. reflex-0.7.14.dist-info/RECORD +408 -0
  260. reflex-0.7.13a1.dist-info/RECORD +0 -407
  261. {reflex-0.7.13a1.dist-info → reflex-0.7.14.dist-info}/WHEEL +0 -0
  262. {reflex-0.7.13a1.dist-info → reflex-0.7.14.dist-info}/entry_points.txt +0 -0
  263. {reflex-0.7.13a1.dist-info → reflex-0.7.14.dist-info}/licenses/LICENSE +0 -0
@@ -157,7 +157,8 @@ class ComponentField(Generic[FIELD_TYPE]):
157
157
  return self.default
158
158
  if self.default_factory is not None:
159
159
  return self.default_factory()
160
- raise ValueError("No default value or factory provided.")
160
+ msg = "No default value or factory provided."
161
+ raise ValueError(msg)
161
162
 
162
163
  def __repr__(self) -> str:
163
164
  """Represent the field in a readable format.
@@ -194,7 +195,8 @@ def field(
194
195
  ValueError: If both default and default_factory are specified.
195
196
  """
196
197
  if default is not MISSING and default_factory is not None:
197
- raise ValueError("cannot specify both default and default_factory")
198
+ msg = "cannot specify both default and default_factory"
199
+ raise ValueError(msg)
198
200
  return ComponentField( # pyright: ignore [reportReturnType]
199
201
  default=default,
200
202
  default_factory=default_factory,
@@ -286,10 +288,11 @@ class BaseComponentMeta(ABCMeta):
286
288
 
287
289
  namespace["_own_fields"] = own_fields
288
290
  namespace["_inherited_fields"] = inherited_fields
289
- namespace["_fields"] = inherited_fields | own_fields
291
+ all_fields = inherited_fields | own_fields
292
+ namespace["_fields"] = all_fields
290
293
  namespace["_js_fields"] = {
291
294
  key: value
292
- for key, value in own_fields.items()
295
+ for key, value in all_fields.items()
293
296
  if value.is_javascript is True
294
297
  }
295
298
  return super().__new__(cls, name, bases, namespace)
@@ -769,11 +772,12 @@ class Component(BaseComponent, ABC):
769
772
  and key not in component_specific_triggers
770
773
  and key not in props
771
774
  ):
772
- raise ValueError(
775
+ msg = (
773
776
  f"The {(comp_name := type(self).__name__)} does not take in an `{key}` event trigger. If {comp_name}"
774
777
  f" is a third party component make sure to add `{key}` to the component's event triggers. "
775
778
  f"visit https://reflex.dev/docs/wrapping-react/guide/#event-triggers for more info."
776
779
  )
780
+ raise ValueError(msg)
777
781
  if key in component_specific_triggers:
778
782
  # Event triggers are bound to event chains.
779
783
  is_var = False
@@ -844,7 +848,8 @@ class Component(BaseComponent, ABC):
844
848
  style = kwargs.get("style", {})
845
849
  if isinstance(style, Sequence):
846
850
  if any(not isinstance(s, Mapping) for s in style):
847
- raise TypeError("Style must be a dictionary or a list of dictionaries.")
851
+ msg = "Style must be a dictionary or a list of dictionaries."
852
+ raise TypeError(msg)
848
853
  # Merge styles, the later ones overriding keys in the earlier ones.
849
854
  style = {
850
855
  k: v
@@ -879,14 +884,12 @@ class Component(BaseComponent, ABC):
879
884
  if not isinstance(c, StringVar) and not issubclass(
880
885
  c._var_type, str
881
886
  ):
882
- raise TypeError(
883
- f"Invalid class_name passed for prop {type(self).__name__}.class_name, expected type str, got value {c._js_expr} of type {c._var_type}."
884
- )
887
+ msg = f"Invalid class_name passed for prop {type(self).__name__}.class_name, expected type str, got value {c._js_expr} of type {c._var_type}."
888
+ raise TypeError(msg)
885
889
  has_var = True
886
890
  else:
887
- raise TypeError(
888
- f"Invalid class_name passed for prop {type(self).__name__}.class_name, expected type str, got value {c} of type {type(c)}."
889
- )
891
+ msg = f"Invalid class_name passed for prop {type(self).__name__}.class_name, expected type str, got value {c} of type {type(c)}."
892
+ raise TypeError(msg)
890
893
  if has_var:
891
894
  kwargs["class_name"] = LiteralArrayVar.create(
892
895
  class_name, _var_type=list[str]
@@ -898,9 +901,8 @@ class Component(BaseComponent, ABC):
898
901
  and not isinstance(class_name, StringVar)
899
902
  and not issubclass(class_name._var_type, str)
900
903
  ):
901
- raise TypeError(
902
- f"Invalid class_name passed for prop {type(self).__name__}.class_name, expected type str, got value {class_name._js_expr} of type {class_name._var_type}."
903
- )
904
+ msg = f"Invalid class_name passed for prop {type(self).__name__}.class_name, expected type str, got value {class_name._js_expr} of type {class_name._var_type}."
905
+ raise TypeError(msg)
904
906
  # Construct the component.
905
907
  for key, value in kwargs.items():
906
908
  setattr(self, key, value)
@@ -1015,7 +1017,7 @@ class Component(BaseComponent, ABC):
1015
1017
  Returns:
1016
1018
  The unique fields.
1017
1019
  """
1018
- return set(cls.get_fields()) - set(Component.get_fields())
1020
+ return set(cls.get_js_fields())
1019
1021
 
1020
1022
  @classmethod
1021
1023
  @functools.cache
@@ -1227,9 +1229,8 @@ class Component(BaseComponent, ABC):
1227
1229
  """
1228
1230
  # 1. Default style from `_add_style`/`add_style`.
1229
1231
  if type(self)._add_style != Component._add_style:
1230
- raise UserWarning(
1231
- "Do not override _add_style directly. Use add_style instead."
1232
- )
1232
+ msg = "Do not override _add_style directly. Use add_style instead."
1233
+ raise UserWarning(msg)
1233
1234
  new_style = self._add_style()
1234
1235
  style_vars = [new_style._var_data]
1235
1236
 
@@ -1347,9 +1348,8 @@ class Component(BaseComponent, ABC):
1347
1348
  validate_child(child.default)
1348
1349
 
1349
1350
  if self._invalid_children and child_name in self._invalid_children:
1350
- raise ValueError(
1351
- f"The component `{comp_name}` cannot have `{child_name}` as a child component"
1352
- )
1351
+ msg = f"The component `{comp_name}` cannot have `{child_name}` as a child component"
1352
+ raise ValueError(msg)
1353
1353
 
1354
1354
  if self._valid_children and child_name not in [
1355
1355
  *self._valid_children,
@@ -1358,9 +1358,8 @@ class Component(BaseComponent, ABC):
1358
1358
  valid_child_list = ", ".join(
1359
1359
  [f"`{v_child}`" for v_child in self._valid_children]
1360
1360
  )
1361
- raise ValueError(
1362
- f"The component `{comp_name}` only allows the components: {valid_child_list} as children. Got `{child_name}` instead."
1363
- )
1361
+ msg = f"The component `{comp_name}` only allows the components: {valid_child_list} as children. Got `{child_name}` instead."
1362
+ raise ValueError(msg)
1364
1363
 
1365
1364
  if child._valid_parents and all(
1366
1365
  clz_name not in [*child._valid_parents, *allowed_components]
@@ -1369,9 +1368,8 @@ class Component(BaseComponent, ABC):
1369
1368
  valid_parent_list = ", ".join(
1370
1369
  [f"`{v_parent}`" for v_parent in child._valid_parents]
1371
1370
  )
1372
- raise ValueError(
1373
- f"The component `{child_name}` can only be a child of the components: {valid_parent_list}. Got `{comp_name}` instead."
1374
- )
1371
+ msg = f"The component `{child_name}` can only be a child of the components: {valid_parent_list}. Got `{comp_name}` instead."
1372
+ raise ValueError(msg)
1375
1373
 
1376
1374
  for child in children:
1377
1375
  validate_child(child)
@@ -1502,13 +1500,9 @@ class Component(BaseComponent, ABC):
1502
1500
  """
1503
1501
  if self.event_triggers and self._event_trigger_values_use_state():
1504
1502
  return True
1505
- else:
1506
- for child in self.children:
1507
- if (
1508
- isinstance(child, Component)
1509
- and child._has_stateful_event_triggers()
1510
- ):
1511
- return True
1503
+ for child in self.children:
1504
+ if isinstance(child, Component) and child._has_stateful_event_triggers():
1505
+ return True
1512
1506
  return False
1513
1507
 
1514
1508
  @classmethod
@@ -1767,6 +1761,7 @@ class Component(BaseComponent, ABC):
1767
1761
  {on_unmount or ""}
1768
1762
  }}
1769
1763
  }}, []);"""
1764
+ return None
1770
1765
 
1771
1766
  def _get_ref_hook(self) -> Var | None:
1772
1767
  """Generate the ref hook for the component.
@@ -1780,6 +1775,7 @@ class Component(BaseComponent, ABC):
1780
1775
  f"const {ref} = useRef(null); {Var(_js_expr=ref)._as_ref()!s} = {ref};",
1781
1776
  _var_data=VarData(position=Hooks.HookPosition.INTERNAL),
1782
1777
  )
1778
+ return None
1783
1779
 
1784
1780
  def _get_vars_hooks(self) -> dict[str, VarData | None]:
1785
1781
  """Get the hooks required by vars referenced in this component.
@@ -1980,24 +1976,38 @@ class Component(BaseComponent, ABC):
1980
1976
  """
1981
1977
  return {}
1982
1978
 
1983
- def _get_all_app_wrap_components(self) -> dict[tuple[int, str], Component]:
1979
+ def _get_all_app_wrap_components(
1980
+ self, *, ignore_ids: set[int] | None = None
1981
+ ) -> dict[tuple[int, str], Component]:
1984
1982
  """Get the app wrap components for the component and its children.
1985
1983
 
1984
+ Args:
1985
+ ignore_ids: A set of component IDs to ignore. Used to avoid duplicates.
1986
+
1986
1987
  Returns:
1987
1988
  The app wrap components.
1988
1989
  """
1990
+ ignore_ids = ignore_ids or set()
1989
1991
  # Store the components in a set to avoid duplicates.
1990
1992
  components = self._get_app_wrap_components()
1991
1993
 
1992
1994
  for component in tuple(components.values()):
1993
- components.update(component._get_all_app_wrap_components())
1995
+ component_id = id(component)
1996
+ if component_id in ignore_ids:
1997
+ continue
1998
+ ignore_ids.add(component_id)
1999
+ components.update(
2000
+ component._get_all_app_wrap_components(ignore_ids=ignore_ids)
2001
+ )
1994
2002
 
1995
2003
  # Add the app wrap components for the children.
1996
2004
  for child in self.children:
2005
+ child_id = id(child)
1997
2006
  # Skip BaseComponent and StatefulComponent children.
1998
- if not isinstance(child, Component):
2007
+ if not isinstance(child, Component) or child_id in ignore_ids:
1999
2008
  continue
2000
- components.update(child._get_all_app_wrap_components())
2009
+ ignore_ids.add(child_id)
2010
+ components.update(child._get_all_app_wrap_components(ignore_ids=ignore_ids))
2001
2011
 
2002
2012
  # Return the components.
2003
2013
  return components
@@ -2198,7 +2208,35 @@ class CustomComponent(Component):
2198
2208
  Returns:
2199
2209
  The code to render the component.
2200
2210
  """
2201
- return self.component_fn(*self.get_prop_vars())
2211
+ component = self.component_fn(*self.get_prop_vars())
2212
+
2213
+ try:
2214
+ from reflex.utils.prerequisites import get_and_validate_app
2215
+
2216
+ style = get_and_validate_app().app.style
2217
+ except Exception:
2218
+ style = {}
2219
+
2220
+ component._add_style_recursive(style)
2221
+ return component
2222
+
2223
+ def _get_all_app_wrap_components(
2224
+ self, *, ignore_ids: set[int] | None = None
2225
+ ) -> dict[tuple[int, str], Component]:
2226
+ """Get the app wrap components for the custom component.
2227
+
2228
+ Args:
2229
+ ignore_ids: A set of IDs to ignore to avoid infinite recursion.
2230
+
2231
+ Returns:
2232
+ The app wrap components.
2233
+ """
2234
+ ignore_ids = ignore_ids or set()
2235
+ component = self.get_component()
2236
+ if id(component) in ignore_ids:
2237
+ return {}
2238
+ ignore_ids.add(id(component))
2239
+ return self.get_component()._get_all_app_wrap_components(ignore_ids=ignore_ids)
2202
2240
 
2203
2241
 
2204
2242
  CUSTOM_COMPONENTS: dict[str, CustomComponent] = {}
@@ -2222,7 +2260,7 @@ def _register_custom_component(
2222
2260
  _var_type=unwrap_var_annotation(annotation),
2223
2261
  ).guess_type()
2224
2262
  if not types.safe_issubclass(annotation, EventHandler)
2225
- else EventSpec(handler=EventHandler(fn=lambda: []))
2263
+ else EventSpec(handler=EventHandler(fn=no_args_event_spec))
2226
2264
  )
2227
2265
  for prop, annotation in typing.get_type_hints(component_fn).items()
2228
2266
  if prop != "return"
@@ -2233,7 +2271,8 @@ def _register_custom_component(
2233
2271
  **dummy_props,
2234
2272
  )
2235
2273
  if dummy_component.tag is None:
2236
- raise TypeError(f"Could not determine the tag name for {component_fn!r}")
2274
+ msg = f"Could not determine the tag name for {component_fn!r}"
2275
+ raise TypeError(msg)
2237
2276
  CUSTOM_COMPONENTS[dummy_component.tag] = dummy_component
2238
2277
 
2239
2278
 
@@ -2312,7 +2351,8 @@ class NoSSRComponent(Component):
2312
2351
  # extract the correct import name from library name
2313
2352
  base_import_name = self._get_import_name()
2314
2353
  if base_import_name is None:
2315
- raise ValueError("Undefined library for NoSSRComponent")
2354
+ msg = "Undefined library for NoSSRComponent"
2355
+ raise ValueError(msg)
2316
2356
  import_name = format.format_library_name(base_import_name)
2317
2357
 
2318
2358
  library_import = f"const {self.alias if self.alias else self.tag} = dynamic(() => import('{import_name}')"
@@ -2320,7 +2360,7 @@ class NoSSRComponent(Component):
2320
2360
  # https://nextjs.org/docs/pages/building-your-application/optimizing/lazy-loading#with-named-exports
2321
2361
  f".then((mod) => mod.{self.tag})" if not self.is_default else ""
2322
2362
  )
2323
- return "".join((library_import, mod_import, opts_fragment))
2363
+ return library_import + mod_import + opts_fragment
2324
2364
 
2325
2365
 
2326
2366
  class StatefulComponent(BaseComponent):
@@ -2540,7 +2580,7 @@ class StatefulComponent(BaseComponent):
2540
2580
  var_name = var_name.strip()
2541
2581
 
2542
2582
  # Break up array and object destructuring if used.
2543
- if var_name.startswith("[") or var_name.startswith("{"):
2583
+ if var_name.startswith(("[", "{")):
2544
2584
  return [
2545
2585
  v.strip().replace("...", "") for v in var_name.strip("[]{}").split(",")
2546
2586
  ]
@@ -256,7 +256,6 @@ class AutoScroll(Div):
256
256
  Returns:
257
257
  An AutoScroll component.
258
258
  """
259
- ...
260
259
 
261
260
  def add_imports(self) -> ImportDict | list[ImportDict]: ...
262
261
  def add_hooks(self) -> list[str | Var]: ...
@@ -16,9 +16,9 @@ from reflex.components.radix.themes.components.dialog import (
16
16
  from reflex.components.radix.themes.layout.flex import Flex
17
17
  from reflex.components.radix.themes.typography.text import Text
18
18
  from reflex.components.sonner.toast import ToastProps, toast_ref
19
- from reflex.config import environment
20
19
  from reflex.constants import Dirs, Hooks, Imports
21
20
  from reflex.constants.compiler import CompileVars
21
+ from reflex.environment import environment
22
22
  from reflex.utils.imports import ImportVar
23
23
  from reflex.vars import VarData
24
24
  from reflex.vars.base import LiteralVar, Var
@@ -93,7 +93,6 @@ class ConnectionToaster(Fragment):
93
93
  Returns:
94
94
  The connection toaster component.
95
95
  """
96
- ...
97
96
 
98
97
  class ConnectionBanner(Component):
99
98
  @overload
@@ -137,7 +136,6 @@ class ConnectionBanner(Component):
137
136
  Returns:
138
137
  The connection banner component.
139
138
  """
140
- ...
141
139
 
142
140
  class ConnectionModal(Component):
143
141
  @overload
@@ -181,7 +179,6 @@ class ConnectionModal(Component):
181
179
  Returns:
182
180
  The connection banner component.
183
181
  """
184
- ...
185
182
 
186
183
  class WifiOffPulse(Icon):
187
184
  @overload
@@ -235,7 +232,6 @@ class WifiOffPulse(Icon):
235
232
  Returns:
236
233
  The icon component with default props applied.
237
234
  """
238
- ...
239
235
 
240
236
  def add_imports(self) -> dict[str, str | ImportVar | list[str | ImportVar]]: ...
241
237
 
@@ -482,7 +478,6 @@ class ConnectionPulser(Div):
482
478
  Returns:
483
479
  The connection pulser component.
484
480
  """
485
- ...
486
481
 
487
482
  class BackendDisabled(Div):
488
483
  @overload
@@ -727,7 +722,6 @@ class BackendDisabled(Div):
727
722
  Returns:
728
723
  The backend disabled component.
729
724
  """
730
- ...
731
725
 
732
726
  connection_banner = ConnectionBanner.create
733
727
  connection_modal = ConnectionModal.create
@@ -75,19 +75,17 @@ class Breakpoints(dict[K, V]):
75
75
 
76
76
  if custom is not None:
77
77
  if any(threshold is not None for threshold in thresholds):
78
- raise ValueError("Named props cannot be used with custom thresholds")
78
+ msg = "Named props cannot be used with custom thresholds"
79
+ raise ValueError(msg)
79
80
 
80
81
  return Breakpoints(custom)
81
- else:
82
- return Breakpoints(
83
- {
84
- k: v
85
- for k, v in zip(
86
- ["initial", *breakpoint_names], thresholds, strict=True
87
- )
88
- if v is not None
89
- }
90
- )
82
+ return Breakpoints(
83
+ {
84
+ k: v
85
+ for k, v in zip(["initial", *breakpoint_names], thresholds, strict=True)
86
+ if v is not None
87
+ }
88
+ )
91
89
 
92
90
 
93
91
  breakpoints = Breakpoints.create
@@ -65,7 +65,6 @@ class ClientSideRouting(Component):
65
65
  Returns:
66
66
  The component.
67
67
  """
68
- ...
69
68
 
70
69
  def wait_for_client_redirect(component: Component) -> Component: ...
71
70
 
@@ -120,4 +119,3 @@ class Default404Page(Component):
120
119
  Returns:
121
120
  The component.
122
121
  """
123
- ...
@@ -70,7 +70,6 @@ class Clipboard(Fragment):
70
70
  Returns:
71
71
  The Clipboard Component.
72
72
  """
73
- ...
74
73
 
75
74
  def add_imports(self) -> dict[str, ImportVar]: ...
76
75
  def add_hooks(self) -> list[str | Var[str]]: ...
@@ -32,19 +32,22 @@ def color(
32
32
  """
33
33
  if isinstance(color, str):
34
34
  if color not in COLORS and REFLEX_VAR_OPENING_TAG not in color:
35
- raise ValueError(f"Color must be one of {COLORS}, received {color}")
35
+ msg = f"Color must be one of {COLORS}, received {color}"
36
+ raise ValueError(msg)
36
37
  elif not isinstance(color, Var):
37
- raise ValueError("Color must be a string or a Var")
38
+ msg = "Color must be a string or a Var"
39
+ raise ValueError(msg)
38
40
 
39
41
  if isinstance(shade, int):
40
42
  if shade < MIN_SHADE_VALUE or shade > MAX_SHADE_VALUE:
41
- raise ValueError(
42
- f"Shade must be between {MIN_SHADE_VALUE} and {MAX_SHADE_VALUE}"
43
- )
43
+ msg = f"Shade must be between {MIN_SHADE_VALUE} and {MAX_SHADE_VALUE}"
44
+ raise ValueError(msg)
44
45
  elif not isinstance(shade, Var):
45
- raise ValueError("Shade must be an integer or a Var")
46
+ msg = "Shade must be an integer or a Var"
47
+ raise ValueError(msg)
46
48
 
47
49
  if not isinstance(alpha, (bool, Var)):
48
- raise ValueError("Alpha must be a boolean or a Var")
50
+ msg = "Alpha must be a boolean or a Var"
51
+ raise ValueError(msg)
49
52
 
50
53
  return Color(color, shade, alpha)
@@ -132,7 +132,8 @@ def cond(condition: Any, c1: Any, c2: Any = types.Unset(), /) -> Component | Var
132
132
  # Convert the condition to a Var.
133
133
  cond_var = LiteralVar.create(condition)
134
134
  if cond_var is None:
135
- raise ValueError("The condition must be set.")
135
+ msg = "The condition must be set."
136
+ raise ValueError(msg)
136
137
 
137
138
  # If the first component is a component, create a Cond component.
138
139
  if isinstance(c1, BaseComponent):
@@ -145,7 +146,8 @@ def cond(condition: Any, c1: Any, c2: Any = types.Unset(), /) -> Component | Var
145
146
  if isinstance(c2, BaseComponent):
146
147
  return Cond.create(cond_var.bool(), Fragment.create(c1), c2)
147
148
  if isinstance(c2, types.Unset):
148
- raise ValueError("For conditional vars, the second argument must be set.")
149
+ msg = "For conditional vars, the second argument must be set."
150
+ raise ValueError(msg)
149
151
 
150
152
  # convert the truth and false cond parts into vars so the _var_data can be obtained.
151
153
  c1_var = Var.create(c1)
@@ -70,14 +70,16 @@ class DebounceInput(Component):
70
70
  ValueError: if the child element does not have an on_change handler.
71
71
  """
72
72
  if len(children) != 1:
73
- raise RuntimeError(
73
+ msg = (
74
74
  "Provide a single child for DebounceInput, such as rx.input() or "
75
- "rx.text_area()",
75
+ "rx.text_area()"
76
76
  )
77
+ raise RuntimeError(msg)
77
78
 
78
79
  child = children[0]
79
80
  if "on_change" not in child.event_triggers:
80
- raise ValueError("DebounceInput child requires an on_change handler")
81
+ msg = "DebounceInput child requires an on_change handler"
82
+ raise ValueError(msg)
81
83
 
82
84
  # Carry known props and event_triggers from the child.
83
85
  props_from_child = {
@@ -74,6 +74,5 @@ class DebounceInput(Component):
74
74
  RuntimeError: unless exactly one child element is provided.
75
75
  ValueError: if the child element does not have an on_change handler.
76
76
  """
77
- ...
78
77
 
79
78
  debounce_input = DebounceInput.create
@@ -69,19 +69,19 @@ class Foreach(Component):
69
69
  )
70
70
 
71
71
  if iterable._var_type == Any:
72
- raise ForeachVarError(
72
+ msg = (
73
73
  f"Could not foreach over var `{iterable!s}` of type Any. "
74
74
  "(If you are trying to foreach over a state var, add a type annotation to the var). "
75
75
  "See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
76
76
  )
77
+ raise ForeachVarError(msg)
77
78
 
78
79
  if (
79
80
  hasattr(render_fn, "__qualname__")
80
81
  and render_fn.__qualname__ == ComponentState.create.__qualname__
81
82
  ):
82
- raise TypeError(
83
- "Using a ComponentState as `render_fn` inside `rx.foreach` is not supported yet."
84
- )
83
+ msg = "Using a ComponentState as `render_fn` inside `rx.foreach` is not supported yet."
84
+ raise TypeError(msg)
85
85
 
86
86
  if isinstance(iterable, ObjectVar):
87
87
  iterable = iterable.entries()
@@ -90,10 +90,11 @@ class Foreach(Component):
90
90
  iterable = iterable.split()
91
91
 
92
92
  if not isinstance(iterable, ArrayVar):
93
- raise ForeachVarError(
93
+ msg = (
94
94
  f"Could not foreach over var `{iterable!s}` of type {iterable._var_type}. "
95
95
  "See https://reflex.dev/docs/library/dynamic-rendering/foreach/"
96
96
  )
97
+ raise ForeachVarError(msg)
97
98
 
98
99
  if types.is_optional(iterable._var_type):
99
100
  iterable = cond(iterable, iterable, [])
@@ -122,11 +123,12 @@ class Foreach(Component):
122
123
 
123
124
  # Validate the render function signature.
124
125
  if len(params) == 0 or len(params) > 2:
125
- raise ForeachRenderError(
126
+ msg = (
126
127
  "Expected 1 or 2 parameters in foreach render function, got "
127
128
  f"{[p.name for p in params]}. See "
128
129
  "https://reflex.dev/docs/library/dynamic-rendering/foreach/"
129
130
  )
131
+ raise ForeachRenderError(msg)
130
132
 
131
133
  if len(params) >= 1:
132
134
  # Determine the arg var name based on the params accepted by render_fn.
@@ -30,9 +30,9 @@ class Html(Div):
30
30
  """
31
31
  # If children are not provided, throw an error.
32
32
  if len(children) != 1:
33
- raise ValueError("Must provide children to the html component.")
34
- else:
35
- props["dangerouslySetInnerHTML"] = {"__html": children[0]}
33
+ msg = "Must provide children to the html component."
34
+ raise ValueError(msg)
35
+ props["dangerouslySetInnerHTML"] = {"__html": children[0]}
36
36
 
37
37
  # Apply the default classname
38
38
  given_class_name = props.pop("class_name", [])
@@ -260,6 +260,5 @@ class Html(Div):
260
260
  Raises:
261
261
  ValueError: If children are not provided or more than one child is provided.
262
262
  """
263
- ...
264
263
 
265
264
  html = Html.create