reflex 0.7.14a6__py3-none-any.whl → 0.8.0a2__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 (211) hide show
  1. reflex/.templates/jinja/app/rxconfig.py.jinja2 +4 -1
  2. reflex/.templates/jinja/web/package.json.jinja2 +1 -1
  3. reflex/.templates/jinja/web/pages/_app.js.jinja2 +16 -10
  4. reflex/.templates/jinja/web/pages/_document.js.jinja2 +1 -1
  5. reflex/.templates/jinja/web/pages/base_page.js.jinja2 +0 -1
  6. reflex/.templates/jinja/web/pages/stateful_component.js.jinja2 +4 -0
  7. reflex/.templates/jinja/web/utils/context.js.jinja2 +25 -8
  8. reflex/.templates/web/app/entry.client.js +8 -0
  9. reflex/.templates/web/app/routes.js +10 -0
  10. reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +12 -37
  11. reflex/.templates/web/postcss.config.js +1 -1
  12. reflex/.templates/web/react-router.config.js +6 -0
  13. reflex/.templates/web/utils/client_side_routing.js +21 -19
  14. reflex/.templates/web/utils/react-theme.js +92 -0
  15. reflex/.templates/web/utils/state.js +160 -67
  16. reflex/.templates/web/vite.config.js +32 -0
  17. reflex/__init__.py +1 -6
  18. reflex/__init__.pyi +0 -4
  19. reflex/app.py +53 -116
  20. reflex/base.py +1 -87
  21. reflex/compiler/compiler.py +41 -8
  22. reflex/compiler/templates.py +3 -3
  23. reflex/compiler/utils.py +73 -33
  24. reflex/components/__init__.py +0 -2
  25. reflex/components/__init__.pyi +0 -3
  26. reflex/components/base/__init__.py +1 -5
  27. reflex/components/base/__init__.pyi +4 -6
  28. reflex/components/base/app_wrap.pyi +5 -4
  29. reflex/components/base/body.pyi +5 -4
  30. reflex/components/base/document.py +18 -14
  31. reflex/components/base/document.pyi +83 -27
  32. reflex/components/base/error_boundary.pyi +5 -4
  33. reflex/components/base/fragment.pyi +5 -4
  34. reflex/components/base/link.pyi +9 -7
  35. reflex/components/base/meta.pyi +17 -13
  36. reflex/components/base/script.py +60 -58
  37. reflex/components/base/script.pyi +246 -31
  38. reflex/components/base/strict_mode.pyi +5 -4
  39. reflex/components/component.py +146 -217
  40. reflex/components/core/__init__.py +1 -0
  41. reflex/components/core/__init__.pyi +1 -0
  42. reflex/components/core/auto_scroll.pyi +5 -4
  43. reflex/components/core/banner.pyi +25 -19
  44. reflex/components/core/client_side_routing.py +7 -6
  45. reflex/components/core/client_side_routing.pyi +6 -56
  46. reflex/components/core/clipboard.pyi +5 -4
  47. reflex/components/core/debounce.py +1 -0
  48. reflex/components/core/debounce.pyi +5 -4
  49. reflex/components/core/foreach.py +3 -2
  50. reflex/components/core/helmet.py +14 -0
  51. reflex/components/{next/base.pyi → core/helmet.pyi} +10 -7
  52. reflex/components/core/html.pyi +5 -4
  53. reflex/components/core/sticky.pyi +17 -13
  54. reflex/components/core/upload.py +2 -1
  55. reflex/components/core/upload.pyi +21 -16
  56. reflex/components/datadisplay/code.py +2 -72
  57. reflex/components/datadisplay/code.pyi +9 -10
  58. reflex/components/datadisplay/dataeditor.pyi +11 -6
  59. reflex/components/datadisplay/shiki_code_block.pyi +13 -10
  60. reflex/components/dynamic.py +5 -5
  61. reflex/components/el/element.pyi +5 -4
  62. reflex/components/el/elements/base.pyi +5 -4
  63. reflex/components/el/elements/forms.pyi +69 -52
  64. reflex/components/el/elements/inline.pyi +113 -85
  65. reflex/components/el/elements/media.pyi +105 -79
  66. reflex/components/el/elements/metadata.pyi +25 -19
  67. reflex/components/el/elements/other.pyi +29 -22
  68. reflex/components/el/elements/scripts.pyi +13 -10
  69. reflex/components/el/elements/sectioning.pyi +61 -46
  70. reflex/components/el/elements/tables.pyi +41 -31
  71. reflex/components/el/elements/typography.pyi +61 -46
  72. reflex/components/field.py +175 -0
  73. reflex/components/gridjs/datatable.py +2 -2
  74. reflex/components/gridjs/datatable.pyi +11 -9
  75. reflex/components/lucide/icon.py +6 -2
  76. reflex/components/lucide/icon.pyi +15 -10
  77. reflex/components/markdown/markdown.pyi +5 -4
  78. reflex/components/moment/moment.pyi +5 -4
  79. reflex/components/plotly/plotly.pyi +19 -10
  80. reflex/components/props.py +376 -27
  81. reflex/components/radix/primitives/accordion.py +8 -1
  82. reflex/components/radix/primitives/accordion.pyi +29 -22
  83. reflex/components/radix/primitives/base.pyi +9 -7
  84. reflex/components/radix/primitives/drawer.pyi +45 -34
  85. reflex/components/radix/primitives/form.pyi +41 -31
  86. reflex/components/radix/primitives/progress.pyi +21 -16
  87. reflex/components/radix/primitives/slider.pyi +21 -16
  88. reflex/components/radix/themes/base.py +3 -3
  89. reflex/components/radix/themes/base.pyi +33 -25
  90. reflex/components/radix/themes/color_mode.pyi +13 -10
  91. reflex/components/radix/themes/components/alert_dialog.pyi +29 -22
  92. reflex/components/radix/themes/components/aspect_ratio.pyi +5 -4
  93. reflex/components/radix/themes/components/avatar.pyi +5 -4
  94. reflex/components/radix/themes/components/badge.pyi +5 -4
  95. reflex/components/radix/themes/components/button.pyi +5 -4
  96. reflex/components/radix/themes/components/callout.pyi +21 -16
  97. reflex/components/radix/themes/components/card.pyi +5 -4
  98. reflex/components/radix/themes/components/checkbox.pyi +13 -10
  99. reflex/components/radix/themes/components/checkbox_cards.pyi +9 -7
  100. reflex/components/radix/themes/components/checkbox_group.pyi +9 -7
  101. reflex/components/radix/themes/components/context_menu.pyi +53 -40
  102. reflex/components/radix/themes/components/data_list.pyi +17 -13
  103. reflex/components/radix/themes/components/dialog.pyi +29 -22
  104. reflex/components/radix/themes/components/dropdown_menu.pyi +33 -25
  105. reflex/components/radix/themes/components/hover_card.pyi +17 -13
  106. reflex/components/radix/themes/components/icon_button.pyi +5 -4
  107. reflex/components/radix/themes/components/inset.pyi +5 -4
  108. reflex/components/radix/themes/components/popover.pyi +17 -13
  109. reflex/components/radix/themes/components/progress.pyi +5 -4
  110. reflex/components/radix/themes/components/radio.pyi +5 -4
  111. reflex/components/radix/themes/components/radio_cards.pyi +9 -7
  112. reflex/components/radix/themes/components/radio_group.pyi +17 -13
  113. reflex/components/radix/themes/components/scroll_area.pyi +5 -4
  114. reflex/components/radix/themes/components/segmented_control.pyi +9 -7
  115. reflex/components/radix/themes/components/select.pyi +37 -28
  116. reflex/components/radix/themes/components/separator.pyi +5 -4
  117. reflex/components/radix/themes/components/skeleton.pyi +5 -4
  118. reflex/components/radix/themes/components/slider.pyi +5 -4
  119. reflex/components/radix/themes/components/spinner.pyi +5 -4
  120. reflex/components/radix/themes/components/switch.pyi +5 -4
  121. reflex/components/radix/themes/components/table.pyi +29 -22
  122. reflex/components/radix/themes/components/tabs.pyi +21 -16
  123. reflex/components/radix/themes/components/text_area.pyi +5 -4
  124. reflex/components/radix/themes/components/text_field.pyi +13 -10
  125. reflex/components/radix/themes/components/tooltip.pyi +5 -4
  126. reflex/components/radix/themes/layout/base.pyi +5 -4
  127. reflex/components/radix/themes/layout/box.pyi +5 -4
  128. reflex/components/radix/themes/layout/center.pyi +5 -4
  129. reflex/components/radix/themes/layout/container.pyi +5 -4
  130. reflex/components/radix/themes/layout/flex.pyi +5 -4
  131. reflex/components/radix/themes/layout/grid.pyi +5 -4
  132. reflex/components/radix/themes/layout/list.pyi +21 -16
  133. reflex/components/radix/themes/layout/section.pyi +5 -4
  134. reflex/components/radix/themes/layout/spacer.pyi +5 -4
  135. reflex/components/radix/themes/layout/stack.pyi +13 -10
  136. reflex/components/radix/themes/typography/blockquote.pyi +5 -4
  137. reflex/components/radix/themes/typography/code.pyi +5 -4
  138. reflex/components/radix/themes/typography/heading.pyi +5 -4
  139. reflex/components/radix/themes/typography/link.py +46 -11
  140. reflex/components/radix/themes/typography/link.pyi +311 -6
  141. reflex/components/radix/themes/typography/text.pyi +29 -22
  142. reflex/components/react_player/audio.pyi +5 -4
  143. reflex/components/react_player/react_player.pyi +5 -4
  144. reflex/components/react_player/video.pyi +5 -4
  145. reflex/components/recharts/cartesian.py +2 -1
  146. reflex/components/recharts/cartesian.pyi +65 -46
  147. reflex/components/recharts/charts.py +4 -2
  148. reflex/components/recharts/charts.pyi +36 -24
  149. reflex/components/recharts/general.pyi +24 -18
  150. reflex/components/recharts/polar.py +8 -4
  151. reflex/components/recharts/polar.pyi +16 -10
  152. reflex/components/recharts/recharts.pyi +9 -7
  153. reflex/components/sonner/toast.py +2 -2
  154. reflex/components/sonner/toast.pyi +10 -8
  155. reflex/config.py +3 -77
  156. reflex/constants/__init__.py +2 -2
  157. reflex/constants/base.py +28 -11
  158. reflex/constants/compiler.py +5 -3
  159. reflex/constants/event.py +1 -0
  160. reflex/constants/installer.py +22 -16
  161. reflex/constants/route.py +19 -7
  162. reflex/constants/state.py +2 -0
  163. reflex/custom_components/custom_components.py +0 -14
  164. reflex/environment.py +1 -1
  165. reflex/event.py +178 -81
  166. reflex/experimental/__init__.py +0 -30
  167. reflex/istate/proxy.py +5 -3
  168. reflex/page.py +0 -27
  169. reflex/plugins/__init__.py +3 -2
  170. reflex/plugins/base.py +5 -1
  171. reflex/plugins/shared_tailwind.py +158 -0
  172. reflex/plugins/sitemap.py +206 -0
  173. reflex/plugins/tailwind_v3.py +13 -106
  174. reflex/plugins/tailwind_v4.py +15 -108
  175. reflex/reflex.py +1 -0
  176. reflex/route.py +15 -21
  177. reflex/state.py +134 -140
  178. reflex/testing.py +58 -10
  179. reflex/utils/build.py +38 -82
  180. reflex/utils/exec.py +59 -161
  181. reflex/utils/export.py +2 -2
  182. reflex/utils/imports.py +0 -4
  183. reflex/utils/misc.py +28 -0
  184. reflex/utils/prerequisites.py +65 -62
  185. reflex/utils/processes.py +8 -7
  186. reflex/utils/pyi_generator.py +21 -9
  187. reflex/utils/serializers.py +14 -1
  188. reflex/utils/types.py +196 -61
  189. reflex/vars/__init__.py +2 -0
  190. reflex/vars/base.py +367 -134
  191. {reflex-0.7.14a6.dist-info → reflex-0.8.0a2.dist-info}/METADATA +12 -5
  192. {reflex-0.7.14a6.dist-info → reflex-0.8.0a2.dist-info}/RECORD +195 -202
  193. reflex/.templates/web/next.config.js +0 -7
  194. reflex/components/base/head.py +0 -20
  195. reflex/components/base/head.pyi +0 -116
  196. reflex/components/next/__init__.py +0 -10
  197. reflex/components/next/base.py +0 -7
  198. reflex/components/next/image.py +0 -117
  199. reflex/components/next/image.pyi +0 -94
  200. reflex/components/next/link.py +0 -20
  201. reflex/components/next/link.pyi +0 -67
  202. reflex/components/next/video.py +0 -38
  203. reflex/components/next/video.pyi +0 -68
  204. reflex/components/suneditor/__init__.py +0 -5
  205. reflex/components/suneditor/editor.py +0 -269
  206. reflex/components/suneditor/editor.pyi +0 -199
  207. reflex/experimental/layout.py +0 -254
  208. reflex/experimental/layout.pyi +0 -814
  209. {reflex-0.7.14a6.dist-info → reflex-0.8.0a2.dist-info}/WHEEL +0 -0
  210. {reflex-0.7.14a6.dist-info → reflex-0.8.0a2.dist-info}/entry_points.txt +0 -0
  211. {reflex-0.7.14a6.dist-info → reflex-0.8.0a2.dist-info}/licenses/LICENSE +0 -0
