reflex 0.5.4a3__py3-none-any.whl → 0.5.5a1__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 (260) hide show
  1. reflex/.templates/apps/demo/code/demo.py +1 -0
  2. reflex/.templates/apps/demo/code/pages/__init__.py +1 -0
  3. reflex/.templates/apps/demo/code/pages/datatable.py +1 -0
  4. reflex/.templates/apps/demo/code/pages/forms.py +1 -0
  5. reflex/.templates/apps/demo/code/pages/graphing.py +1 -0
  6. reflex/.templates/apps/demo/code/pages/home.py +1 -0
  7. reflex/.templates/apps/demo/code/styles.py +1 -0
  8. reflex/.templates/apps/demo/code/webui/components/loading_icon.py +1 -8
  9. reflex/.templates/web/components/reflex/chakra_color_mode_provider.js +27 -12
  10. reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +19 -5
  11. reflex/.templates/web/utils/state.js +73 -7
  12. reflex/__init__.py +3 -0
  13. reflex/__init__.pyi +3 -0
  14. reflex/admin.py +1 -0
  15. reflex/app.py +8 -6
  16. reflex/app_module_for_backend.py +2 -1
  17. reflex/base.py +4 -4
  18. reflex/compiler/compiler.py +4 -3
  19. reflex/compiler/templates.py +2 -0
  20. reflex/compiler/utils.py +58 -35
  21. reflex/components/__init__.py +1 -0
  22. reflex/components/base/__init__.py +1 -0
  23. reflex/components/base/app_wrap.py +1 -0
  24. reflex/components/base/fragment.py +1 -0
  25. reflex/components/base/link.py +0 -1
  26. reflex/components/base/script.py +11 -15
  27. reflex/components/base/script.pyi +1 -2
  28. reflex/components/chakra/base.py +15 -13
  29. reflex/components/chakra/base.pyi +3 -1
  30. reflex/components/chakra/datadisplay/code.py +1 -0
  31. reflex/components/chakra/datadisplay/divider.py +1 -0
  32. reflex/components/chakra/datadisplay/table.py +1 -0
  33. reflex/components/chakra/datadisplay/table.pyi +3 -0
  34. reflex/components/chakra/datadisplay/tag.py +1 -0
  35. reflex/components/chakra/disclosure/transition.py +1 -0
  36. reflex/components/chakra/feedback/circularprogress.py +1 -0
  37. reflex/components/chakra/forms/button.py +1 -0
  38. reflex/components/chakra/forms/checkbox.py +4 -13
  39. reflex/components/chakra/forms/checkbox.pyi +1 -3
  40. reflex/components/chakra/forms/colormodeswitch.py +1 -0
  41. reflex/components/chakra/forms/editable.py +13 -16
  42. reflex/components/chakra/forms/editable.pyi +1 -3
  43. reflex/components/chakra/forms/form.py +1 -0
  44. reflex/components/chakra/forms/input.py +22 -21
  45. reflex/components/chakra/forms/input.pyi +4 -4
  46. reflex/components/chakra/forms/multiselect.py +1 -0
  47. reflex/components/chakra/forms/numberinput.py +3 -12
  48. reflex/components/chakra/forms/numberinput.pyi +1 -3
  49. reflex/components/chakra/forms/pininput.py +8 -14
  50. reflex/components/chakra/forms/pininput.pyi +2 -3
  51. reflex/components/chakra/forms/radio.py +4 -13
  52. reflex/components/chakra/forms/radio.pyi +2 -3
  53. reflex/components/chakra/forms/rangeslider.py +10 -13
  54. reflex/components/chakra/forms/rangeslider.pyi +2 -3
  55. reflex/components/chakra/forms/select.py +4 -12
  56. reflex/components/chakra/forms/select.pyi +2 -3
  57. reflex/components/chakra/forms/slider.py +10 -13
  58. reflex/components/chakra/forms/slider.pyi +2 -3
  59. reflex/components/chakra/forms/switch.py +4 -13
  60. reflex/components/chakra/forms/switch.pyi +1 -3
  61. reflex/components/chakra/forms/textarea.py +16 -17
  62. reflex/components/chakra/forms/textarea.pyi +1 -3
  63. reflex/components/chakra/media/avatar.py +4 -12
  64. reflex/components/chakra/media/avatar.pyi +1 -2
  65. reflex/components/chakra/media/icon.py +1 -0
  66. reflex/components/chakra/media/image.py +7 -11
  67. reflex/components/chakra/media/image.pyi +2 -2
  68. reflex/components/chakra/navigation/link.py +8 -4
  69. reflex/components/chakra/navigation/link.pyi +2 -1
  70. reflex/components/chakra/overlay/alertdialog.py +12 -14
  71. reflex/components/chakra/overlay/alertdialog.pyi +1 -2
  72. reflex/components/chakra/overlay/drawer.py +12 -14
  73. reflex/components/chakra/overlay/drawer.pyi +1 -2
  74. reflex/components/chakra/overlay/menu.py +7 -11
  75. reflex/components/chakra/overlay/menu.pyi +2 -2
  76. reflex/components/chakra/overlay/modal.py +13 -13
  77. reflex/components/chakra/overlay/modal.pyi +2 -2
  78. reflex/components/chakra/overlay/popover.py +6 -12
  79. reflex/components/chakra/overlay/popover.pyi +1 -2
  80. reflex/components/chakra/overlay/tooltip.py +7 -13
  81. reflex/components/chakra/overlay/tooltip.pyi +1 -2
  82. reflex/components/chakra/typography/heading.py +0 -1
  83. reflex/components/chakra/typography/span.py +1 -0
  84. reflex/components/chakra/typography/text.py +1 -0
  85. reflex/components/component.py +70 -43
  86. reflex/components/core/__init__.py +1 -0
  87. reflex/components/core/banner.py +27 -24
  88. reflex/components/core/banner.pyi +6 -2
  89. reflex/components/core/client_side_routing.py +1 -0
  90. reflex/components/core/cond.py +19 -17
  91. reflex/components/core/debounce.py +4 -11
  92. reflex/components/core/debounce.pyi +1 -1
  93. reflex/components/core/foreach.py +1 -0
  94. reflex/components/core/html.py +1 -0
  95. reflex/components/core/match.py +9 -6
  96. reflex/components/core/upload.py +26 -25
  97. reflex/components/core/upload.pyi +3 -4
  98. reflex/components/datadisplay/__init__.py +1 -0
  99. reflex/components/datadisplay/code.py +27 -23
  100. reflex/components/datadisplay/code.pyi +4 -2
  101. reflex/components/datadisplay/dataeditor.py +73 -80
  102. reflex/components/datadisplay/dataeditor.pyi +52 -4
  103. reflex/components/datadisplay/logo.py +1 -0
  104. reflex/components/el/__init__.py +1 -0
  105. reflex/components/el/__init__.pyi +8 -0
  106. reflex/components/el/element.py +0 -1
  107. reflex/components/el/elements/__init__.py +5 -0
  108. reflex/components/el/elements/__init__.pyi +12 -1
  109. reflex/components/el/elements/base.py +1 -0
  110. reflex/components/el/elements/forms.py +44 -61
  111. reflex/components/el/elements/forms.pyi +4 -6
  112. reflex/components/el/elements/inline.py +1 -0
  113. reflex/components/el/elements/media.py +53 -0
  114. reflex/components/el/elements/media.pyi +428 -0
  115. reflex/components/el/elements/metadata.py +11 -0
  116. reflex/components/el/elements/metadata.pyi +80 -0
  117. reflex/components/el/elements/other.py +1 -0
  118. reflex/components/el/elements/scripts.py +1 -0
  119. reflex/components/el/elements/tables.py +1 -0
  120. reflex/components/el/elements/typography.py +1 -0
  121. reflex/components/gridjs/datatable.py +9 -6
  122. reflex/components/gridjs/datatable.pyi +4 -1
  123. reflex/components/markdown/markdown.py +36 -41
  124. reflex/components/markdown/markdown.pyi +4 -3
  125. reflex/components/media/icon.py +1 -0
  126. reflex/components/moment/moment.py +11 -17
  127. reflex/components/moment/moment.pyi +4 -3
  128. reflex/components/next/base.py +1 -0
  129. reflex/components/next/image.py +6 -11
  130. reflex/components/next/image.pyi +2 -2
  131. reflex/components/plotly/plotly.py +1 -0
  132. reflex/components/props.py +1 -0
  133. reflex/components/radix/__init__.py +1 -0
  134. reflex/components/radix/primitives/__init__.py +1 -0
  135. reflex/components/radix/primitives/accordion.py +7 -15
  136. reflex/components/radix/primitives/accordion.pyi +7 -4
  137. reflex/components/radix/primitives/base.py +1 -0
  138. reflex/components/radix/primitives/drawer.py +17 -27
  139. reflex/components/radix/primitives/drawer.pyi +2 -4
  140. reflex/components/radix/primitives/form.py +4 -12
  141. reflex/components/radix/primitives/form.pyi +2 -3
  142. reflex/components/radix/primitives/slider.py +6 -11
  143. reflex/components/radix/primitives/slider.pyi +2 -2
  144. reflex/components/radix/themes/__init__.py +1 -0
  145. reflex/components/radix/themes/base.py +3 -3
  146. reflex/components/radix/themes/base.pyi +3 -2
  147. reflex/components/radix/themes/color_mode.py +31 -2
  148. reflex/components/radix/themes/color_mode.pyi +10 -1
  149. reflex/components/radix/themes/components/__init__.py +1 -0
  150. reflex/components/radix/themes/components/alert_dialog.py +13 -24
  151. reflex/components/radix/themes/components/alert_dialog.pyi +2 -4
  152. reflex/components/radix/themes/components/aspect_ratio.py +1 -0
  153. reflex/components/radix/themes/components/card.py +1 -0
  154. reflex/components/radix/themes/components/checkbox.py +6 -22
  155. reflex/components/radix/themes/components/checkbox.pyi +2 -4
  156. reflex/components/radix/themes/components/checkbox_group.py +15 -3
  157. reflex/components/radix/themes/components/checkbox_group.pyi +10 -2
  158. reflex/components/radix/themes/components/context_menu.py +29 -38
  159. reflex/components/radix/themes/components/context_menu.pyi +2 -5
  160. reflex/components/radix/themes/components/dialog.py +18 -26
  161. reflex/components/radix/themes/components/dialog.pyi +2 -4
  162. reflex/components/radix/themes/components/dropdown_menu.py +32 -57
  163. reflex/components/radix/themes/components/dropdown_menu.pyi +2 -7
  164. reflex/components/radix/themes/components/hover_card.py +5 -12
  165. reflex/components/radix/themes/components/hover_card.pyi +2 -3
  166. reflex/components/radix/themes/components/icon_button.py +1 -0
  167. reflex/components/radix/themes/components/icon_button.pyi +1 -0
  168. reflex/components/radix/themes/components/inset.py +1 -0
  169. reflex/components/radix/themes/components/popover.py +22 -27
  170. reflex/components/radix/themes/components/popover.pyi +2 -4
  171. reflex/components/radix/themes/components/radio_group.py +25 -17
  172. reflex/components/radix/themes/components/radio_group.pyi +2 -3
  173. reflex/components/radix/themes/components/scroll_area.py +1 -0
  174. reflex/components/radix/themes/components/segmented_control.py +18 -5
  175. reflex/components/radix/themes/components/segmented_control.pyi +16 -7
  176. reflex/components/radix/themes/components/select.py +13 -23
  177. reflex/components/radix/themes/components/select.pyi +1 -4
  178. reflex/components/radix/themes/components/separator.py +1 -0
  179. reflex/components/radix/themes/components/slider.py +7 -12
  180. reflex/components/radix/themes/components/slider.pyi +2 -3
  181. reflex/components/radix/themes/components/switch.py +5 -12
  182. reflex/components/radix/themes/components/switch.pyi +2 -3
  183. reflex/components/radix/themes/components/table.py +1 -0
  184. reflex/components/radix/themes/components/tabs.py +4 -11
  185. reflex/components/radix/themes/components/tabs.pyi +2 -2
  186. reflex/components/radix/themes/components/text_area.py +19 -18
  187. reflex/components/radix/themes/components/text_area.pyi +2 -3
  188. reflex/components/radix/themes/components/text_field.py +19 -18
  189. reflex/components/radix/themes/components/text_field.pyi +3 -3
  190. reflex/components/radix/themes/components/tooltip.py +10 -13
  191. reflex/components/radix/themes/components/tooltip.pyi +2 -3
  192. reflex/components/radix/themes/layout/__init__.py +1 -0
  193. reflex/components/radix/themes/layout/box.py +1 -0
  194. reflex/components/radix/themes/layout/container.py +1 -0
  195. reflex/components/radix/themes/layout/list.py +1 -0
  196. reflex/components/radix/themes/layout/list.pyi +1 -0
  197. reflex/components/radix/themes/layout/section.py +1 -0
  198. reflex/components/radix/themes/typography/__init__.py +1 -0
  199. reflex/components/radix/themes/typography/base.py +1 -0
  200. reflex/components/radix/themes/typography/blockquote.py +1 -0
  201. reflex/components/radix/themes/typography/code.py +1 -0
  202. reflex/components/radix/themes/typography/heading.py +1 -0
  203. reflex/components/radix/themes/typography/link.py +8 -3
  204. reflex/components/radix/themes/typography/link.pyi +2 -1
  205. reflex/components/react_player/audio.py +1 -0
  206. reflex/components/react_player/audio.pyi +48 -0
  207. reflex/components/react_player/react_player.py +49 -0
  208. reflex/components/react_player/react_player.pyi +49 -0
  209. reflex/components/react_player/video.py +1 -0
  210. reflex/components/react_player/video.pyi +48 -0
  211. reflex/components/recharts/__init__.py +1 -0
  212. reflex/components/recharts/cartesian.py +264 -74
  213. reflex/components/recharts/cartesian.pyi +573 -58
  214. reflex/components/recharts/charts.py +68 -78
  215. reflex/components/recharts/charts.pyi +373 -156
  216. reflex/components/recharts/general.py +52 -20
  217. reflex/components/recharts/general.pyi +52 -6
  218. reflex/components/recharts/polar.py +30 -18
  219. reflex/components/recharts/polar.pyi +66 -5
  220. reflex/components/recharts/recharts.py +5 -3
  221. reflex/components/recharts/recharts.pyi +2 -1
  222. reflex/components/sonner/toast.py +2 -2
  223. reflex/components/sonner/toast.pyi +1 -1
  224. reflex/components/suneditor/editor.py +39 -26
  225. reflex/components/suneditor/editor.pyi +4 -4
  226. reflex/components/tags/iter_tag.py +1 -0
  227. reflex/constants/__init__.py +3 -2
  228. reflex/constants/base.py +20 -21
  229. reflex/constants/compiler.py +3 -1
  230. reflex/constants/config.py +1 -0
  231. reflex/constants/event.py +1 -0
  232. reflex/constants/installer.py +3 -2
  233. reflex/constants/style.py +2 -8
  234. reflex/event.py +36 -6
  235. reflex/experimental/assets.py +1 -0
  236. reflex/experimental/client_state.py +9 -3
  237. reflex/experimental/hooks.py +1 -0
  238. reflex/experimental/misc.py +12 -3
  239. reflex/middleware/hydrate_middleware.py +1 -0
  240. reflex/middleware/middleware.py +1 -0
  241. reflex/state.py +38 -1
  242. reflex/style.py +67 -20
  243. reflex/testing.py +6 -2
  244. reflex/utils/build.py +76 -72
  245. reflex/utils/exec.py +17 -9
  246. reflex/utils/export.py +13 -9
  247. reflex/utils/imports.py +34 -5
  248. reflex/utils/lazy_loader.py +1 -0
  249. reflex/utils/path_ops.py +39 -33
  250. reflex/utils/prerequisites.py +35 -27
  251. reflex/utils/processes.py +1 -1
  252. reflex/utils/serializers.py +3 -6
  253. reflex/utils/watch.py +3 -1
  254. reflex/vars.py +26 -10
  255. reflex/vars.pyi +3 -3
  256. {reflex-0.5.4a3.dist-info → reflex-0.5.5a1.dist-info}/METADATA +2 -2
  257. {reflex-0.5.4a3.dist-info → reflex-0.5.5a1.dist-info}/RECORD +260 -260
  258. {reflex-0.5.4a3.dist-info → reflex-0.5.5a1.dist-info}/LICENSE +0 -0
  259. {reflex-0.5.4a3.dist-info → reflex-0.5.5a1.dist-info}/WHEEL +0 -0
  260. {reflex-0.5.4a3.dist-info → reflex-0.5.5a1.dist-info}/entry_points.txt +0 -0
