reflex 0.5.3a2__py3-none-any.whl → 0.5.4__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/chakra/base.py +3 -1
- reflex/components/chakra/forms/checkbox.py +1 -1
- reflex/components/chakra/forms/pininput.py +1 -1
- reflex/components/chakra/forms/rangeslider.py +1 -1
- reflex/components/chakra/navigation/link.py +3 -1
- reflex/components/component.py +43 -15
- reflex/components/core/banner.py +2 -1
- reflex/components/core/client_side_routing.py +3 -3
- reflex/components/core/client_side_routing.pyi +1 -0
- reflex/components/core/debounce.py +3 -1
- reflex/components/core/foreach.py +1 -1
- reflex/components/core/upload.py +2 -1
- reflex/components/datadisplay/code.py +4 -1
- reflex/components/datadisplay/dataeditor.py +11 -8
- reflex/components/datadisplay/dataeditor.pyi +1 -0
- reflex/components/el/elements/forms.py +25 -14
- reflex/components/el/elements/forms.pyi +2 -1
- reflex/components/markdown/markdown.py +17 -11
- reflex/components/markdown/markdown.pyi +12 -8
- reflex/components/plotly/plotly.py +82 -14
- reflex/components/plotly/plotly.pyi +15 -82
- reflex/components/radix/primitives/accordion.py +1 -1
- reflex/components/radix/themes/base.py +10 -2
- reflex/components/radix/themes/base.pyi +1 -0
- reflex/components/radix/themes/color_mode.py +1 -1
- reflex/components/radix/themes/components/checkbox.py +3 -1
- reflex/components/radix/themes/components/radio_group.py +6 -4
- reflex/components/radix/themes/components/separator.py +1 -1
- reflex/components/radix/themes/layout/container.py +1 -1
- reflex/components/radix/themes/layout/section.py +1 -1
- 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 +37 -17
- reflex/components/sonner/toast.pyi +9 -5
- reflex/components/tags/tag.py +2 -1
- reflex/config.py +22 -14
- reflex/constants/__init__.py +2 -0
- reflex/constants/config.py +7 -0
- reflex/event.py +24 -15
- reflex/experimental/__init__.py +22 -2
- reflex/experimental/client_state.py +81 -23
- reflex/experimental/hooks.py +35 -35
- reflex/experimental/layout.py +17 -5
- reflex/experimental/layout.pyi +536 -0
- reflex/reflex.py +9 -5
- reflex/style.py +3 -2
- reflex/testing.py +44 -13
- reflex/utils/compat.py +5 -0
- reflex/utils/format.py +12 -2
- 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 +57 -20
- reflex/vars.pyi +2 -2
- {reflex-0.5.3a2.dist-info → reflex-0.5.4.dist-info}/METADATA +1 -1
- {reflex-0.5.3a2.dist-info → reflex-0.5.4.dist-info}/RECORD +69 -68
- {reflex-0.5.3a2.dist-info → reflex-0.5.4.dist-info}/LICENSE +0 -0
- {reflex-0.5.3a2.dist-info → reflex-0.5.4.dist-info}/WHEEL +0 -0
- {reflex-0.5.3a2.dist-info → reflex-0.5.4.dist-info}/entry_points.txt +0 -0
|
@@ -11,6 +11,7 @@ from typing import Any, Dict, List, Union
|
|
|
11
11
|
from reflex.components.component import Component
|
|
12
12
|
from reflex.components.recharts.general import ResponsiveContainer
|
|
13
13
|
from reflex.constants import EventTriggers
|
|
14
|
+
from reflex.event import EventHandler
|
|
14
15
|
from reflex.vars import Var
|
|
15
16
|
from .recharts import (
|
|
16
17
|
LiteralAnimationEasing,
|
|
@@ -105,12 +106,6 @@ class AreaChart(ChartBase):
|
|
|
105
106
|
Union[int, Literal["dataMin", "dataMax", "auto"]],
|
|
106
107
|
]
|
|
107
108
|
] = None,
|
|
108
|
-
stack_offset: Optional[
|
|
109
|
-
Union[
|
|
110
|
-
Var[Literal["expand", "none", "wiggle", "silhouette"]],
|
|
111
|
-
Literal["expand", "none", "wiggle", "silhouette"],
|
|
112
|
-
]
|
|
113
|
-
] = None,
|
|
114
109
|
data: Optional[Union[Var[List[Dict[str, Any]]], List[Dict[str, Any]]]] = None,
|
|
115
110
|
sync_id: Optional[Union[Var[str], str]] = None,
|
|
116
111
|
sync_method: Optional[
|
|
@@ -125,6 +120,12 @@ class AreaChart(ChartBase):
|
|
|
125
120
|
]
|
|
126
121
|
] = None,
|
|
127
122
|
margin: Optional[Union[Var[Dict[str, Any]], Dict[str, Any]]] = None,
|
|
123
|
+
stack_offset: Optional[
|
|
124
|
+
Union[
|
|
125
|
+
Var[Literal["expand", "none", "wiggle", "silhouette"]],
|
|
126
|
+
Literal["expand", "none", "wiggle", "silhouette"],
|
|
127
|
+
]
|
|
128
|
+
] = None,
|
|
128
129
|
style: Optional[Style] = None,
|
|
129
130
|
key: Optional[Any] = None,
|
|
130
131
|
id: Optional[Any] = None,
|
|
@@ -150,7 +151,6 @@ class AreaChart(ChartBase):
|
|
|
150
151
|
Args:
|
|
151
152
|
*children: The children of the chart component.
|
|
152
153
|
base_value: The base value of area. Number | 'dataMin' | 'dataMax' | 'auto'
|
|
153
|
-
stack_offset: The type of offset function used to generate the lower and upper values in the series array. The four types are built-in offsets in d3-shape. 'expand' | 'none' | 'wiggle' | 'silhouette'
|
|
154
154
|
data: The source data, in which each element is an object.
|
|
155
155
|
sync_id: If any two categorical charts(rx.line_chart, rx.area_chart, rx.bar_chart, rx.composed_chart) have the same sync_id, these two charts can sync the position GraphingTooltip, and the start_index, end_index of Brush.
|
|
156
156
|
sync_method: When sync_id is provided, allows customisation of how the charts will synchronize GraphingTooltips and brushes. Using 'index' (default setting), other charts will reuse current datum's index within the data array. In cases where data does not have the same length, this might yield unexpected results. In that case use 'value' which will try to match other charts values, or a fully custom function which will receive tick, data as argument and should return an index. 'index' | 'value' | function
|
|
@@ -158,6 +158,7 @@ class AreaChart(ChartBase):
|
|
|
158
158
|
height: The height of chart container.
|
|
159
159
|
layout: The layout of area in the chart. 'horizontal' | 'vertical'
|
|
160
160
|
margin: The sizes of whitespace around the chart.
|
|
161
|
+
stack_offset: The type of offset function used to generate the lower and upper values in the series array. The four types are built-in offsets in d3-shape. 'expand' | 'none' | 'wiggle' | 'silhouette'
|
|
161
162
|
style: The style of the component.
|
|
162
163
|
key: A unique key for the component.
|
|
163
164
|
id: The id for the component.
|
|
@@ -526,9 +527,6 @@ class RadarChart(ChartBase):
|
|
|
526
527
|
on_mouse_leave: Optional[
|
|
527
528
|
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
528
529
|
] = None,
|
|
529
|
-
on_mouse_move: Optional[
|
|
530
|
-
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
531
|
-
] = None,
|
|
532
530
|
**props
|
|
533
531
|
) -> "RadarChart":
|
|
534
532
|
"""Create a chart component.
|
|
@@ -613,9 +611,6 @@ class RadialBarChart(ChartBase):
|
|
|
613
611
|
on_mouse_leave: Optional[
|
|
614
612
|
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
615
613
|
] = None,
|
|
616
|
-
on_mouse_move: Optional[
|
|
617
|
-
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
618
|
-
] = None,
|
|
619
614
|
**props
|
|
620
615
|
) -> "RadialBarChart":
|
|
621
616
|
"""Create a chart component.
|
|
@@ -688,6 +683,9 @@ class ScatterChart(ChartBase):
|
|
|
688
683
|
on_click: Optional[
|
|
689
684
|
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
690
685
|
] = None,
|
|
686
|
+
on_mouse_down: Optional[
|
|
687
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
688
|
+
] = None,
|
|
691
689
|
on_mouse_enter: Optional[
|
|
692
690
|
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
693
691
|
] = None,
|
|
@@ -703,6 +701,9 @@ class ScatterChart(ChartBase):
|
|
|
703
701
|
on_mouse_over: Optional[
|
|
704
702
|
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
705
703
|
] = None,
|
|
704
|
+
on_mouse_up: Optional[
|
|
705
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
706
|
+
] = None,
|
|
706
707
|
**props
|
|
707
708
|
) -> "ScatterChart":
|
|
708
709
|
"""Create a chart component.
|
|
@@ -731,7 +732,6 @@ class ScatterChart(ChartBase):
|
|
|
731
732
|
...
|
|
732
733
|
|
|
733
734
|
class FunnelChart(RechartsCharts):
|
|
734
|
-
def get_event_triggers(self) -> dict[str, Union[Var, Any]]: ...
|
|
735
735
|
@overload
|
|
736
736
|
@classmethod
|
|
737
737
|
def create( # type: ignore
|
|
@@ -756,9 +756,27 @@ class FunnelChart(RechartsCharts):
|
|
|
756
756
|
class_name: Optional[Any] = None,
|
|
757
757
|
autofocus: Optional[bool] = None,
|
|
758
758
|
custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
|
|
759
|
+
on_blur: Optional[
|
|
760
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
761
|
+
] = None,
|
|
759
762
|
on_click: Optional[
|
|
760
763
|
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
761
764
|
] = None,
|
|
765
|
+
on_context_menu: Optional[
|
|
766
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
767
|
+
] = None,
|
|
768
|
+
on_double_click: Optional[
|
|
769
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
770
|
+
] = None,
|
|
771
|
+
on_focus: Optional[
|
|
772
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
773
|
+
] = None,
|
|
774
|
+
on_mount: Optional[
|
|
775
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
776
|
+
] = None,
|
|
777
|
+
on_mouse_down: Optional[
|
|
778
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
779
|
+
] = None,
|
|
762
780
|
on_mouse_enter: Optional[
|
|
763
781
|
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
764
782
|
] = None,
|
|
@@ -768,6 +786,21 @@ class FunnelChart(RechartsCharts):
|
|
|
768
786
|
on_mouse_move: Optional[
|
|
769
787
|
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
770
788
|
] = None,
|
|
789
|
+
on_mouse_out: Optional[
|
|
790
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
791
|
+
] = None,
|
|
792
|
+
on_mouse_over: Optional[
|
|
793
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
794
|
+
] = None,
|
|
795
|
+
on_mouse_up: Optional[
|
|
796
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
797
|
+
] = None,
|
|
798
|
+
on_scroll: Optional[
|
|
799
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
800
|
+
] = None,
|
|
801
|
+
on_unmount: Optional[
|
|
802
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
803
|
+
] = None,
|
|
771
804
|
**props
|
|
772
805
|
) -> "FunnelChart":
|
|
773
806
|
"""Create a new memoization leaf component.
|
|
@@ -821,6 +854,12 @@ class Treemap(RechartsCharts):
|
|
|
821
854
|
class_name: Optional[Any] = None,
|
|
822
855
|
autofocus: Optional[bool] = None,
|
|
823
856
|
custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
|
|
857
|
+
on_animation_end: Optional[
|
|
858
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
859
|
+
] = None,
|
|
860
|
+
on_animation_start: Optional[
|
|
861
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
862
|
+
] = None,
|
|
824
863
|
on_blur: Optional[
|
|
825
864
|
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
826
865
|
] = None,
|
|
@@ -28,7 +28,7 @@ LiteralPosition = Literal[
|
|
|
28
28
|
]
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
toast_ref = Var.create_safe("refs['__toast']")
|
|
31
|
+
toast_ref = Var.create_safe("refs['__toast']", _var_is_string=False)
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class ToastAction(Base):
|
|
@@ -65,7 +65,8 @@ def _toast_callback_signature(toast: Var) -> list[Var]:
|
|
|
65
65
|
"""
|
|
66
66
|
return [
|
|
67
67
|
Var.create_safe(
|
|
68
|
-
f"(() => {{let {{action, cancel, onDismiss, onAutoClose, ...rest}} = {toast}; return rest}})()"
|
|
68
|
+
f"(() => {{let {{action, cancel, onDismiss, onAutoClose, ...rest}} = {toast}; return rest}})()",
|
|
69
|
+
_var_is_string=False,
|
|
69
70
|
)
|
|
70
71
|
]
|
|
71
72
|
|
|
@@ -106,7 +107,7 @@ class ToastProps(PropsBase):
|
|
|
106
107
|
cancel: Optional[ToastAction]
|
|
107
108
|
|
|
108
109
|
# Custom id for the toast.
|
|
109
|
-
id: Optional[str]
|
|
110
|
+
id: Optional[Union[str, Var]]
|
|
110
111
|
|
|
111
112
|
# Removes the default styling, which allows for easier customization.
|
|
112
113
|
unstyled: Optional[bool]
|
|
@@ -127,7 +128,7 @@ class ToastProps(PropsBase):
|
|
|
127
128
|
# Function that gets called when the toast disappears automatically after it's timeout (duration` prop).
|
|
128
129
|
on_auto_close: Optional[Any]
|
|
129
130
|
|
|
130
|
-
def dict(self, *args, **kwargs) -> dict:
|
|
131
|
+
def dict(self, *args, **kwargs) -> dict[str, Any]:
|
|
131
132
|
"""Convert the object to a dictionary.
|
|
132
133
|
|
|
133
134
|
Args:
|
|
@@ -137,7 +138,7 @@ class ToastProps(PropsBase):
|
|
|
137
138
|
Returns:
|
|
138
139
|
The object as a dictionary with ToastAction fields intact.
|
|
139
140
|
"""
|
|
140
|
-
kwargs.setdefault("exclude_none", True)
|
|
141
|
+
kwargs.setdefault("exclude_none", True) # type: ignore
|
|
141
142
|
d = super().dict(*args, **kwargs)
|
|
142
143
|
# Keep these fields as ToastAction so they can be serialized specially
|
|
143
144
|
if "action" in d:
|
|
@@ -179,7 +180,9 @@ class Toaster(Component):
|
|
|
179
180
|
visible_toasts: Var[int]
|
|
180
181
|
|
|
181
182
|
# the position of the toast
|
|
182
|
-
position: Var[LiteralPosition] = Var.create_safe(
|
|
183
|
+
position: Var[LiteralPosition] = Var.create_safe(
|
|
184
|
+
"bottom-right", _var_is_string=True
|
|
185
|
+
)
|
|
183
186
|
|
|
184
187
|
# whether to show the close button
|
|
185
188
|
close_button: Var[bool] = Var.create_safe(False)
|
|
@@ -208,10 +211,16 @@ class Toaster(Component):
|
|
|
208
211
|
# Pauses toast timers when the page is hidden, e.g., when the tab is backgrounded, the browser is minimized, or the OS is locked.
|
|
209
212
|
pause_when_page_is_hidden: Var[bool]
|
|
210
213
|
|
|
211
|
-
def
|
|
214
|
+
def add_hooks(self) -> list[Var | str]:
|
|
215
|
+
"""Add hooks for the toaster component.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
The hooks for the toaster component.
|
|
219
|
+
"""
|
|
212
220
|
hook = Var.create_safe(
|
|
213
221
|
f"{toast_ref} = toast",
|
|
214
222
|
_var_is_local=True,
|
|
223
|
+
_var_is_string=False,
|
|
215
224
|
_var_data=VarData(
|
|
216
225
|
imports={
|
|
217
226
|
"/utils/state": [ImportVar(tag="refs")],
|
|
@@ -219,7 +228,7 @@ class Toaster(Component):
|
|
|
219
228
|
}
|
|
220
229
|
),
|
|
221
230
|
)
|
|
222
|
-
return hook
|
|
231
|
+
return [hook]
|
|
223
232
|
|
|
224
233
|
@staticmethod
|
|
225
234
|
def send_toast(message: str, level: str | None = None, **props) -> EventSpec:
|
|
@@ -235,13 +244,13 @@ class Toaster(Component):
|
|
|
235
244
|
"""
|
|
236
245
|
toast_command = f"{toast_ref}.{level}" if level is not None else toast_ref
|
|
237
246
|
if props:
|
|
238
|
-
args = serialize(ToastProps(**props))
|
|
247
|
+
args = serialize(ToastProps(**props)) # type: ignore
|
|
239
248
|
toast = f"{toast_command}(`{message}`, {args})"
|
|
240
249
|
else:
|
|
241
250
|
toast = f"{toast_command}(`{message}`)"
|
|
242
251
|
|
|
243
|
-
toast_action = Var.
|
|
244
|
-
return call_script(toast_action)
|
|
252
|
+
toast_action = Var.create_safe(toast, _var_is_string=False, _var_is_local=True)
|
|
253
|
+
return call_script(toast_action)
|
|
245
254
|
|
|
246
255
|
@staticmethod
|
|
247
256
|
def toast_info(message: str, **kwargs):
|
|
@@ -295,7 +304,8 @@ class Toaster(Component):
|
|
|
295
304
|
"""
|
|
296
305
|
return Toaster.send_toast(message, level="success", **kwargs)
|
|
297
306
|
|
|
298
|
-
|
|
307
|
+
@staticmethod
|
|
308
|
+
def toast_dismiss(id: Var | str | None = None):
|
|
299
309
|
"""Dismiss a toast.
|
|
300
310
|
|
|
301
311
|
Args:
|
|
@@ -304,12 +314,22 @@ class Toaster(Component):
|
|
|
304
314
|
Returns:
|
|
305
315
|
The toast dismiss event.
|
|
306
316
|
"""
|
|
307
|
-
|
|
308
|
-
|
|
317
|
+
dismiss_var_data = None
|
|
318
|
+
|
|
319
|
+
if isinstance(id, Var):
|
|
320
|
+
dismiss = f"{toast_ref}.dismiss({id._var_name_unwrapped})"
|
|
321
|
+
dismiss_var_data = id._var_data
|
|
322
|
+
elif isinstance(id, str):
|
|
323
|
+
dismiss = f"{toast_ref}.dismiss('{id}')"
|
|
309
324
|
else:
|
|
310
|
-
dismiss = f"{toast_ref}.dismiss(
|
|
311
|
-
dismiss_action = Var.
|
|
312
|
-
|
|
325
|
+
dismiss = f"{toast_ref}.dismiss()"
|
|
326
|
+
dismiss_action = Var.create_safe(
|
|
327
|
+
dismiss,
|
|
328
|
+
_var_is_string=False,
|
|
329
|
+
_var_is_local=True,
|
|
330
|
+
_var_data=dismiss_var_data,
|
|
331
|
+
)
|
|
332
|
+
return call_script(dismiss_action)
|
|
313
333
|
|
|
314
334
|
|
|
315
335
|
# TODO: figure out why loading toast stay open forever
|
|
@@ -27,7 +27,7 @@ LiteralPosition = Literal[
|
|
|
27
27
|
"bottom-center",
|
|
28
28
|
"bottom-right",
|
|
29
29
|
]
|
|
30
|
-
toast_ref = Var.create_safe("refs['__toast']")
|
|
30
|
+
toast_ref = Var.create_safe("refs['__toast']", _var_is_string=False)
|
|
31
31
|
|
|
32
32
|
class ToastAction(Base):
|
|
33
33
|
label: str
|
|
@@ -46,7 +46,7 @@ class ToastProps(PropsBase):
|
|
|
46
46
|
dismissible: Optional[bool]
|
|
47
47
|
action: Optional[ToastAction]
|
|
48
48
|
cancel: Optional[ToastAction]
|
|
49
|
-
id: Optional[str]
|
|
49
|
+
id: Optional[Union[str, Var]]
|
|
50
50
|
unstyled: Optional[bool]
|
|
51
51
|
style: Optional[Style]
|
|
52
52
|
action_button_styles: Optional[Style]
|
|
@@ -54,9 +54,10 @@ class ToastProps(PropsBase):
|
|
|
54
54
|
on_dismiss: Optional[Any]
|
|
55
55
|
on_auto_close: Optional[Any]
|
|
56
56
|
|
|
57
|
-
def dict(self, *args, **kwargs) -> dict: ...
|
|
57
|
+
def dict(self, *args, **kwargs) -> dict[str, Any]: ...
|
|
58
58
|
|
|
59
59
|
class Toaster(Component):
|
|
60
|
+
def add_hooks(self) -> list[Var | str]: ...
|
|
60
61
|
@staticmethod
|
|
61
62
|
def send_toast(message: str, level: str | None = None, **props) -> EventSpec: ...
|
|
62
63
|
@staticmethod
|
|
@@ -67,7 +68,8 @@ class Toaster(Component):
|
|
|
67
68
|
def toast_error(message: str, **kwargs): ...
|
|
68
69
|
@staticmethod
|
|
69
70
|
def toast_success(message: str, **kwargs): ...
|
|
70
|
-
|
|
71
|
+
@staticmethod
|
|
72
|
+
def toast_dismiss(id: Var | str | None = None): ...
|
|
71
73
|
@overload
|
|
72
74
|
@classmethod
|
|
73
75
|
def create( # type: ignore
|
|
@@ -202,7 +204,9 @@ class ToastNamespace(ComponentNamespace):
|
|
|
202
204
|
dismiss = staticmethod(Toaster.toast_dismiss)
|
|
203
205
|
|
|
204
206
|
@staticmethod
|
|
205
|
-
def __call__(
|
|
207
|
+
def __call__(
|
|
208
|
+
message: str, level: Optional[str] = None, **props
|
|
209
|
+
) -> "Optional[EventSpec]":
|
|
206
210
|
"""Send a toast message.
|
|
207
211
|
|
|
208
212
|
Args:
|
reflex/components/tags/tag.py
CHANGED
|
@@ -41,7 +41,8 @@ class Tag(Base):
|
|
|
41
41
|
# Convert any props to vars.
|
|
42
42
|
if "props" in kwargs:
|
|
43
43
|
kwargs["props"] = {
|
|
44
|
-
name: Var.create(value
|
|
44
|
+
name: Var.create(value, _var_is_string=False)
|
|
45
|
+
for name, value in kwargs["props"].items()
|
|
45
46
|
}
|
|
46
47
|
super().__init__(*args, **kwargs)
|
|
47
48
|
|
reflex/config.py
CHANGED
|
@@ -161,13 +161,13 @@ class Config(Base):
|
|
|
161
161
|
loglevel: constants.LogLevel = constants.LogLevel.INFO
|
|
162
162
|
|
|
163
163
|
# The port to run the frontend on. NOTE: When running in dev mode, the next available port will be used if this is taken.
|
|
164
|
-
frontend_port: int =
|
|
164
|
+
frontend_port: int = constants.DefaultPorts.FRONTEND_PORT
|
|
165
165
|
|
|
166
166
|
# The path to run the frontend on. For example, "/app" will run the frontend on http://localhost:3000/app
|
|
167
167
|
frontend_path: str = ""
|
|
168
168
|
|
|
169
169
|
# The port to run the backend on. NOTE: When running in dev mode, the next available port will be used if this is taken.
|
|
170
|
-
backend_port: int =
|
|
170
|
+
backend_port: int = constants.DefaultPorts.BACKEND_PORT
|
|
171
171
|
|
|
172
172
|
# The backend url the frontend will connect to. This must be updated if the backend is hosted elsewhere, or in production.
|
|
173
173
|
api_url: str = f"http://localhost:{backend_port}"
|
|
@@ -316,17 +316,22 @@ class Config(Base):
|
|
|
316
316
|
):
|
|
317
317
|
self.deploy_url = f"http://localhost:{kwargs['frontend_port']}"
|
|
318
318
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
319
|
+
if "api_url" not in self._non_default_attributes:
|
|
320
|
+
# If running in Github Codespaces, override API_URL
|
|
321
|
+
codespace_name = os.getenv("CODESPACE_NAME")
|
|
322
322
|
GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN = os.getenv(
|
|
323
323
|
"GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN"
|
|
324
324
|
)
|
|
325
|
-
|
|
325
|
+
# If running on Replit.com interactively, override API_URL to ensure we maintain the backend_port
|
|
326
|
+
replit_dev_domain = os.getenv("REPLIT_DEV_DOMAIN")
|
|
327
|
+
backend_port = kwargs.get("backend_port", self.backend_port)
|
|
328
|
+
if codespace_name and GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN:
|
|
326
329
|
self.api_url = (
|
|
327
330
|
f"https://{codespace_name}-{kwargs.get('backend_port', self.backend_port)}"
|
|
328
331
|
f".{GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN}"
|
|
329
332
|
)
|
|
333
|
+
elif replit_dev_domain and backend_port:
|
|
334
|
+
self.api_url = f"https://{replit_dev_domain}:{backend_port}"
|
|
330
335
|
|
|
331
336
|
def _set_persistent(self, **kwargs):
|
|
332
337
|
"""Set values in this config and in the environment so they persist into subprocess.
|
|
@@ -352,11 +357,14 @@ def get_config(reload: bool = False) -> Config:
|
|
|
352
357
|
The app config.
|
|
353
358
|
"""
|
|
354
359
|
sys.path.insert(0, os.getcwd())
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
360
|
+
# only import the module if it exists. If a module spec exists then
|
|
361
|
+
# the module exists.
|
|
362
|
+
spec = importlib.util.find_spec(constants.Config.MODULE) # type: ignore
|
|
363
|
+
if not spec:
|
|
364
|
+
# we need this condition to ensure that a ModuleNotFound error is not thrown when
|
|
365
|
+
# running unit/integration tests.
|
|
366
|
+
return Config(app_name="")
|
|
367
|
+
rxconfig = importlib.import_module(constants.Config.MODULE)
|
|
368
|
+
if reload:
|
|
369
|
+
importlib.reload(rxconfig)
|
|
370
|
+
return rxconfig.config
|
reflex/constants/__init__.py
CHANGED
|
@@ -36,6 +36,7 @@ from .compiler import (
|
|
|
36
36
|
from .config import (
|
|
37
37
|
ALEMBIC_CONFIG,
|
|
38
38
|
Config,
|
|
39
|
+
DefaultPorts,
|
|
39
40
|
Expiration,
|
|
40
41
|
GitIgnore,
|
|
41
42
|
RequirementsTxt,
|
|
@@ -72,6 +73,7 @@ __ALL__ = [
|
|
|
72
73
|
ComponentName,
|
|
73
74
|
CustomComponents,
|
|
74
75
|
DefaultPage,
|
|
76
|
+
DefaultPorts,
|
|
75
77
|
Dirs,
|
|
76
78
|
Endpoint,
|
|
77
79
|
Env,
|
reflex/constants/config.py
CHANGED
|
@@ -50,5 +50,12 @@ class RequirementsTxt(SimpleNamespace):
|
|
|
50
50
|
DEFAULTS_STUB = f"{Reflex.MODULE_NAME}=="
|
|
51
51
|
|
|
52
52
|
|
|
53
|
+
class DefaultPorts(SimpleNamespace):
|
|
54
|
+
"""Default port constants."""
|
|
55
|
+
|
|
56
|
+
FRONTEND_PORT = 3000
|
|
57
|
+
BACKEND_PORT = 8000
|
|
58
|
+
|
|
59
|
+
|
|
53
60
|
# The deployment URL.
|
|
54
61
|
PRODUCTION_BACKEND_URL = "https://{username}-{app_name}.api.pynecone.app"
|
reflex/event.py
CHANGED
|
@@ -186,7 +186,7 @@ class EventHandler(EventActionsMixin):
|
|
|
186
186
|
|
|
187
187
|
# Get the function args.
|
|
188
188
|
fn_args = inspect.getfullargspec(self.fn).args[1:]
|
|
189
|
-
fn_args = (Var.create_safe(arg) for arg in fn_args)
|
|
189
|
+
fn_args = (Var.create_safe(arg, _var_is_string=False) for arg in fn_args)
|
|
190
190
|
|
|
191
191
|
# Construct the payload.
|
|
192
192
|
values = []
|
|
@@ -264,7 +264,7 @@ class EventSpec(EventActionsMixin):
|
|
|
264
264
|
|
|
265
265
|
# Get the remaining unfilled function args.
|
|
266
266
|
fn_args = inspect.getfullargspec(self.handler.fn).args[1 + len(self.args) :]
|
|
267
|
-
fn_args = (Var.create_safe(arg) for arg in fn_args)
|
|
267
|
+
fn_args = (Var.create_safe(arg, _var_is_string=False) for arg in fn_args)
|
|
268
268
|
|
|
269
269
|
# Construct the payload.
|
|
270
270
|
values = []
|
|
@@ -389,13 +389,13 @@ class FileUpload(Base):
|
|
|
389
389
|
|
|
390
390
|
spec_args = [
|
|
391
391
|
(
|
|
392
|
-
Var.create_safe("files"),
|
|
393
|
-
Var.create_safe(
|
|
394
|
-
|
|
395
|
-
),
|
|
392
|
+
Var.create_safe("files", _var_is_string=False),
|
|
393
|
+
Var.create_safe(
|
|
394
|
+
f"filesById.{upload_id}", _var_is_string=False
|
|
395
|
+
)._replace(_var_data=upload_files_context_var_data),
|
|
396
396
|
),
|
|
397
397
|
(
|
|
398
|
-
Var.create_safe("upload_id"),
|
|
398
|
+
Var.create_safe("upload_id", _var_is_string=False),
|
|
399
399
|
Var.create_safe(upload_id, _var_is_string=True),
|
|
400
400
|
),
|
|
401
401
|
]
|
|
@@ -415,6 +415,8 @@ class FileUpload(Base):
|
|
|
415
415
|
) # type: ignore
|
|
416
416
|
else:
|
|
417
417
|
raise ValueError(f"{on_upload_progress} is not a valid event handler.")
|
|
418
|
+
if isinstance(events, Var):
|
|
419
|
+
raise ValueError(f"{on_upload_progress} cannot return a var {events}.")
|
|
418
420
|
on_upload_progress_chain = EventChain(
|
|
419
421
|
events=events,
|
|
420
422
|
args_spec=self.on_upload_progress_args_spec,
|
|
@@ -422,7 +424,7 @@ class FileUpload(Base):
|
|
|
422
424
|
formatted_chain = str(format.format_prop(on_upload_progress_chain))
|
|
423
425
|
spec_args.append(
|
|
424
426
|
(
|
|
425
|
-
Var.create_safe("on_upload_progress"),
|
|
427
|
+
Var.create_safe("on_upload_progress", _var_is_string=False),
|
|
426
428
|
BaseVar(
|
|
427
429
|
_var_name=formatted_chain.strip("{}"),
|
|
428
430
|
_var_type=EventChain,
|
|
@@ -462,7 +464,10 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
|
|
|
462
464
|
return EventSpec(
|
|
463
465
|
handler=EventHandler(fn=fn),
|
|
464
466
|
args=tuple(
|
|
465
|
-
(
|
|
467
|
+
(
|
|
468
|
+
Var.create_safe(k, _var_is_string=False),
|
|
469
|
+
Var.create_safe(v, _var_is_string=isinstance(v, str)),
|
|
470
|
+
)
|
|
466
471
|
for k, v in kwargs.items()
|
|
467
472
|
),
|
|
468
473
|
)
|
|
@@ -714,7 +719,7 @@ def _callback_arg_spec(eval_result):
|
|
|
714
719
|
|
|
715
720
|
|
|
716
721
|
def call_script(
|
|
717
|
-
javascript_code: str,
|
|
722
|
+
javascript_code: str | Var[str],
|
|
718
723
|
callback: EventSpec
|
|
719
724
|
| EventHandler
|
|
720
725
|
| Callable
|
|
@@ -831,19 +836,19 @@ def parse_args_spec(arg_spec: ArgsSpec):
|
|
|
831
836
|
)
|
|
832
837
|
|
|
833
838
|
|
|
834
|
-
def call_event_fn(fn: Callable, arg: Union[Var, ArgsSpec]) -> list[EventSpec]:
|
|
839
|
+
def call_event_fn(fn: Callable, arg: Union[Var, ArgsSpec]) -> list[EventSpec] | Var:
|
|
835
840
|
"""Call a function to a list of event specs.
|
|
836
841
|
|
|
837
|
-
The function should return
|
|
838
|
-
If the function takes in an arg, the arg will be passed to the
|
|
839
|
-
Otherwise, the function will be called with no args.
|
|
842
|
+
The function should return a single EventSpec, a list of EventSpecs, or a
|
|
843
|
+
single Var. If the function takes in an arg, the arg will be passed to the
|
|
844
|
+
function. Otherwise, the function will be called with no args.
|
|
840
845
|
|
|
841
846
|
Args:
|
|
842
847
|
fn: The function to call.
|
|
843
848
|
arg: The argument to pass to the function.
|
|
844
849
|
|
|
845
850
|
Returns:
|
|
846
|
-
The event specs from calling the function.
|
|
851
|
+
The event specs from calling the function or a Var.
|
|
847
852
|
|
|
848
853
|
Raises:
|
|
849
854
|
EventHandlerValueError: If the lambda has an invalid signature.
|
|
@@ -866,6 +871,10 @@ def call_event_fn(fn: Callable, arg: Union[Var, ArgsSpec]) -> list[EventSpec]:
|
|
|
866
871
|
else:
|
|
867
872
|
raise EventHandlerValueError(f"Lambda {fn} must have 0 or 1 arguments.")
|
|
868
873
|
|
|
874
|
+
# If the function returns a Var, assume it's an EventChain and render it directly.
|
|
875
|
+
if isinstance(out, Var):
|
|
876
|
+
return out
|
|
877
|
+
|
|
869
878
|
# Convert the output to a list.
|
|
870
879
|
if not isinstance(out, List):
|
|
871
880
|
out = [out]
|
reflex/experimental/__init__.py
CHANGED
|
@@ -17,7 +17,28 @@ warn(
|
|
|
17
17
|
"`rx._x` contains experimental features and might be removed at any time in the future .",
|
|
18
18
|
)
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
_EMITTED_PROMOTION_WARNINGS = set()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ExperimentalNamespace(SimpleNamespace):
|
|
24
|
+
"""Namespace for experimental features."""
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def toast(self):
|
|
28
|
+
"""Temporary property returning the toast namespace.
|
|
29
|
+
|
|
30
|
+
Remove this property when toast is fully promoted.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
The toast namespace.
|
|
34
|
+
"""
|
|
35
|
+
if "toast" not in _EMITTED_PROMOTION_WARNINGS:
|
|
36
|
+
_EMITTED_PROMOTION_WARNINGS.add("toast")
|
|
37
|
+
warn(f"`rx._x.toast` was promoted to `rx.toast`.")
|
|
38
|
+
return toast
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
_x = ExperimentalNamespace(
|
|
21
42
|
asset=asset,
|
|
22
43
|
client_state=ClientStateVar.create,
|
|
23
44
|
hooks=hooks,
|
|
@@ -25,5 +46,4 @@ _x = SimpleNamespace(
|
|
|
25
46
|
progress=progress,
|
|
26
47
|
PropsBase=PropsBase,
|
|
27
48
|
run_in_thread=run_in_thread,
|
|
28
|
-
toast=toast,
|
|
29
49
|
)
|