@@ -39,9 +39,7 @@ from reflex.compiler import templates
39
39
  from reflex.config import Config, get_config
40
40
  from reflex.environment import environment
41
41
  from reflex.utils import console, net, path_ops, processes, redir
42
- from reflex.utils.decorator import once
43
42
  from reflex.utils.exceptions import SystemPackageMissingError
44
- from reflex.utils.format import format_library_name
45
43
  from reflex.utils.registry import get_npm_registry
46
44
 
47
45
  if typing.TYPE_CHECKING:
@@ -74,7 +72,7 @@ class CpuInfo:
74
72
 
75
73
 
76
74
  def get_web_dir() -> Path:
77
- """Get the working directory for the next.js commands.
75
+ """Get the working directory for the frontend.
78
76
 
79
77
  Can be overridden with REFLEX_WEB_WORKDIR.
80
78
 
@@ -334,13 +332,14 @@ def npm_escape_hatch() -> bool:
334
332
 
335
333
 
336
334
  def _check_app_name(config: Config):
337
- """Check if the app name is set in the config.
335
+ """Check if the app name is valid and matches the folder structure.
338
336
 
339
337
  Args:
340
338
  config: The config object.
341
339
 
342
340
  Raises:
343
- RuntimeError: If the app name is not set in the config.
341
+ RuntimeError: If the app name is not set, folder doesn't exist, or doesn't match config.
342
+ ModuleNotFoundError: If the app_name is not importable (i.e., not a valid Python package, folder structure being wrong).
344
343
  """
345
344
  if not config.app_name:
346
345
  msg = (
@@ -349,6 +348,21 @@ def _check_app_name(config: Config):
349
348
  )
350
349
  raise RuntimeError(msg)
351
350
 
351
+ from reflex.utils.misc import with_cwd_in_syspath
352
+
353
+ with with_cwd_in_syspath():
354
+ try:
355
+ mod_spec = importlib.util.find_spec(config.module)
356
+ except ModuleNotFoundError:
357
+ mod_spec = None
358
+ if mod_spec is None:
359
+ msg = f"Module {config.module} not found. "
360
+ if config.app_module_import is not None:
361
+ msg += f"Ensure app_module_import='{config.app_module_import}' in rxconfig.py matches your folder structure."
362
+ else:
363
+ msg += f"Ensure app_name='{config.app_name}' in rxconfig.py matches your folder structure."
364
+ raise ModuleNotFoundError(msg)
365
+
352
366
 
353
367
  def get_app(reload: bool = False) -> ModuleType:
354
368
  """Get the app module based on the default config.