@@ -10,6 +10,7 @@ from .base import (
10
10
  REFLEX_VAR_CLOSING_TAG,
11
11
  REFLEX_VAR_OPENING_TAG,
12
12
  RELOAD_CONFIG,
13
+ SESSION_STORAGE,
13
14
  SKIP_COMPILE_ENV_VAR,
14
15
  ColorMode,
15
16
  Dirs,
@@ -62,7 +63,7 @@ from .route import (
62
63
  RouteRegex,
63
64
  RouteVar,
64
65
  )
65
- from .style import STYLES_DIR, Tailwind
66
+ from .style import Tailwind
66
67
 
67
68
  __ALL__ = [
68
69
  ALEMBIC_CONFIG,
@@ -88,6 +89,7 @@ __ALL__ = [
88
89
  Imports,
89
90
  IS_WINDOWS,
90
91
  LOCAL_STORAGE,
92
+ SESSION_STORAGE,
91
93
  LogLevel,
92
94
  MemoizationDisposition,
93
95
  MemoizationMode,
@@ -113,7 +115,6 @@ __ALL__ = [
113
115
  SETTER_PREFIX,
114
116
  SKIP_COMPILE_ENV_VAR,
115
117
  SocketEvent,
116
- STYLES_DIR,
117
118
  Tailwind,
118
119
  Templates,
119
120
  CompileVars,
reflex/constants/base.py CHANGED
@@ -25,30 +25,26 @@ class Dirs(SimpleNamespace):
25
25
  EXTERNAL_APP_ASSETS = "external"
26
26
  # The name of the utils file.
27
27
  UTILS = "utils"
28
- # The name of the output static directory.
29
- STATIC = "_static"
30
- # The name of the public html directory served at "/"
31
- PUBLIC = "public"
32
28
  # The name of the state file.
33
29
  STATE_PATH = "/".join([UTILS, "state"])
34
30
  # The name of the components file.
35
31
  COMPONENTS_PATH = "/".join([UTILS, "components"])
36
32
  # The name of the contexts file.
37
33
  CONTEXTS_PATH = "/".join([UTILS, "context"])
38
- # The directory where the app pages are compiled to.
39
- WEB_PAGES = os.path.join(WEB, "pages")
40
- # The directory where the static build is located.
41
- WEB_STATIC = os.path.join(WEB, STATIC)
42
- # The directory where the utils file is located.
43
- WEB_UTILS = os.path.join(WEB, UTILS)
44
- # The directory where the assets are located.
45
- WEB_ASSETS = os.path.join(WEB, PUBLIC)
46
- # The env json file.
47
- ENV_JSON = os.path.join(WEB, "env.json")
48
- # The reflex json file.
49
- REFLEX_JSON = os.path.join(WEB, "reflex.json")
50
- # The path to postcss.config.js
51
- POSTCSS_JS = os.path.join(WEB, "postcss.config.js")
34
+ # The name of the output static directory.
35
+ STATIC = "_static"
36
+ # The name of the public html directory served at "/"
37
+ PUBLIC = "public"
38
+ # The directory where styles are located.
39
+ STYLES = "styles"
40
+ # The name of the pages directory.
41
+ PAGES = "pages"
42
+ # The name of the env json file.
43
+ ENV_JSON = "env.json"
44
+ # The name of the reflex json file.
45
+ REFLEX_JSON = "reflex.json"
46
+ # The name of the postcss config file.
47
+ POSTCSS_JS = "postcss.config.js"
52
48
 
53
49
 
54
50
  class Reflex(SimpleNamespace):
@@ -61,7 +57,7 @@ class Reflex(SimpleNamespace):
61
57
  VERSION = metadata.version(MODULE_NAME)
62
58
 
63
59
  # The reflex json file.
64
- JSON = os.path.join(Dirs.WEB, "reflex.json")
60
+ JSON = "reflex.json"
65
61
 
66
62
  # Files and directories used to init a new project.
67
63
  # The directory to store reflex dependencies.
@@ -117,7 +113,7 @@ class Next(SimpleNamespace):
117
113
  # The NextJS config file
118
114
  CONFIG_FILE = "next.config.js"
119
115
  # The sitemap config file.
120
- SITEMAP_CONFIG_FILE = os.path.join(Dirs.WEB, "next-sitemap.config.js")
116
+ SITEMAP_CONFIG_FILE = "next-sitemap.config.js"
121
117
  # The node modules directory.
122
118
  NODE_MODULES = "node_modules"
123
119
  # The package lock file.
@@ -130,9 +126,11 @@ class Next(SimpleNamespace):
130
126
  class ColorMode(SimpleNamespace):
131
127
  """Constants related to ColorMode."""
132
128
 
133
- NAME = "colorMode"
129
+ NAME = "rawColorMode"
130
+ RESOLVED_NAME = "resolvedColorMode"
134
131
  USE = "useColorMode"
135
132
  TOGGLE = "toggleColorMode"
133
+ SET = "setColorMode"
136
134
 
137
135
 
138
136
  # Env modes
@@ -182,6 +180,7 @@ class Ping(SimpleNamespace):
182
180
  # Keys in the client_side_storage dict
183
181
  COOKIES = "cookies"
184
182
  LOCAL_STORAGE = "local_storage"
183
+ SESSION_STORAGE = "session_storage"
185
184
 
186
185
  # If this env var is set to "yes", App.compile will be a no-op
187
186
  SKIP_COMPILE_ENV_VAR = "__REFLEX_SKIP_COMPILE"
@@ -12,7 +12,7 @@ from reflex.utils.imports import ImportVar
12
12
  SETTER_PREFIX = "set_"
13
13
 
14
14
  # The file used to specify no compilation.
15
- NOCOMPILE_FILE = ".web/nocompile"
15
+ NOCOMPILE_FILE = "nocompile"
16
16
 
17
17
 
18
18
  class Ext(SimpleNamespace):
@@ -80,6 +80,8 @@ class PageNames(SimpleNamespace):
80
80
  DOCUMENT_ROOT = "_document"
81
81
  # The name of the theme page.
82
82
  THEME = "theme"
83
+ # The module containing components.
84
+ COMPONENTS = "components"
83
85
  # The module containing shared stateful components
84
86
  STATEFUL_COMPONENTS = "stateful_components"
85
87
 
@@ -1,4 +1,5 @@
1
1
  """Config constants."""
2
+
2
3
  import os
3
4
  from types import SimpleNamespace
4
5
 
reflex/constants/event.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Event-related constants."""
2
+
2
3
  from enum import Enum
3
4
  from types import SimpleNamespace
4
5
 
@@ -1,11 +1,12 @@
1
1
  """File for constants related to the installation process. (Bun/FNM/Node)."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import os
5
6
  import platform
6
7
  from types import SimpleNamespace
7
8
 
8
- from .base import IS_WINDOWS, Dirs, Reflex
9
+ from .base import IS_WINDOWS, Reflex
9
10
 
10
11
 
11
12
  def get_fnm_name() -> str | None:
@@ -105,7 +106,7 @@ class PackageJson(SimpleNamespace):
105
106
  EXPORT_SITEMAP = "next build && next-sitemap"
106
107
  PROD = "next start"
107
108
 
108
- PATH = os.path.join(Dirs.WEB, "package.json")
109
+ PATH = "package.json"
109
110
 
110
111
  DEPENDENCIES = {
111
112
  "@emotion/react": "11.11.1",
reflex/constants/style.py CHANGED
@@ -1,13 +1,7 @@
1
1
  """Style constants."""
2
2
 
3
- import os
4
3
  from types import SimpleNamespace
5
4
 
6
- from reflex.constants.base import Dirs
7
-
8
- # The directory where styles are located.
9
- STYLES_DIR = os.path.join(Dirs.WEB, "styles")
10
-
11
5
 
12
6
  class Tailwind(SimpleNamespace):
13
7
  """Tailwind constants."""
@@ -15,8 +9,8 @@ class Tailwind(SimpleNamespace):
15
9
  # The Tailwindcss version
16
10
  VERSION = "tailwindcss@3.3.2"
17
11
  # The Tailwind config.
18
- CONFIG = os.path.join(Dirs.WEB, "tailwind.config.js")
12
+ CONFIG = "tailwind.config.js"
19
13
  # Default Tailwind content paths
20
14
  CONTENT = ["./pages/**/*.{js,ts,jsx,tsx}", "./utils/**/*.{js,ts,jsx,tsx}"]
21
- # Relative tailwind style path to root stylesheet in STYLES_DIR.
15
+ # Relative tailwind style path to root stylesheet in Dirs.STYLES.
22
16
  ROOT_STYLE_PATH = "./tailwind.css"
reflex/event.py CHANGED
@@ -386,12 +386,12 @@ class FileUpload(Base):
386
386
  )
387
387
 
388
388
  upload_id = self.upload_id or DEFAULT_UPLOAD_ID
389
-
390
389
  spec_args = [
391
390
  (
392
391
  Var.create_safe("files", _var_is_string=False),
393
392
  Var.create_safe(
394
- f"filesById.{upload_id}", _var_is_string=False
393
+ f"filesById[{Var.create_safe(upload_id, _var_is_string=True)._var_name_unwrapped}]",
394
+ _var_is_string=False,
395
395
  )._replace(_var_data=upload_files_context_var_data),
396
396
  ),
397
397
  (
@@ -617,6 +617,34 @@ def remove_local_storage(key: str) -> EventSpec:
617
617
  )
618
618
 
619
619
 
620
+ def clear_session_storage() -> EventSpec:
621
+ """Set a value in the session storage on the frontend.
622
+
623
+ Returns:
624
+ EventSpec: An event to clear the session storage.
625
+ """
626
+ return server_side(
627
+ "_clear_session_storage",
628
+ get_fn_signature(clear_session_storage),
629
+ )
630
+
631
+
632
+ def remove_session_storage(key: str) -> EventSpec:
633
+ """Set a value in the session storage on the frontend.
634
+
635
+ Args:
636
+ key: The key identifying the variable in the session storage to remove.
637
+
638
+ Returns:
639
+ EventSpec: An event to remove an item based on the provided key in session storage.
640
+ """
641
+ return server_side(
642
+ "_remove_session_storage",
643
+ get_fn_signature(remove_session_storage),
644
+ key=key,
645
+ )
646
+
647
+
620
648
  def set_clipboard(content: str) -> EventSpec:
621
649
  """Set the text in content in the clipboard.
622
650
 
@@ -738,10 +766,12 @@ def call_script(
738
766
  callback_kwargs = {}
739
767
  if callback is not None:
740
768
  callback_kwargs = {
741
- "callback": format.format_queue_events(
742
- callback,
743
- args_spec=lambda result: [result],
744
- )
769
+ "callback": str(
770
+ format.format_queue_events(
771
+ callback,
772
+ args_spec=lambda result: [result],
773
+ ),
774
+ ),
745
775
  }
746
776
  return server_side(
747
777
  "_call_script",
@@ -1,4 +1,5 @@
1
1
  """Helper functions for adding assets to the app."""
2
+
2
3
  import inspect
3
4
  from pathlib import Path
4
5
  from typing import Optional
@@ -1,4 +1,5 @@
1
1
  """Handle client side state with `useState`."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  import dataclasses
@@ -8,7 +9,7 @@ from typing import Any, Callable, Optional, Type, Union
8
9
  from reflex import constants
9
10
  from reflex.event import EventChain, EventHandler, EventSpec, call_script
10
11
  from reflex.utils.imports import ImportVar
11
- from reflex.vars import Var, VarData
12
+ from reflex.vars import Var, VarData, get_unique_variable_name
12
13
 
13
14
  NoValue = object()
14
15
 
@@ -74,7 +75,10 @@ class ClientStateVar(Var):
74
75
 
75
76
  @classmethod
76
77
  def create(
77
- cls, var_name: str, default: Any = NoValue, global_ref: bool = True
78
+ cls,
79
+ var_name: str | None = None,
80
+ default: Any = NoValue,
81
+ global_ref: bool = True,
78
82
  ) -> "ClientStateVar":
79
83
  """Create a local_state Var that can be accessed and updated on the client.
80
84
 
@@ -101,6 +105,8 @@ class ClientStateVar(Var):
101
105
  Returns:
102
106
  ClientStateVar
103
107
  """
108
+ if var_name is None:
109
+ var_name = get_unique_variable_name()
104
110
  assert isinstance(var_name, str), "var_name must be a string."
105
111
  if default is NoValue:
106
112
  default_var = Var.create_safe("", _var_is_local=False, _var_is_string=False)
@@ -188,7 +194,7 @@ class ClientStateVar(Var):
188
194
  # This is a hack to make it work like an EventSpec taking an arg
189
195
  value = Var.create_safe(value, _var_is_string=isinstance(value, str))
190
196
  if not value._var_is_string and value._var_full_name.startswith("_"):
191
- arg = value._var_name_unwrapped
197
+ arg = value._var_name_unwrapped.partition(".")[0]
192
198
  else:
193
199
  arg = ""
194
200
  setter = f"({arg}) => {setter}({value._var_name_unwrapped})"
@@ -1,4 +1,5 @@
1
1
  """Add standard Hooks wrapper for React."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from reflex.utils.imports import ImportVar
@@ -1,12 +1,21 @@
1
1
  """Miscellaneous functions for the experimental package."""
2
2
 
3
3
  import asyncio
4
+ from typing import Any
4
5
 
5
6
 
6
- async def run_in_thread(func):
7
+ async def run_in_thread(func) -> Any:
7
8
  """Run a function in a separate thread.
8
9
 
10
+ To not block the UI event queue, run_in_thread must be inside inside a rx.background() decorated method.
11
+
9
12
  Args:
10
- func (callable): The function to run.
13
+ func (callable): The non-async function to run.
14
+
15
+ Returns:
16
+ Any: The return value of the function.
11
17
  """
12
- await asyncio.get_event_loop().run_in_executor(None, func)
18
+ assert not asyncio.coroutines.iscoroutinefunction(
19
+ func
20
+ ), "func must be a non-async function"
21
+ return await asyncio.get_event_loop().run_in_executor(None, func)
@@ -1,4 +1,5 @@
1
1
  """Middleware to hydrate the state."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from typing import TYPE_CHECKING, Optional
@@ -1,4 +1,5 @@
1
1
  """Base Reflex middleware."""
2
+
2
3
  from __future__ import annotations
3
4
 
4
5
  from abc import ABC
reflex/state.py CHANGED
@@ -1988,6 +1988,7 @@ class StateProxy(wrapt.ObjectProxy):
1988
1988
  self._self_substate_path = state_instance.get_full_name().split(".")
1989
1989
  self._self_actx = None
1990
1990
  self._self_mutable = False
1991
+ self._self_actx_lock = asyncio.Lock()
1991
1992
 
1992
1993
  async def __aenter__(self) -> StateProxy:
1993
1994
  """Enter the async context manager protocol.
@@ -2001,6 +2002,7 @@ class StateProxy(wrapt.ObjectProxy):
2001
2002
  Returns:
2002
2003
  This StateProxy instance in mutable mode.
2003
2004
  """
2005
+ await self._self_actx_lock.acquire()
2004
2006
  self._self_actx = self._self_app.modify_state(
2005
2007
  token=_substate_key(
2006
2008
  self.__wrapped__.router.session.client_token,
@@ -2025,7 +2027,10 @@ class StateProxy(wrapt.ObjectProxy):
2025
2027
  if self._self_actx is None:
2026
2028
  return
2027
2029
  self._self_mutable = False
2028
- await self._self_actx.__aexit__(*exc_info)
2030
+ try:
2031
+ await self._self_actx.__aexit__(*exc_info)
2032
+ finally:
2033
+ self._self_actx_lock.release()
2029
2034
  self._self_actx = None
2030
2035
 
2031
2036
  def __enter__(self):
@@ -2835,6 +2840,38 @@ class LocalStorage(ClientStorageBase, str):
2835
2840
  return inst
2836
2841
 
2837
2842
 
2843
+ class SessionStorage(ClientStorageBase, str):
2844
+ """Represents a state Var that is stored in sessionStorage in the browser."""
2845
+
2846
+ name: str | None
2847
+
2848
+ def __new__(
2849
+ cls,
2850
+ object: Any = "",
2851
+ encoding: str | None = None,
2852
+ errors: str | None = None,
2853
+ /,
2854
+ name: str | None = None,
2855
+ ) -> "SessionStorage":
2856
+ """Create a client-side sessionStorage (str).
2857
+
2858
+ Args:
2859
+ object: The initial object.
2860
+ encoding: The encoding to use.
2861
+ errors: The error handling scheme to use
2862
+ name: The name of the storage on the client side
2863
+
2864
+ Returns:
2865
+ The client-side sessionStorage object.
2866
+ """
2867
+ if encoding or errors:
2868
+ inst = super().__new__(cls, object, encoding or "utf-8", errors or "strict")
2869
+ else:
2870
+ inst = super().__new__(cls, object)
2871
+ inst.name = name
2872
+ return inst
2873
+
2874
+
2838
2875
  class MutableProxy(wrapt.ObjectProxy):
2839
2876
  """A proxy for a mutable object that tracks changes."""
2840
2877
 
reflex/style.py CHANGED
@@ -2,41 +2,88 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Any, Tuple
5
+ from typing import Any, Literal, Tuple, Type
6
6
 
7
7
  from reflex import constants
8
8
  from reflex.event import EventChain
9
9
  from reflex.utils import format
10
10
  from reflex.utils.imports import ImportVar
11
- from reflex.vars import BaseVar, Var, VarData
11
+ from reflex.vars import BaseVar, CallableVar, Var, VarData
12
12
 
13
13
  VarData.update_forward_refs() # Ensure all type definitions are resolved
14
14
 
15
15
  SYSTEM_COLOR_MODE: str = "system"
16
16
  LIGHT_COLOR_MODE: str = "light"
17
17
  DARK_COLOR_MODE: str = "dark"
18
+ LiteralColorMode = Literal["system", "light", "dark"]
18
19
 
19
20
  # Reference the global ColorModeContext
20
- color_mode_var_data = VarData(
21
- imports={
22
- f"/{constants.Dirs.CONTEXTS_PATH}": [ImportVar(tag="ColorModeContext")],
23
- "react": [ImportVar(tag="useContext")],
24
- },
25
- hooks={
26
- f"const [ {constants.ColorMode.NAME}, {constants.ColorMode.TOGGLE} ] = useContext(ColorModeContext)": None,
27
- },
28
- )
29
- # Var resolves to the current color mode for the app ("light" or "dark")
30
- color_mode = BaseVar(
31
- _var_name=constants.ColorMode.NAME,
32
- _var_type="str",
33
- _var_data=color_mode_var_data,
34
- )
21
+ color_mode_imports = {
22
+ f"/{constants.Dirs.CONTEXTS_PATH}": [ImportVar(tag="ColorModeContext")],
23
+ "react": [ImportVar(tag="useContext")],
24
+ }
25
+
26
+
27
+ def _color_mode_var(_var_name: str, _var_type: Type = str) -> BaseVar:
28
+ """Create a Var that destructs the _var_name from ColorModeContext.
29
+
30
+ Args:
31
+ _var_name: The name of the variable to get from ColorModeContext.
32
+ _var_type: The type of the Var.
33
+
34
+ Returns:
35
+ The BaseVar for accessing _var_name from ColorModeContext.
36
+ """
37
+ return BaseVar(
38
+ _var_name=_var_name,
39
+ _var_type=_var_type,
40
+ _var_is_local=False,
41
+ _var_is_string=False,
42
+ _var_data=VarData(
43
+ imports=color_mode_imports,
44
+ hooks={f"const {{ {_var_name} }} = useContext(ColorModeContext)": None},
45
+ ),
46
+ )
47
+
48
+
49
+ @CallableVar
50
+ def set_color_mode(
51
+ new_color_mode: LiteralColorMode | Var[LiteralColorMode] | None = None,
52
+ ) -> BaseVar[EventChain]:
53
+ """Create an EventChain Var that sets the color mode to a specific value.
54
+
55
+ Note: `set_color_mode` is not a real event and cannot be triggered from a
56
+ backend event handler.
57
+
58
+ Args:
59
+ new_color_mode: The color mode to set.
60
+
61
+ Returns:
62
+ The EventChain Var that can be passed to an event trigger.
63
+ """
64
+ base_setter = _color_mode_var(
65
+ _var_name=constants.ColorMode.SET,
66
+ _var_type=EventChain,
67
+ )
68
+ if new_color_mode is None:
69
+ return base_setter
70
+
71
+ if not isinstance(new_color_mode, Var):
72
+ new_color_mode = Var.create_safe(new_color_mode, _var_is_string=True)
73
+ return base_setter._replace(
74
+ _var_name=f"() => {base_setter._var_name}({new_color_mode._var_name_unwrapped})",
75
+ merge_var_data=new_color_mode._var_data,
76
+ )
77
+
78
+
79
+ # Var resolves to the current color mode for the app ("light", "dark" or "system")
80
+ color_mode = _color_mode_var(_var_name=constants.ColorMode.NAME)
81
+ # Var resolves to the resolved color mode for the app ("light" or "dark")
82
+ resolved_color_mode = _color_mode_var(_var_name=constants.ColorMode.RESOLVED_NAME)
35
83
  # Var resolves to a function invocation that toggles the color mode
36
- toggle_color_mode = BaseVar(
84
+ toggle_color_mode = _color_mode_var(
37
85
  _var_name=constants.ColorMode.TOGGLE,
38
86
  _var_type=EventChain,
39
- _var_data=color_mode_var_data,
40
87
  )
41
88
 
42
89
  breakpoints = ["0", "30em", "48em", "62em", "80em", "96em"]
@@ -273,7 +320,7 @@ def format_as_emotion(style_dict: dict[str, Any]) -> Style | None:
273
320
 
274
321
 
275
322
  def convert_dict_to_style_and_format_emotion(
276
- raw_dict: dict[str, Any]
323
+ raw_dict: dict[str, Any],
277
324
  ) -> dict[str, Any] | None:
278
325
  """Convert a dict to a style dict and then format as emotion.
279
326
 
reflex/testing.py CHANGED
@@ -330,7 +330,7 @@ class AppHarness:
330
330
  # Start the frontend.
331
331
  self.frontend_process = reflex.utils.processes.new_process(
332
332
  [reflex.utils.prerequisites.get_package_manager(), "run", "dev"],
333
- cwd=self.app_path / reflex.constants.Dirs.WEB,
333
+ cwd=self.app_path / reflex.utils.prerequisites.get_web_dir(),
334
334
  env={"PORT": "0"},
335
335
  **FRONTEND_POPEN_ARGS,
336
336
  )
@@ -854,7 +854,11 @@ class AppHarnessProd(AppHarness):
854
854
  frontend_server: Optional[Subdir404TCPServer] = None
855
855
 
856
856
  def _run_frontend(self):
857
- web_root = self.app_path / reflex.constants.Dirs.WEB_STATIC
857
+ web_root = (
858
+ self.app_path
859
+ / reflex.utils.prerequisites.get_web_dir()
860
+ / reflex.constants.Dirs.STATIC
861
+ )
858
862
  error_page_map = {
859
863
  404: web_root / "404.html",
860
864
  }