reflex 0.5.3a2__py3-none-any.whl → 0.5.4a1__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.
- reflex/.templates/apps/demo/code/webui/state.py +3 -2
- reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +19 -20
- reflex/.templates/web/utils/state.js +6 -0
- reflex/__init__.py +7 -1
- reflex/__init__.pyi +2 -0
- reflex/app.py +2 -5
- reflex/compiler/compiler.py +2 -2
- reflex/components/component.py +19 -6
- reflex/components/core/client_side_routing.py +2 -2
- reflex/components/core/client_side_routing.pyi +1 -0
- reflex/components/core/upload.py +1 -1
- reflex/components/datadisplay/dataeditor.py +7 -2
- reflex/components/datadisplay/dataeditor.pyi +1 -0
- reflex/components/el/elements/forms.py +18 -11
- reflex/components/el/elements/forms.pyi +1 -0
- reflex/components/markdown/markdown.py +1 -1
- reflex/components/plotly/plotly.py +76 -12
- reflex/components/plotly/plotly.pyi +15 -82
- reflex/components/radix/themes/base.py +9 -2
- reflex/components/radix/themes/base.pyi +1 -0
- reflex/components/recharts/cartesian.py +42 -14
- reflex/components/recharts/cartesian.pyi +81 -17
- reflex/components/recharts/charts.py +12 -21
- reflex/components/recharts/charts.pyi +53 -14
- reflex/components/sonner/toast.py +30 -14
- reflex/components/sonner/toast.pyi +8 -4
- reflex/config.py +22 -14
- reflex/constants/__init__.py +2 -0
- reflex/constants/config.py +7 -0
- reflex/event.py +12 -6
- reflex/experimental/__init__.py +22 -2
- reflex/experimental/client_state.py +81 -23
- reflex/experimental/hooks.py +29 -35
- reflex/experimental/layout.py +8 -3
- reflex/experimental/layout.pyi +536 -0
- reflex/reflex.py +9 -5
- reflex/style.py +1 -0
- reflex/testing.py +44 -13
- reflex/utils/format.py +8 -1
- reflex/utils/processes.py +27 -0
- reflex/utils/pyi_generator.py +11 -4
- reflex/utils/serializers.py +114 -15
- reflex/utils/types.py +6 -2
- reflex/vars.py +39 -10
- reflex/vars.pyi +2 -2
- {reflex-0.5.3a2.dist-info → reflex-0.5.4a1.dist-info}/METADATA +1 -1
- {reflex-0.5.3a2.dist-info → reflex-0.5.4a1.dist-info}/RECORD +50 -49
- {reflex-0.5.3a2.dist-info → reflex-0.5.4a1.dist-info}/LICENSE +0 -0
- {reflex-0.5.3a2.dist-info → reflex-0.5.4a1.dist-info}/WHEEL +0 -0
- {reflex-0.5.3a2.dist-info → reflex-0.5.4a1.dist-info}/entry_points.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"""Handle client side state with `useState`."""
|
|
2
|
+
from __future__ import annotations
|
|
2
3
|
|
|
3
4
|
import dataclasses
|
|
4
5
|
import sys
|
|
@@ -9,6 +10,13 @@ from reflex.event import EventChain, EventHandler, EventSpec, call_script
|
|
|
9
10
|
from reflex.utils.imports import ImportVar
|
|
10
11
|
from reflex.vars import Var, VarData
|
|
11
12
|
|
|
13
|
+
NoValue = object()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
_refs_import = {
|
|
17
|
+
f"/{constants.Dirs.STATE_PATH}": [ImportVar(tag="refs")],
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
|
|
13
21
|
def _client_state_ref(var_name: str) -> str:
|
|
14
22
|
"""Get the ref path for a ClientStateVar.
|
|
@@ -36,6 +44,9 @@ class ClientStateVar(Var):
|
|
|
36
44
|
_setter_name: str = dataclasses.field()
|
|
37
45
|
_getter_name: str = dataclasses.field()
|
|
38
46
|
|
|
47
|
+
# Whether to add the var and setter to the global `refs` object for use in any Component.
|
|
48
|
+
_global_ref: bool = dataclasses.field(default=True)
|
|
49
|
+
|
|
39
50
|
# The type of the var.
|
|
40
51
|
_var_type: Type = dataclasses.field(default=Any)
|
|
41
52
|
|
|
@@ -62,7 +73,9 @@ class ClientStateVar(Var):
|
|
|
62
73
|
)
|
|
63
74
|
|
|
64
75
|
@classmethod
|
|
65
|
-
def create(
|
|
76
|
+
def create(
|
|
77
|
+
cls, var_name: str, default: Any = NoValue, global_ref: bool = True
|
|
78
|
+
) -> "ClientStateVar":
|
|
66
79
|
"""Create a local_state Var that can be accessed and updated on the client.
|
|
67
80
|
|
|
68
81
|
The `ClientStateVar` should be included in the highest parent component
|
|
@@ -72,7 +85,7 @@ class ClientStateVar(Var):
|
|
|
72
85
|
|
|
73
86
|
To render the var in a component, use the `value` property.
|
|
74
87
|
|
|
75
|
-
To update the var in a component, use the `set` property.
|
|
88
|
+
To update the var in a component, use the `set` property or `set_value` method.
|
|
76
89
|
|
|
77
90
|
To access the var in an event handler, use the `retrieve` method with
|
|
78
91
|
`callback` set to the event handler which should receive the value.
|
|
@@ -83,36 +96,45 @@ class ClientStateVar(Var):
|
|
|
83
96
|
Args:
|
|
84
97
|
var_name: The name of the variable.
|
|
85
98
|
default: The default value of the variable.
|
|
99
|
+
global_ref: Whether the state should be accessible in any Component and on the backend.
|
|
86
100
|
|
|
87
101
|
Returns:
|
|
88
102
|
ClientStateVar
|
|
89
103
|
"""
|
|
90
|
-
|
|
104
|
+
assert isinstance(var_name, str), "var_name must be a string."
|
|
105
|
+
if default is NoValue:
|
|
91
106
|
default_var = Var.create_safe("", _var_is_local=False, _var_is_string=False)
|
|
92
107
|
elif not isinstance(default, Var):
|
|
93
|
-
default_var = Var.create_safe(
|
|
108
|
+
default_var = Var.create_safe(
|
|
109
|
+
default,
|
|
110
|
+
_var_is_string=isinstance(default, str),
|
|
111
|
+
)
|
|
94
112
|
else:
|
|
95
113
|
default_var = default
|
|
96
114
|
setter_name = f"set{var_name.capitalize()}"
|
|
115
|
+
hooks = {
|
|
116
|
+
f"const [{var_name}, {setter_name}] = useState({default_var._var_name_unwrapped})": None,
|
|
117
|
+
}
|
|
118
|
+
imports = {
|
|
119
|
+
"react": [ImportVar(tag="useState")],
|
|
120
|
+
}
|
|
121
|
+
if global_ref:
|
|
122
|
+
hooks[f"{_client_state_ref(var_name)} = {var_name}"] = None
|
|
123
|
+
hooks[f"{_client_state_ref(setter_name)} = {setter_name}"] = None
|
|
124
|
+
imports.update(_refs_import)
|
|
97
125
|
return cls(
|
|
98
126
|
_var_name="",
|
|
99
127
|
_setter_name=setter_name,
|
|
100
128
|
_getter_name=var_name,
|
|
129
|
+
_global_ref=global_ref,
|
|
101
130
|
_var_is_local=False,
|
|
102
131
|
_var_is_string=False,
|
|
103
132
|
_var_type=default_var._var_type,
|
|
104
133
|
_var_data=VarData.merge(
|
|
105
134
|
default_var._var_data,
|
|
106
135
|
VarData( # type: ignore
|
|
107
|
-
hooks=
|
|
108
|
-
|
|
109
|
-
f"{_client_state_ref(var_name)} = {var_name}": None,
|
|
110
|
-
f"{_client_state_ref(setter_name)} = {setter_name}": None,
|
|
111
|
-
},
|
|
112
|
-
imports={
|
|
113
|
-
"react": [ImportVar(tag="useState", install=False)],
|
|
114
|
-
f"/{constants.Dirs.STATE_PATH}": [ImportVar(tag="refs")],
|
|
115
|
-
},
|
|
136
|
+
hooks=hooks,
|
|
137
|
+
imports=imports,
|
|
116
138
|
),
|
|
117
139
|
),
|
|
118
140
|
)
|
|
@@ -130,47 +152,73 @@ class ClientStateVar(Var):
|
|
|
130
152
|
"""
|
|
131
153
|
return (
|
|
132
154
|
Var.create_safe(
|
|
133
|
-
_client_state_ref(self._getter_name)
|
|
155
|
+
_client_state_ref(self._getter_name)
|
|
156
|
+
if self._global_ref
|
|
157
|
+
else self._getter_name,
|
|
134
158
|
_var_is_local=False,
|
|
135
159
|
_var_is_string=False,
|
|
136
160
|
)
|
|
137
161
|
.to(self._var_type)
|
|
138
162
|
._replace(
|
|
139
163
|
merge_var_data=VarData( # type: ignore
|
|
140
|
-
imports={
|
|
141
|
-
f"/{constants.Dirs.STATE_PATH}": [ImportVar(tag="refs")],
|
|
142
|
-
}
|
|
164
|
+
imports=_refs_import if self._global_ref else {}
|
|
143
165
|
)
|
|
144
166
|
)
|
|
145
167
|
)
|
|
146
168
|
|
|
147
|
-
|
|
148
|
-
def set(self) -> Var:
|
|
169
|
+
def set_value(self, value: Any = NoValue) -> Var:
|
|
149
170
|
"""Set the value of the client state variable.
|
|
150
171
|
|
|
151
172
|
This property can only be attached to a frontend event trigger.
|
|
152
173
|
|
|
153
174
|
To set a value from a backend event handler, see `push`.
|
|
154
175
|
|
|
176
|
+
Args:
|
|
177
|
+
value: The value to set.
|
|
178
|
+
|
|
155
179
|
Returns:
|
|
156
180
|
A special EventChain Var which will set the value when triggered.
|
|
157
181
|
"""
|
|
182
|
+
setter = (
|
|
183
|
+
_client_state_ref(self._setter_name)
|
|
184
|
+
if self._global_ref
|
|
185
|
+
else self._setter_name
|
|
186
|
+
)
|
|
187
|
+
if value is not NoValue:
|
|
188
|
+
# This is a hack to make it work like an EventSpec taking an arg
|
|
189
|
+
value = Var.create_safe(value, _var_is_string=isinstance(value, str))
|
|
190
|
+
if not value._var_is_string and value._var_full_name.startswith("_"):
|
|
191
|
+
arg = value._var_name_unwrapped
|
|
192
|
+
else:
|
|
193
|
+
arg = ""
|
|
194
|
+
setter = f"({arg}) => {setter}({value._var_name_unwrapped})"
|
|
158
195
|
return (
|
|
159
196
|
Var.create_safe(
|
|
160
|
-
|
|
197
|
+
setter,
|
|
161
198
|
_var_is_local=False,
|
|
162
199
|
_var_is_string=False,
|
|
163
200
|
)
|
|
164
201
|
.to(EventChain)
|
|
165
202
|
._replace(
|
|
166
203
|
merge_var_data=VarData( # type: ignore
|
|
167
|
-
imports={
|
|
168
|
-
f"/{constants.Dirs.STATE_PATH}": [ImportVar(tag="refs")],
|
|
169
|
-
}
|
|
204
|
+
imports=_refs_import if self._global_ref else {}
|
|
170
205
|
)
|
|
171
206
|
)
|
|
172
207
|
)
|
|
173
208
|
|
|
209
|
+
@property
|
|
210
|
+
def set(self) -> Var:
|
|
211
|
+
"""Set the value of the client state variable.
|
|
212
|
+
|
|
213
|
+
This property can only be attached to a frontend event trigger.
|
|
214
|
+
|
|
215
|
+
To set a value from a backend event handler, see `push`.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
A special EventChain Var which will set the value when triggered.
|
|
219
|
+
"""
|
|
220
|
+
return self.set_value()
|
|
221
|
+
|
|
174
222
|
def retrieve(
|
|
175
223
|
self, callback: Union[EventHandler, Callable, None] = None
|
|
176
224
|
) -> EventSpec:
|
|
@@ -183,7 +231,12 @@ class ClientStateVar(Var):
|
|
|
183
231
|
|
|
184
232
|
Returns:
|
|
185
233
|
An EventSpec which will retrieve the value when triggered.
|
|
234
|
+
|
|
235
|
+
Raises:
|
|
236
|
+
ValueError: If the ClientStateVar is not global.
|
|
186
237
|
"""
|
|
238
|
+
if not self._global_ref:
|
|
239
|
+
raise ValueError("ClientStateVar must be global to retrieve the value.")
|
|
187
240
|
return call_script(_client_state_ref(self._getter_name), callback=callback)
|
|
188
241
|
|
|
189
242
|
def push(self, value: Any) -> EventSpec:
|
|
@@ -196,5 +249,10 @@ class ClientStateVar(Var):
|
|
|
196
249
|
|
|
197
250
|
Returns:
|
|
198
251
|
An EventSpec which will push the value when triggered.
|
|
252
|
+
|
|
253
|
+
Raises:
|
|
254
|
+
ValueError: If the ClientStateVar is not global.
|
|
199
255
|
"""
|
|
256
|
+
if not self._global_ref:
|
|
257
|
+
raise ValueError("ClientStateVar must be global to push the value.")
|
|
200
258
|
return call_script(f"{_client_state_ref(self._setter_name)}({value})")
|
reflex/experimental/hooks.py
CHANGED
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
"""Add standard Hooks wrapper for React."""
|
|
2
|
-
|
|
3
|
-
from typing import Optional, Union
|
|
2
|
+
from __future__ import annotations
|
|
4
3
|
|
|
5
4
|
from reflex.utils.imports import ImportVar
|
|
6
5
|
from reflex.vars import Var, VarData
|
|
7
6
|
|
|
8
7
|
|
|
9
|
-
def
|
|
10
|
-
|
|
11
|
-
return
|
|
12
|
-
|
|
13
|
-
if isinstance(tags, str):
|
|
14
|
-
tags = [tags]
|
|
15
|
-
|
|
16
|
-
v._var_data = VarData( # type: ignore
|
|
17
|
-
imports={"react": [ImportVar(tag=tag, install=False) for tag in tags]},
|
|
18
|
-
)
|
|
8
|
+
def _compose_react_imports(tags: list[str]) -> dict[str, list[ImportVar]]:
|
|
9
|
+
return {"react": [ImportVar(tag=tag, install=False) for tag in tags]}
|
|
19
10
|
|
|
20
11
|
|
|
21
|
-
def const(name, value) ->
|
|
12
|
+
def const(name, value) -> Var:
|
|
22
13
|
"""Create a constant Var.
|
|
23
14
|
|
|
24
15
|
Args:
|
|
@@ -29,11 +20,11 @@ def const(name, value) -> Optional[Var]:
|
|
|
29
20
|
The constant Var.
|
|
30
21
|
"""
|
|
31
22
|
if isinstance(name, list):
|
|
32
|
-
return Var.
|
|
33
|
-
return Var.
|
|
23
|
+
return Var.create_safe(f"const [{', '.join(name)}] = {value}")
|
|
24
|
+
return Var.create_safe(f"const {name} = {value}")
|
|
34
25
|
|
|
35
26
|
|
|
36
|
-
def useCallback(func, deps) ->
|
|
27
|
+
def useCallback(func, deps) -> Var:
|
|
37
28
|
"""Create a useCallback hook with a function and dependencies.
|
|
38
29
|
|
|
39
30
|
Args:
|
|
@@ -43,15 +34,13 @@ def useCallback(func, deps) -> Optional[Var]:
|
|
|
43
34
|
Returns:
|
|
44
35
|
The useCallback hook.
|
|
45
36
|
"""
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
_add_react_import(v, "useCallback")
|
|
51
|
-
return v
|
|
37
|
+
return Var.create_safe(
|
|
38
|
+
f"useCallback({func}, {deps})" if deps else f"useCallback({func})",
|
|
39
|
+
_var_data=VarData(imports=_compose_react_imports(["useCallback"])),
|
|
40
|
+
)
|
|
52
41
|
|
|
53
42
|
|
|
54
|
-
def useContext(context) ->
|
|
43
|
+
def useContext(context) -> Var:
|
|
55
44
|
"""Create a useContext hook with a context.
|
|
56
45
|
|
|
57
46
|
Args:
|
|
@@ -60,12 +49,13 @@ def useContext(context) -> Optional[Var]:
|
|
|
60
49
|
Returns:
|
|
61
50
|
The useContext hook.
|
|
62
51
|
"""
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
52
|
+
return Var.create_safe(
|
|
53
|
+
f"useContext({context})",
|
|
54
|
+
_var_data=VarData(imports=_compose_react_imports(["useContext"])),
|
|
55
|
+
)
|
|
66
56
|
|
|
67
57
|
|
|
68
|
-
def useRef(default) ->
|
|
58
|
+
def useRef(default) -> Var:
|
|
69
59
|
"""Create a useRef hook with a default value.
|
|
70
60
|
|
|
71
61
|
Args:
|
|
@@ -74,12 +64,13 @@ def useRef(default) -> Optional[Var]:
|
|
|
74
64
|
Returns:
|
|
75
65
|
The useRef hook.
|
|
76
66
|
"""
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
67
|
+
return Var.create_safe(
|
|
68
|
+
f"useRef({default})",
|
|
69
|
+
_var_data=VarData(imports=_compose_react_imports(["useRef"])),
|
|
70
|
+
)
|
|
80
71
|
|
|
81
72
|
|
|
82
|
-
def useState(var_name, default=None) ->
|
|
73
|
+
def useState(var_name, default=None) -> Var:
|
|
83
74
|
"""Create a useState hook with a variable name and setter name.
|
|
84
75
|
|
|
85
76
|
Args:
|
|
@@ -89,7 +80,10 @@ def useState(var_name, default=None) -> Optional[Var]:
|
|
|
89
80
|
Returns:
|
|
90
81
|
A useState hook.
|
|
91
82
|
"""
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
83
|
+
return const(
|
|
84
|
+
[var_name, f"set{var_name.capitalize()}"],
|
|
85
|
+
Var.create_safe(
|
|
86
|
+
f"useState({default})",
|
|
87
|
+
_var_data=VarData(imports=_compose_react_imports(["useState"])),
|
|
88
|
+
),
|
|
89
|
+
)
|
reflex/experimental/layout.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any, List
|
|
6
6
|
|
|
7
7
|
from reflex import color, cond
|
|
8
8
|
from reflex.components.base.fragment import Fragment
|
|
@@ -65,8 +65,13 @@ class Sidebar(Box, MemoizationLeaf):
|
|
|
65
65
|
}
|
|
66
66
|
)
|
|
67
67
|
|
|
68
|
-
def
|
|
69
|
-
|
|
68
|
+
def add_hooks(self) -> List[Var]:
|
|
69
|
+
"""Get the hooks to render.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
The hooks for the sidebar.
|
|
73
|
+
"""
|
|
74
|
+
return [hooks.useState("open", "true")] if not self.State else []
|
|
70
75
|
|
|
71
76
|
|
|
72
77
|
class StatefulSidebar(ComponentState):
|