@@ -439,7 +453,7 @@ def validate_app(
439
453
 
440
454
  def get_compiled_app(
441
455
  reload: bool = False,
442
- export: bool = False,
456
+ prerender_routes: bool = False,
443
457
  dry_run: bool = False,
444
458
  check_if_schema_up_to_date: bool = False,
445
459
  ) -> ModuleType:
@@ -447,7 +461,7 @@ def get_compiled_app(
447
461
 
448
462
  Args:
449
463
  reload: Re-import the app module from disk
450
- export: Compile the app for export
464
+ prerender_routes: Whether to prerender routes.
451
465
  dry_run: If True, do not write the compiled app to disk.
452
466
  check_if_schema_up_to_date: If True, check if the schema is up to date.
453
467
 
@@ -460,13 +474,13 @@ def get_compiled_app(
460
474
  # For py3.9 compatibility when redis is used, we MUST add any decorator pages
461
475
  # before compiling the app in a thread to avoid event loop error (REF-2172).
462
476
  app._apply_decorated_pages()
463
- app._compile(export=export, dry_run=dry_run)
477
+ app._compile(prerender_routes=prerender_routes, dry_run=dry_run)
464
478
  return app_module
465
479
 
466
480
 
467
481
  def compile_app(
468
482
  reload: bool = False,
469
- export: bool = False,
483
+ prerender_routes: bool = False,
470
484
  dry_run: bool = False,
471
485
  check_if_schema_up_to_date: bool = False,
472
486
  ) -> None:
@@ -474,13 +488,13 @@ def compile_app(
474
488
 
475
489
  Args:
476
490
  reload: Re-import the app module from disk
477
- export: Compile the app for export
491
+ prerender_routes: Whether to prerender routes.
478
492
  dry_run: If True, do not write the compiled app to disk.
479
493
  check_if_schema_up_to_date: If True, check if the schema is up to date.
480
494
  """
481
495
  get_compiled_app(
482
496
  reload=reload,
483
- export=export,
497
+ prerender_routes=prerender_routes,
484
498
  dry_run=dry_run,
485
499
  check_if_schema_up_to_date=check_if_schema_up_to_date,
486
500
  )
@@ -529,20 +543,26 @@ def _can_colorize() -> bool:
529
543
 
530
544
 
531
545
  def compile_or_validate_app(
532
- compile: bool = False, check_if_schema_up_to_date: bool = False
546
+ compile: bool = False,
547
+ check_if_schema_up_to_date: bool = False,
548
+ prerender_routes: bool = False,
533
549
  ) -> bool:
534
550
  """Compile or validate the app module based on the default config.
535
551
 
536
552
  Args:
537
553
  compile: Whether to compile the app.
538
554
  check_if_schema_up_to_date: If True, check if the schema is up to date.
555
+ prerender_routes: Whether to prerender routes.
539
556
 
540
557
  Returns:
541
558
  If the app is compiled successfully.
542
559
  """
543
560
  try:
544
561
  if compile:
545
- compile_app(check_if_schema_up_to_date=check_if_schema_up_to_date)
562
+ compile_app(
563
+ check_if_schema_up_to_date=check_if_schema_up_to_date,
564
+ prerender_routes=prerender_routes,
565
+ )
546
566
  else:
547
567
  validate_app(check_if_schema_up_to_date=check_if_schema_up_to_date)
548
568
  except Exception as e:
@@ -591,19 +611,19 @@ def get_redis_sync() -> RedisSync | None:
591
611
 
592
612
 
593
613
  def parse_redis_url() -> str | None:
594
- """Parse the REDIS_URL in config if applicable.
614
+ """Parse the REFLEX_REDIS_URL in config if applicable.
595
615
 
596
616
  Returns:
597
617
  If url is non-empty, return the URL as it is.
598
618
 
599
619
  Raises:
600
- ValueError: If the REDIS_URL is not a supported scheme.
620
+ ValueError: If the REFLEX_REDIS_URL is not a supported scheme.
601
621
  """
602
622
  config = get_config()
603
623
  if not config.redis_url:
604
624
  return None
605
625
  if not config.redis_url.startswith(("redis://", "rediss://", "unix://")):
606
- msg = "REDIS_URL must start with 'redis://', 'rediss://', or 'unix://'."
626
+ msg = "REFLEX_REDIS_URL must start with 'redis://', 'rediss://', or 'unix://'."
607
627
  raise ValueError(msg)
608
628
  return config.redis_url
609
629
 
@@ -1017,29 +1037,19 @@ def initialize_web_directory():
1017
1037
  console.debug("Initializing the public directory.")
1018
1038
  path_ops.mkdir(get_web_dir() / constants.Dirs.PUBLIC)
1019
1039
 
1020
- console.debug("Initializing the next.config.js file.")
1021
- update_next_config()
1040
+ console.debug("Initializing the react-router.config.js file.")
1041
+ update_react_router_config()
1022
1042
 
1023
1043
  console.debug("Initializing the reflex.json file.")
1024
1044
  # Initialize the reflex json file.
1025
1045
  init_reflex_json(project_hash=project_hash)
1026
1046
 
1027
1047
 
1028
- @once
1029
- def _turbopack_flag() -> str:
1030
- return " --turbopack" if environment.REFLEX_USE_TURBOPACK.get() else ""
1031
-
1032
-
1033
1048
  def _compile_package_json():
1034
1049
  return templates.PACKAGE_JSON.render(
1035
1050
  scripts={
1036
- "dev": constants.PackageJson.Commands.DEV.format(flags=_turbopack_flag()),
1037
- "export": constants.PackageJson.Commands.EXPORT.format(
1038
- flags=_turbopack_flag()
1039
- ),
1040
- "export_sitemap": constants.PackageJson.Commands.EXPORT_SITEMAP.format(
1041
- flags=_turbopack_flag()
1042
- ),
1051
+ "dev": constants.PackageJson.Commands.DEV,
1052
+ "export": constants.PackageJson.Commands.EXPORT,
1043
1053
  "prod": constants.PackageJson.Commands.PROD,
1044
1054
  },
1045
1055
  dependencies=constants.PackageJson.DEPENDENCIES,
@@ -1107,50 +1117,43 @@ def init_reflex_json(project_hash: int | None):
1107
1117
  path_ops.update_json_file(get_web_dir() / constants.Reflex.JSON, reflex_json)
1108
1118
 
1109
1119
 
1110
- def update_next_config(
1111
- export: bool = False, transpile_packages: list[str] | None = None
1112
- ):
1113
- """Update Next.js config from Reflex config.
1120
+ def update_react_router_config(prerender_routes: bool = False):
1121
+ """Update react-router.config.js config from Reflex config.
1114
1122
 
1115
1123
  Args:
1116
- export: if the method run during reflex export.
1117
- transpile_packages: list of packages to transpile via next.config.js.
1124
+ prerender_routes: Whether to enable prerendering of routes.
1118
1125
  """
1119
- next_config_file = get_web_dir() / constants.Next.CONFIG_FILE
1126
+ react_router_config_file_path = get_web_dir() / constants.ReactRouter.CONFIG_FILE
1120
1127
 
1121
- next_config = _update_next_config(
1122
- get_config(), export=export, transpile_packages=transpile_packages
1128
+ new_react_router_config = _update_react_router_config(
1129
+ get_config(), prerender_routes=prerender_routes
1123
1130
  )
1124
1131
 
1125
- # Overwriting the next.config.js triggers a full server reload, so make sure
1132
+ # Overwriting the config file triggers a full server reload, so make sure
1126
1133
  # there is actually a diff.
1127
- orig_next_config = next_config_file.read_text() if next_config_file.exists() else ""
1128
- if orig_next_config != next_config:
1129
- next_config_file.write_text(next_config)
1134
+ old_react_router_config = (
1135
+ react_router_config_file_path.read_text()
1136
+ if react_router_config_file_path.exists()
1137
+ else ""
1138
+ )
1139
+ if old_react_router_config != new_react_router_config:
1140
+ react_router_config_file_path.write_text(new_react_router_config)
1130
1141
 
1131
1142
 
1132
- def _update_next_config(
1133
- config: Config, export: bool = False, transpile_packages: list[str] | None = None
1134
- ):
1135
- next_config = {
1136
- "basePath": config.frontend_path or "",
1137
- "compress": config.next_compression,
1138
- "trailingSlash": True,
1139
- "staticPageGenerationTimeout": config.static_page_generation_timeout,
1143
+ def _update_react_router_config(config: Config, prerender_routes: bool = False):
1144
+ react_router_config = {
1145
+ "basename": "/" + (config.frontend_path or "").removeprefix("/"),
1146
+ "future": {
1147
+ "unstable_optimizeDeps": True,
1148
+ },
1149
+ "ssr": False,
1140
1150
  }
1141
- if not config.next_dev_indicators:
1142
- next_config["devIndicators"] = False
1143
1151
 
1144
- if transpile_packages:
1145
- next_config["transpilePackages"] = list(
1146
- dict.fromkeys([format_library_name(p) for p in transpile_packages])
1147
- )
1148
- if export:
1149
- next_config["output"] = "export"
1150
- next_config["distDir"] = constants.Dirs.STATIC
1152
+ if prerender_routes:
1153
+ react_router_config["prerender"] = True
1154
+ react_router_config["build"] = constants.Dirs.BUILD_DIR
1151
1155
 
1152
- next_config_json = re.sub(r'"([^"]+)"(?=:)', r"\1", json.dumps(next_config))
1153
- return f"module.exports = {next_config_json};"
1156
+ return f"export default {json.dumps(react_router_config)};"
1154
1157
 
1155
1158
 
1156
1159
  def remove_existing_bun_installation():
reflex/utils/processes.py CHANGED
@@ -320,7 +320,8 @@ def stream_logs(
320
320
 
321
321
  # Windows uvicorn bug
322
322
  # https://github.com/reflex-dev/reflex/issues/2335
323
- accepted_return_codes = [0, -2, 15] if constants.IS_WINDOWS else [0, -2]
323
+ # 130 is the exit code that react router returns when it is interrupted by a signal.
324
+ accepted_return_codes = [0, -2, 15, 130] if constants.IS_WINDOWS else [0, -2, 130]
324
325
  if process.returncode not in accepted_return_codes and not suppress_errors:
325
326
  console.error(f"{message} failed with exit code {process.returncode}")
326
327
  if "".join(logs).count("CERT_HAS_EXPIRED") > 0:
@@ -412,12 +413,12 @@ def show_progress(message: str, process: subprocess.Popen, checkpoints: list[str
412
413
  task = progress.add_task(f"{message}: ", total=len(checkpoints))
413
414
  for line in stream_logs(message, process, progress=progress):
414
415
  # Check for special strings and update the progress bar.
415
- for special_string in checkpoints:
416
- if special_string in line:
417
- progress.update(task, advance=1)
418
- if special_string == checkpoints[-1]:
419
- progress.update(task, completed=len(checkpoints))
420
- break
416
+ special_string = checkpoints[0]
417
+ if special_string in line:
418
+ progress.update(task, advance=1)
419
+ checkpoints.pop(0)
420
+ if not checkpoints:
421
+ break
421
422
 
422
423
 
423
424
  def atexit_handler():
@@ -90,6 +90,7 @@ DEFAULT_IMPORTS = {
90
90
  "EventSpec",
91
91
  "EventType",
92
92
  "KeyInputInfo",
93
+ "PointerEventInfo",
93
94
  ],
94
95
  "reflex.style": ["Style"],
95
96
  "reflex.vars.base": ["Var"],
@@ -366,7 +367,7 @@ def _extract_class_props_as_ast_nodes(
366
367
  all_props = []
367
368
  kwargs = []
368
369
  for target_class in clzs:
369
- event_triggers = target_class._create([]).get_event_triggers()
370
+ event_triggers = target_class.get_event_triggers()
370
371
  # Import from the target class to ensure type hints are resolvable.
371
372
  exec(f"from {target_class.__module__} import *", type_hint_globals)
372
373
  for name, value in target_class.__annotations__.items():
@@ -409,7 +410,7 @@ def _extract_class_props_as_ast_nodes(
409
410
  )
410
411
  ),
411
412
  ),
412
- ast.Constant(value=default),
413
+ ast.Constant(value=default), # pyright: ignore [reportArgumentType]
413
414
  )
414
415
  )
415
416
  return kwargs
@@ -444,7 +445,11 @@ def type_to_ast(typ: Any, cls: type) -> ast.expr:
444
445
 
445
446
  if all(a == b for a, b in zipped) and len(typ_parts) == len(cls_parts):
446
447
  return ast.Name(id=typ.__name__)
447
-
448
+ if (
449
+ typ.__module__ in DEFAULT_IMPORTS
450
+ and typ.__name__ in DEFAULT_IMPORTS[typ.__module__]
451
+ ):
452
+ return ast.Name(id=typ.__name__)
448
453
  return ast.Name(id=typ.__module__ + "." + typ.__name__)
449
454
  return ast.Name(id=typ.__name__)
450
455
  if hasattr(typ, "_name"):
@@ -607,7 +612,7 @@ def _generate_component_create_functiondef(
607
612
  return ast.Name(id=f"{' | '.join(map(ast.unparse, all_count_args_type))}")
608
613
  return ast.Name(id="EventType[Any]")
609
614
 
610
- event_triggers = clz._create([]).get_event_triggers()
615
+ event_triggers = clz.get_event_triggers()
611
616
 
612
617
  # event handler kwargs
613
618
  kwargs.extend(
@@ -1337,12 +1342,19 @@ class PyiGenerator:
1337
1342
 
1338
1343
 
1339
1344
  if __name__ == "__main__":
1345
+ import argparse
1346
+
1347
+ parser = argparse.ArgumentParser(description="Generate .pyi stub files")
1348
+ parser.add_argument(
1349
+ "targets",
1350
+ nargs="*",
1351
+ default=["reflex/components", "reflex/experimental", "reflex/__init__.py"],
1352
+ help="Target directories/files to process",
1353
+ )
1354
+ args = parser.parse_args()
1355
+
1340
1356
  logging.basicConfig(level=logging.INFO)
1341
1357
  logging.getLogger("blib2to3.pgen2.driver").setLevel(logging.INFO)
1342
1358
 
1343
1359
  gen = PyiGenerator()
1344
- gen.scan_all(
1345
- ["reflex/components", "reflex/experimental", "reflex/__init__.py"],
1346
- None,
1347
- use_json=True,
1348
- )
1360
+ gen.scan_all(args.targets, None, use_json=True)
@@ -9,7 +9,7 @@ import functools
9
9
  import inspect
10
10
  import json
11
11
  import warnings
12
- from collections.abc import Callable, Sequence
12
+ from collections.abc import Callable, Mapping, Sequence
13
13
  from datetime import date, datetime, time, timedelta
14
14
  from enum import Enum
15
15
  from pathlib import Path
@@ -335,6 +335,19 @@ def serialize_sequence(value: Sequence) -> list:
335
335
  return list(value)
336
336
 
337
337
 
338
+ @serializer(to=dict)
339
+ def serialize_mapping(value: Mapping) -> dict:
340
+ """Serialize a mapping type to a dictionary.
341
+
342
+ Args:
343
+ value: The mapping instance to serialize.
344
+
345
+ Returns:
346
+ A new dictionary containing the same key-value pairs as the input mapping.
347
+ """
348
+ return {**value}
349
+
350
+
338
351
  @serializer(to=str)
339
352
  def serialize_datetime(dt: date | datetime | time | timedelta) -> str:
340
353
  """Serialize a datetime to a JSON string.