reflex 0.4.9a1__py3-none-any.whl → 0.5.0__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/blank/code/blank.py +19 -16
- reflex/.templates/apps/demo/code/demo.py +1 -1
- reflex/.templates/apps/demo/code/pages/datatable.py +4 -4
- reflex/.templates/apps/demo/code/pages/forms.py +2 -2
- reflex/.templates/jinja/web/tailwind.config.js.jinja2 +12 -0
- reflex/.templates/web/utils/helpers/debounce.js +17 -0
- reflex/.templates/web/utils/helpers/throttle.js +22 -0
- reflex/.templates/web/utils/state.js +21 -3
- reflex/__init__.py +6 -1
- reflex/__init__.pyi +4 -1
- reflex/app.py +160 -140
- reflex/app_module_for_backend.py +1 -1
- reflex/base.py +13 -15
- reflex/compiler/compiler.py +10 -1
- reflex/compiler/utils.py +3 -30
- reflex/components/__init__.py +1 -0
- reflex/components/chakra/datadisplay/list.py +1 -3
- reflex/components/chakra/datadisplay/list.pyi +3 -3
- reflex/components/chakra/disclosure/accordion.py +1 -1
- reflex/components/chakra/forms/pininput.pyi +1 -1
- reflex/components/chakra/media/icon.py +2 -2
- reflex/components/component.py +275 -32
- reflex/components/core/__init__.py +2 -2
- reflex/components/core/cond.py +1 -10
- reflex/components/core/debounce.py +5 -2
- reflex/components/core/debounce.pyi +4 -2
- reflex/components/core/foreach.py +60 -49
- reflex/components/core/html.py +6 -0
- reflex/components/core/match.py +2 -17
- reflex/components/core/upload.py +42 -1
- reflex/components/core/upload.pyi +199 -1
- reflex/components/datadisplay/code.py +7 -3
- reflex/components/datadisplay/code.pyi +3 -1
- reflex/components/el/elements/forms.py +1 -1
- reflex/components/el/elements/forms.pyi +1 -1
- reflex/components/lucide/icon.py +5 -13
- reflex/components/lucide/icon.pyi +0 -1
- reflex/components/markdown/markdown.py +5 -23
- reflex/components/markdown/markdown.pyi +1 -4
- reflex/components/radix/primitives/accordion.py +265 -410
- reflex/components/radix/primitives/accordion.pyi +390 -36
- reflex/components/radix/primitives/form.py +33 -29
- reflex/components/radix/primitives/form.pyi +7 -2
- reflex/components/radix/primitives/progress.py +17 -9
- reflex/components/radix/primitives/progress.pyi +2 -0
- reflex/components/radix/primitives/slider.py +30 -18
- reflex/components/radix/primitives/slider.pyi +4 -0
- reflex/components/radix/themes/base.py +8 -1
- reflex/components/radix/themes/base.pyi +79 -1
- reflex/components/radix/themes/color_mode.py +88 -20
- reflex/components/radix/themes/color_mode.pyi +157 -139
- reflex/components/radix/themes/components/__init__.py +17 -0
- reflex/components/radix/themes/components/badge.py +2 -1
- reflex/components/radix/themes/components/badge.pyi +3 -1
- reflex/components/radix/themes/components/button.py +3 -1
- reflex/components/radix/themes/components/button.pyi +4 -1
- reflex/components/radix/themes/components/checkbox_cards.py +48 -0
- reflex/components/radix/themes/components/checkbox_cards.pyi +264 -0
- reflex/components/radix/themes/components/checkbox_group.py +42 -0
- reflex/components/radix/themes/components/checkbox_group.pyi +253 -0
- reflex/components/radix/themes/components/data_list.py +63 -0
- reflex/components/radix/themes/components/data_list.pyi +426 -0
- reflex/components/radix/themes/components/icon_button.py +20 -17
- reflex/components/radix/themes/components/icon_button.pyi +5 -1
- reflex/components/radix/themes/components/progress.py +55 -0
- reflex/components/radix/themes/components/progress.pyi +180 -0
- reflex/components/radix/themes/components/radio.py +31 -0
- reflex/components/radix/themes/components/radio.pyi +169 -0
- reflex/components/radix/themes/components/radio_cards.py +48 -0
- reflex/components/radix/themes/components/radio_cards.pyi +264 -0
- reflex/components/radix/themes/components/radio_group.py +2 -4
- reflex/components/radix/themes/components/segmented_control.py +48 -0
- reflex/components/radix/themes/components/segmented_control.pyi +262 -0
- reflex/components/radix/themes/components/skeleton.py +32 -0
- reflex/components/radix/themes/components/skeleton.pyi +106 -0
- reflex/components/radix/themes/components/spinner.py +26 -0
- reflex/components/radix/themes/components/spinner.pyi +101 -0
- reflex/components/radix/themes/components/tabs.py +26 -1
- reflex/components/radix/themes/components/tabs.pyi +69 -9
- reflex/components/radix/themes/components/text_field.py +101 -71
- reflex/components/radix/themes/components/text_field.pyi +81 -499
- reflex/components/radix/themes/layout/base.py +2 -2
- reflex/components/radix/themes/layout/base.pyi +4 -4
- reflex/components/radix/themes/layout/center.py +8 -3
- reflex/components/radix/themes/layout/center.pyi +2 -1
- reflex/components/radix/themes/layout/container.py +30 -2
- reflex/components/radix/themes/layout/container.pyi +9 -30
- reflex/components/radix/themes/layout/list.py +10 -5
- reflex/components/radix/themes/layout/list.pyi +5 -21
- reflex/components/radix/themes/layout/spacer.py +8 -3
- reflex/components/radix/themes/layout/spacer.pyi +2 -1
- reflex/components/radix/themes/layout/stack.py +7 -1
- reflex/components/radix/themes/layout/stack.pyi +3 -3
- reflex/components/radix/themes/typography/link.py +10 -2
- reflex/components/radix/themes/typography/link.pyi +5 -4
- reflex/components/sonner/__init__.py +3 -0
- reflex/components/sonner/toast.py +267 -0
- reflex/components/sonner/toast.pyi +205 -0
- reflex/components/tags/iter_tag.py +9 -6
- reflex/config.py +30 -54
- reflex/constants/__init__.py +0 -2
- reflex/constants/base.py +0 -5
- reflex/constants/colors.py +2 -0
- reflex/constants/installer.py +6 -1
- reflex/constants/route.py +4 -0
- reflex/custom_components/custom_components.py +24 -2
- reflex/event.py +75 -30
- reflex/experimental/__init__.py +5 -0
- reflex/experimental/layout.py +24 -6
- reflex/model.py +2 -1
- reflex/page.py +7 -4
- reflex/reflex.py +8 -3
- reflex/route.py +39 -0
- reflex/state.py +128 -131
- reflex/style.py +25 -3
- reflex/testing.py +10 -6
- reflex/utils/console.py +3 -1
- reflex/utils/exec.py +20 -7
- reflex/utils/format.py +1 -1
- reflex/utils/imports.py +3 -1
- reflex/utils/prerequisites.py +141 -20
- reflex/utils/processes.py +21 -1
- reflex/utils/pyi_generator.py +100 -5
- reflex/utils/serializers.py +1 -1
- reflex/utils/telemetry.py +26 -4
- reflex/utils/types.py +62 -18
- reflex/vars.py +11 -5
- {reflex-0.4.9a1.dist-info → reflex-0.5.0.dist-info}/METADATA +16 -4
- {reflex-0.4.9a1.dist-info → reflex-0.5.0.dist-info}/RECORD +132 -110
- {reflex-0.4.9a1.dist-info → reflex-0.5.0.dist-info}/WHEEL +1 -1
- reflex/app.pyi +0 -149
- {reflex-0.4.9a1.dist-info → reflex-0.5.0.dist-info}/LICENSE +0 -0
- {reflex-0.4.9a1.dist-info → reflex-0.5.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"""Sonner toast component."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
from reflex.base import Base
|
|
8
|
+
from reflex.components.component import Component, ComponentNamespace
|
|
9
|
+
from reflex.components.lucide.icon import Icon
|
|
10
|
+
from reflex.event import EventSpec, call_script
|
|
11
|
+
from reflex.style import Style, color_mode
|
|
12
|
+
from reflex.utils import format
|
|
13
|
+
from reflex.utils.imports import ImportVar
|
|
14
|
+
from reflex.utils.serializers import serialize
|
|
15
|
+
from reflex.vars import Var, VarData
|
|
16
|
+
|
|
17
|
+
LiteralPosition = Literal[
|
|
18
|
+
"top-left",
|
|
19
|
+
"top-center",
|
|
20
|
+
"top-right",
|
|
21
|
+
"bottom-left",
|
|
22
|
+
"bottom-center",
|
|
23
|
+
"bottom-right",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
toast_ref = Var.create_safe("refs['__toast']")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class PropsBase(Base):
|
|
31
|
+
"""Base class for all props classes."""
|
|
32
|
+
|
|
33
|
+
def json(self) -> str:
|
|
34
|
+
"""Convert the object to a json string.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
The object as a json string.
|
|
38
|
+
"""
|
|
39
|
+
from reflex.utils.serializers import serialize
|
|
40
|
+
|
|
41
|
+
return self.__config__.json_dumps(
|
|
42
|
+
{format.to_camel_case(key): value for key, value in self.dict().items()},
|
|
43
|
+
default=serialize,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ToastProps(PropsBase):
|
|
48
|
+
"""Props for the toast component."""
|
|
49
|
+
|
|
50
|
+
# Toast's description, renders underneath the title.
|
|
51
|
+
description: str = ""
|
|
52
|
+
|
|
53
|
+
# Whether to show the close button.
|
|
54
|
+
close_button: bool = False
|
|
55
|
+
|
|
56
|
+
# Dark toast in light mode and vice versa.
|
|
57
|
+
invert: bool = False
|
|
58
|
+
|
|
59
|
+
# Control the sensitivity of the toast for screen readers
|
|
60
|
+
important: bool = False
|
|
61
|
+
|
|
62
|
+
# Time in milliseconds that should elapse before automatically closing the toast.
|
|
63
|
+
duration: int = 4000
|
|
64
|
+
|
|
65
|
+
# Position of the toast.
|
|
66
|
+
position: LiteralPosition = "bottom-right"
|
|
67
|
+
|
|
68
|
+
# If false, it'll prevent the user from dismissing the toast.
|
|
69
|
+
dismissible: bool = True
|
|
70
|
+
|
|
71
|
+
# TODO: fix serialization of icons for toast? (might not be possible yet)
|
|
72
|
+
# Icon displayed in front of toast's text, aligned vertically.
|
|
73
|
+
# icon: Optional[Icon] = None
|
|
74
|
+
|
|
75
|
+
# TODO: fix implementation for action / cancel buttons
|
|
76
|
+
# Renders a primary button, clicking it will close the toast.
|
|
77
|
+
# action: str = ""
|
|
78
|
+
|
|
79
|
+
# Renders a secondary button, clicking it will close the toast.
|
|
80
|
+
# cancel: str = ""
|
|
81
|
+
|
|
82
|
+
# Custom id for the toast.
|
|
83
|
+
id: str = ""
|
|
84
|
+
|
|
85
|
+
# Removes the default styling, which allows for easier customization.
|
|
86
|
+
unstyled: bool = False
|
|
87
|
+
|
|
88
|
+
# Custom style for the toast.
|
|
89
|
+
style: Style = Style()
|
|
90
|
+
|
|
91
|
+
# Custom style for the toast primary button.
|
|
92
|
+
# action_button_styles: Style = Style()
|
|
93
|
+
|
|
94
|
+
# Custom style for the toast secondary button.
|
|
95
|
+
# cancel_button_styles: Style = Style()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class Toaster(Component):
|
|
99
|
+
"""A Toaster Component for displaying toast notifications."""
|
|
100
|
+
|
|
101
|
+
library = "sonner@1.4.41"
|
|
102
|
+
|
|
103
|
+
tag = "Toaster"
|
|
104
|
+
|
|
105
|
+
# the theme of the toast
|
|
106
|
+
theme: Var[str] = color_mode
|
|
107
|
+
|
|
108
|
+
# whether to show rich colors
|
|
109
|
+
rich_colors: Var[bool] = Var.create_safe(True)
|
|
110
|
+
|
|
111
|
+
# whether to expand the toast
|
|
112
|
+
expand: Var[bool] = Var.create_safe(True)
|
|
113
|
+
|
|
114
|
+
# the number of toasts that are currently visible
|
|
115
|
+
visible_toasts: Var[int]
|
|
116
|
+
|
|
117
|
+
# the position of the toast
|
|
118
|
+
position: Var[LiteralPosition] = Var.create_safe("bottom-right")
|
|
119
|
+
|
|
120
|
+
# whether to show the close button
|
|
121
|
+
close_button: Var[bool] = Var.create_safe(False)
|
|
122
|
+
|
|
123
|
+
# offset of the toast
|
|
124
|
+
offset: Var[str]
|
|
125
|
+
|
|
126
|
+
# directionality of the toast (default: ltr)
|
|
127
|
+
dir: Var[str]
|
|
128
|
+
|
|
129
|
+
# Keyboard shortcut that will move focus to the toaster area.
|
|
130
|
+
hotkey: Var[str]
|
|
131
|
+
|
|
132
|
+
# Dark toasts in light mode and vice versa.
|
|
133
|
+
invert: Var[bool]
|
|
134
|
+
|
|
135
|
+
# These will act as default options for all toasts. See toast() for all available options.
|
|
136
|
+
toast_options: Var[ToastProps]
|
|
137
|
+
|
|
138
|
+
# Gap between toasts when expanded
|
|
139
|
+
gap: Var[int]
|
|
140
|
+
|
|
141
|
+
# Changes the default loading icon
|
|
142
|
+
loading_icon: Var[Icon]
|
|
143
|
+
|
|
144
|
+
# Pauses toast timers when the page is hidden, e.g., when the tab is backgrounded, the browser is minimized, or the OS is locked.
|
|
145
|
+
pause_when_page_is_hidden: Var[bool]
|
|
146
|
+
|
|
147
|
+
def _get_hooks(self) -> Var[str]:
|
|
148
|
+
hook = Var.create_safe(f"{toast_ref} = toast", _var_is_local=True)
|
|
149
|
+
hook._var_data = VarData( # type: ignore
|
|
150
|
+
imports={
|
|
151
|
+
"/utils/state": [ImportVar(tag="refs")],
|
|
152
|
+
self.library: [ImportVar(tag="toast", install=False)],
|
|
153
|
+
}
|
|
154
|
+
)
|
|
155
|
+
return hook
|
|
156
|
+
|
|
157
|
+
@staticmethod
|
|
158
|
+
def send_toast(message: str, level: str | None = None, **props) -> EventSpec:
|
|
159
|
+
"""Send a toast message.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
message: The message to display.
|
|
163
|
+
level: The level of the toast.
|
|
164
|
+
**props: The options for the toast.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
The toast event.
|
|
168
|
+
"""
|
|
169
|
+
toast_command = f"{toast_ref}.{level}" if level is not None else toast_ref
|
|
170
|
+
if props:
|
|
171
|
+
args = serialize(ToastProps(**props))
|
|
172
|
+
toast = f"{toast_command}(`{message}`, {args})"
|
|
173
|
+
else:
|
|
174
|
+
toast = f"{toast_command}(`{message}`)"
|
|
175
|
+
|
|
176
|
+
toast_action = Var.create(toast, _var_is_string=False, _var_is_local=True)
|
|
177
|
+
return call_script(toast_action) # type: ignore
|
|
178
|
+
|
|
179
|
+
@staticmethod
|
|
180
|
+
def toast_info(message: str, **kwargs):
|
|
181
|
+
"""Display an info toast message.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
message: The message to display.
|
|
185
|
+
kwargs: Additional toast props.
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
The toast event.
|
|
189
|
+
"""
|
|
190
|
+
return Toaster.send_toast(message, level="info", **kwargs)
|
|
191
|
+
|
|
192
|
+
@staticmethod
|
|
193
|
+
def toast_warning(message: str, **kwargs):
|
|
194
|
+
"""Display a warning toast message.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
message: The message to display.
|
|
198
|
+
kwargs: Additional toast props.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
The toast event.
|
|
202
|
+
"""
|
|
203
|
+
return Toaster.send_toast(message, level="warning", **kwargs)
|
|
204
|
+
|
|
205
|
+
@staticmethod
|
|
206
|
+
def toast_error(message: str, **kwargs):
|
|
207
|
+
"""Display an error toast message.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
message: The message to display.
|
|
211
|
+
kwargs: Additional toast props.
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
The toast event.
|
|
215
|
+
"""
|
|
216
|
+
return Toaster.send_toast(message, level="error", **kwargs)
|
|
217
|
+
|
|
218
|
+
@staticmethod
|
|
219
|
+
def toast_success(message: str, **kwargs):
|
|
220
|
+
"""Display a success toast message.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
message: The message to display.
|
|
224
|
+
kwargs: Additional toast props.
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
The toast event.
|
|
228
|
+
"""
|
|
229
|
+
return Toaster.send_toast(message, level="success", **kwargs)
|
|
230
|
+
|
|
231
|
+
def toast_dismiss(self, id: str | None):
|
|
232
|
+
"""Dismiss a toast.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
id: The id of the toast to dismiss.
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
The toast dismiss event.
|
|
239
|
+
"""
|
|
240
|
+
if id is None:
|
|
241
|
+
dismiss = f"{toast_ref}.dismiss()"
|
|
242
|
+
else:
|
|
243
|
+
dismiss = f"{toast_ref}.dismiss({id})"
|
|
244
|
+
dismiss_action = Var.create(dismiss, _var_is_string=False, _var_is_local=True)
|
|
245
|
+
return call_script(dismiss_action) # type: ignore
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
# TODO: figure out why loading toast stay open forever
|
|
249
|
+
# def toast_loading(message: str, **kwargs):
|
|
250
|
+
# return _toast(message, level="loading", **kwargs)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
class ToastNamespace(ComponentNamespace):
|
|
254
|
+
"""Namespace for toast components."""
|
|
255
|
+
|
|
256
|
+
provider = staticmethod(Toaster.create)
|
|
257
|
+
options = staticmethod(ToastProps)
|
|
258
|
+
info = staticmethod(Toaster.toast_info)
|
|
259
|
+
warning = staticmethod(Toaster.toast_warning)
|
|
260
|
+
error = staticmethod(Toaster.toast_error)
|
|
261
|
+
success = staticmethod(Toaster.toast_success)
|
|
262
|
+
dismiss = staticmethod(Toaster.toast_dismiss)
|
|
263
|
+
# loading = staticmethod(toast_loading)
|
|
264
|
+
__call__ = staticmethod(Toaster.send_toast)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
toast = ToastNamespace()
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""Stub file for reflex/components/sonner/toast.py"""
|
|
2
|
+
# ------------------- DO NOT EDIT ----------------------
|
|
3
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
|
+
# ------------------------------------------------------
|
|
5
|
+
|
|
6
|
+
from typing import Any, Dict, Literal, Optional, Union, overload
|
|
7
|
+
from reflex.vars import Var, BaseVar, ComputedVar
|
|
8
|
+
from reflex.event import EventChain, EventHandler, EventSpec
|
|
9
|
+
from reflex.style import Style
|
|
10
|
+
from typing import Literal
|
|
11
|
+
from reflex.base import Base
|
|
12
|
+
from reflex.components.component import Component, ComponentNamespace
|
|
13
|
+
from reflex.components.lucide.icon import Icon
|
|
14
|
+
from reflex.event import EventSpec, call_script
|
|
15
|
+
from reflex.style import Style, color_mode
|
|
16
|
+
from reflex.utils import format
|
|
17
|
+
from reflex.utils.imports import ImportVar
|
|
18
|
+
from reflex.utils.serializers import serialize
|
|
19
|
+
from reflex.vars import Var, VarData
|
|
20
|
+
|
|
21
|
+
LiteralPosition = Literal[
|
|
22
|
+
"top-left",
|
|
23
|
+
"top-center",
|
|
24
|
+
"top-right",
|
|
25
|
+
"bottom-left",
|
|
26
|
+
"bottom-center",
|
|
27
|
+
"bottom-right",
|
|
28
|
+
]
|
|
29
|
+
toast_ref = Var.create_safe("refs['__toast']")
|
|
30
|
+
|
|
31
|
+
class PropsBase(Base):
|
|
32
|
+
def json(self) -> str: ...
|
|
33
|
+
|
|
34
|
+
class ToastProps(PropsBase):
|
|
35
|
+
description: str
|
|
36
|
+
close_button: bool
|
|
37
|
+
invert: bool
|
|
38
|
+
important: bool
|
|
39
|
+
duration: int
|
|
40
|
+
position: LiteralPosition
|
|
41
|
+
dismissible: bool
|
|
42
|
+
id: str
|
|
43
|
+
unstyled: bool
|
|
44
|
+
style: Style
|
|
45
|
+
|
|
46
|
+
class Toaster(Component):
|
|
47
|
+
@staticmethod
|
|
48
|
+
def send_toast(message: str, level: str | None = None, **props) -> EventSpec: ...
|
|
49
|
+
@staticmethod
|
|
50
|
+
def toast_info(message: str, **kwargs): ...
|
|
51
|
+
@staticmethod
|
|
52
|
+
def toast_warning(message: str, **kwargs): ...
|
|
53
|
+
@staticmethod
|
|
54
|
+
def toast_error(message: str, **kwargs): ...
|
|
55
|
+
@staticmethod
|
|
56
|
+
def toast_success(message: str, **kwargs): ...
|
|
57
|
+
def toast_dismiss(self, id: str | None): ...
|
|
58
|
+
@overload
|
|
59
|
+
@classmethod
|
|
60
|
+
def create( # type: ignore
|
|
61
|
+
cls,
|
|
62
|
+
*children,
|
|
63
|
+
theme: Optional[Union[Var[str], str]] = None,
|
|
64
|
+
rich_colors: Optional[Union[Var[bool], bool]] = None,
|
|
65
|
+
expand: Optional[Union[Var[bool], bool]] = None,
|
|
66
|
+
visible_toasts: Optional[Union[Var[int], int]] = None,
|
|
67
|
+
position: Optional[
|
|
68
|
+
Union[
|
|
69
|
+
Var[
|
|
70
|
+
Literal[
|
|
71
|
+
"top-left",
|
|
72
|
+
"top-center",
|
|
73
|
+
"top-right",
|
|
74
|
+
"bottom-left",
|
|
75
|
+
"bottom-center",
|
|
76
|
+
"bottom-right",
|
|
77
|
+
]
|
|
78
|
+
],
|
|
79
|
+
Literal[
|
|
80
|
+
"top-left",
|
|
81
|
+
"top-center",
|
|
82
|
+
"top-right",
|
|
83
|
+
"bottom-left",
|
|
84
|
+
"bottom-center",
|
|
85
|
+
"bottom-right",
|
|
86
|
+
],
|
|
87
|
+
]
|
|
88
|
+
] = None,
|
|
89
|
+
close_button: Optional[Union[Var[bool], bool]] = None,
|
|
90
|
+
offset: Optional[Union[Var[str], str]] = None,
|
|
91
|
+
dir: Optional[Union[Var[str], str]] = None,
|
|
92
|
+
hotkey: Optional[Union[Var[str], str]] = None,
|
|
93
|
+
invert: Optional[Union[Var[bool], bool]] = None,
|
|
94
|
+
toast_options: Optional[Union[Var[ToastProps], ToastProps]] = None,
|
|
95
|
+
gap: Optional[Union[Var[int], int]] = None,
|
|
96
|
+
loading_icon: Optional[Union[Var[Icon], Icon]] = None,
|
|
97
|
+
pause_when_page_is_hidden: Optional[Union[Var[bool], bool]] = None,
|
|
98
|
+
style: Optional[Style] = None,
|
|
99
|
+
key: Optional[Any] = None,
|
|
100
|
+
id: Optional[Any] = None,
|
|
101
|
+
class_name: Optional[Any] = None,
|
|
102
|
+
autofocus: Optional[bool] = None,
|
|
103
|
+
custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
|
|
104
|
+
on_blur: Optional[
|
|
105
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
106
|
+
] = None,
|
|
107
|
+
on_click: Optional[
|
|
108
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
109
|
+
] = None,
|
|
110
|
+
on_context_menu: Optional[
|
|
111
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
112
|
+
] = None,
|
|
113
|
+
on_double_click: Optional[
|
|
114
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
115
|
+
] = None,
|
|
116
|
+
on_focus: Optional[
|
|
117
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
118
|
+
] = None,
|
|
119
|
+
on_mount: Optional[
|
|
120
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
121
|
+
] = None,
|
|
122
|
+
on_mouse_down: Optional[
|
|
123
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
124
|
+
] = None,
|
|
125
|
+
on_mouse_enter: Optional[
|
|
126
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
127
|
+
] = None,
|
|
128
|
+
on_mouse_leave: Optional[
|
|
129
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
130
|
+
] = None,
|
|
131
|
+
on_mouse_move: Optional[
|
|
132
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
133
|
+
] = None,
|
|
134
|
+
on_mouse_out: Optional[
|
|
135
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
136
|
+
] = None,
|
|
137
|
+
on_mouse_over: Optional[
|
|
138
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
139
|
+
] = None,
|
|
140
|
+
on_mouse_up: Optional[
|
|
141
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
142
|
+
] = None,
|
|
143
|
+
on_scroll: Optional[
|
|
144
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
145
|
+
] = None,
|
|
146
|
+
on_unmount: Optional[
|
|
147
|
+
Union[EventHandler, EventSpec, list, function, BaseVar]
|
|
148
|
+
] = None,
|
|
149
|
+
**props
|
|
150
|
+
) -> "Toaster":
|
|
151
|
+
"""Create the component.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
*children: The children of the component.
|
|
155
|
+
theme: the theme of the toast
|
|
156
|
+
rich_colors: whether to show rich colors
|
|
157
|
+
expand: whether to expand the toast
|
|
158
|
+
visible_toasts: the number of toasts that are currently visible
|
|
159
|
+
position: the position of the toast
|
|
160
|
+
close_button: whether to show the close button
|
|
161
|
+
offset: offset of the toast
|
|
162
|
+
dir: directionality of the toast (default: ltr)
|
|
163
|
+
hotkey: Keyboard shortcut that will move focus to the toaster area.
|
|
164
|
+
invert: Dark toasts in light mode and vice versa.
|
|
165
|
+
toast_options: These will act as default options for all toasts. See toast() for all available options.
|
|
166
|
+
gap: Gap between toasts when expanded
|
|
167
|
+
loading_icon: Changes the default loading icon
|
|
168
|
+
pause_when_page_is_hidden: Pauses toast timers when the page is hidden, e.g., when the tab is backgrounded, the browser is minimized, or the OS is locked.
|
|
169
|
+
style: The style of the component.
|
|
170
|
+
key: A unique key for the component.
|
|
171
|
+
id: The id for the component.
|
|
172
|
+
class_name: The class name for the component.
|
|
173
|
+
autofocus: Whether the component should take the focus once the page is loaded
|
|
174
|
+
custom_attrs: custom attribute
|
|
175
|
+
**props: The props of the component.
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
The component.
|
|
179
|
+
"""
|
|
180
|
+
...
|
|
181
|
+
|
|
182
|
+
class ToastNamespace(ComponentNamespace):
|
|
183
|
+
provider = staticmethod(Toaster.create)
|
|
184
|
+
options = staticmethod(ToastProps)
|
|
185
|
+
info = staticmethod(Toaster.toast_info)
|
|
186
|
+
warning = staticmethod(Toaster.toast_warning)
|
|
187
|
+
error = staticmethod(Toaster.toast_error)
|
|
188
|
+
success = staticmethod(Toaster.toast_success)
|
|
189
|
+
dismiss = staticmethod(Toaster.toast_dismiss)
|
|
190
|
+
|
|
191
|
+
@staticmethod
|
|
192
|
+
def __call__(message: str, level: Optional[str], **props) -> "Optional[EventSpec]":
|
|
193
|
+
"""Send a toast message.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
message: The message to display.
|
|
197
|
+
level: The level of the toast.
|
|
198
|
+
**props: The options for the toast.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
The toast event.
|
|
202
|
+
"""
|
|
203
|
+
...
|
|
204
|
+
|
|
205
|
+
toast = ToastNamespace()
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
import inspect
|
|
5
|
-
from typing import TYPE_CHECKING, Any, Callable, List, Type
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Callable, List, Tuple, Type, Union, get_args
|
|
6
6
|
|
|
7
7
|
from reflex.components.tags.tag import Tag
|
|
8
8
|
from reflex.vars import BaseVar, Var
|
|
@@ -33,11 +33,14 @@ class IterTag(Tag):
|
|
|
33
33
|
The type of the iterable var.
|
|
34
34
|
"""
|
|
35
35
|
try:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
if self.iterable._var_type.mro()[0] == dict:
|
|
37
|
+
# Arg is a tuple of (key, value).
|
|
38
|
+
return Tuple[get_args(self.iterable._var_type)] # type: ignore
|
|
39
|
+
elif self.iterable._var_type.mro()[0] == tuple:
|
|
40
|
+
# Arg is a union of any possible values in the tuple.
|
|
41
|
+
return Union[get_args(self.iterable._var_type)] # type: ignore
|
|
42
|
+
else:
|
|
43
|
+
return get_args(self.iterable._var_type)[0]
|
|
41
44
|
except Exception:
|
|
42
45
|
return Any
|
|
43
46
|
|
reflex/config.py
CHANGED
|
@@ -6,16 +6,10 @@ import importlib
|
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
8
|
import urllib.parse
|
|
9
|
-
from typing import
|
|
9
|
+
from typing import Any, Dict, List, Optional, Set
|
|
10
10
|
|
|
11
11
|
try:
|
|
12
|
-
|
|
13
|
-
# reflex-hosting-cli tools are compatible with pydantic v2
|
|
14
|
-
|
|
15
|
-
if not TYPE_CHECKING:
|
|
16
|
-
import pydantic.v1 as pydantic
|
|
17
|
-
else:
|
|
18
|
-
raise ModuleNotFoundError
|
|
12
|
+
import pydantic.v1 as pydantic
|
|
19
13
|
except ModuleNotFoundError:
|
|
20
14
|
import pydantic
|
|
21
15
|
|
|
@@ -135,29 +129,47 @@ class DBConfig(Base):
|
|
|
135
129
|
|
|
136
130
|
|
|
137
131
|
class Config(Base):
|
|
138
|
-
"""
|
|
132
|
+
"""The config defines runtime settings for the app.
|
|
133
|
+
|
|
134
|
+
By default, the config is defined in an `rxconfig.py` file in the root of the app.
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
# rxconfig.py
|
|
138
|
+
import reflex as rx
|
|
139
|
+
|
|
140
|
+
config = rx.Config(
|
|
141
|
+
app_name="myapp",
|
|
142
|
+
api_url="http://localhost:8000",
|
|
143
|
+
)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Every config value can be overridden by an environment variable with the same name in uppercase.
|
|
147
|
+
For example, `db_url` can be overridden by setting the `DB_URL` environment variable.
|
|
148
|
+
|
|
149
|
+
See the [configuration](https://reflex.dev/docs/getting-started/configuration/) docs for more info.
|
|
150
|
+
"""
|
|
139
151
|
|
|
140
152
|
class Config:
|
|
141
153
|
"""Pydantic config for the config."""
|
|
142
154
|
|
|
143
155
|
validate_assignment = True
|
|
144
156
|
|
|
145
|
-
# The name of the app.
|
|
157
|
+
# The name of the app (should match the name of the app directory).
|
|
146
158
|
app_name: str
|
|
147
159
|
|
|
148
160
|
# The log level to use.
|
|
149
161
|
loglevel: constants.LogLevel = constants.LogLevel.INFO
|
|
150
162
|
|
|
151
|
-
# The port to run the frontend on.
|
|
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.
|
|
152
164
|
frontend_port: int = 3000
|
|
153
165
|
|
|
154
|
-
# The path to run the frontend on.
|
|
166
|
+
# The path to run the frontend on. For example, "/app" will run the frontend on http://localhost:3000/app
|
|
155
167
|
frontend_path: str = ""
|
|
156
168
|
|
|
157
|
-
# The port to run the backend on.
|
|
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.
|
|
158
170
|
backend_port: int = 8000
|
|
159
171
|
|
|
160
|
-
# The backend url the frontend will connect to.
|
|
172
|
+
# The backend url the frontend will connect to. This must be updated if the backend is hosted elsewhere, or in production.
|
|
161
173
|
api_url: str = f"http://localhost:{backend_port}"
|
|
162
174
|
|
|
163
175
|
# The url the frontend will be hosted on.
|
|
@@ -166,10 +178,10 @@ class Config(Base):
|
|
|
166
178
|
# The url the backend will be hosted on.
|
|
167
179
|
backend_host: str = "0.0.0.0"
|
|
168
180
|
|
|
169
|
-
# The database url.
|
|
181
|
+
# The database url used by rx.Model.
|
|
170
182
|
db_url: Optional[str] = "sqlite:///reflex.db"
|
|
171
183
|
|
|
172
|
-
# The redis url
|
|
184
|
+
# The redis url
|
|
173
185
|
redis_url: Optional[str] = None
|
|
174
186
|
|
|
175
187
|
# Telemetry opt-in.
|
|
@@ -190,9 +202,6 @@ class Config(Base):
|
|
|
190
202
|
# Whether to enable or disable nextJS gzip compression.
|
|
191
203
|
next_compression: bool = True
|
|
192
204
|
|
|
193
|
-
# The event namespace for ws connection
|
|
194
|
-
event_namespace: Optional[str] = None
|
|
195
|
-
|
|
196
205
|
# Additional frontend packages to install.
|
|
197
206
|
frontend_packages: List[str] = []
|
|
198
207
|
|
|
@@ -216,9 +225,6 @@ class Config(Base):
|
|
|
216
225
|
"""
|
|
217
226
|
super().__init__(*args, **kwargs)
|
|
218
227
|
|
|
219
|
-
# Check for deprecated values.
|
|
220
|
-
self.check_deprecated_values(**kwargs)
|
|
221
|
-
|
|
222
228
|
# Update the config from environment variables.
|
|
223
229
|
env_kwargs = self.update_from_env()
|
|
224
230
|
for key, env_value in env_kwargs.items():
|
|
@@ -238,29 +244,8 @@ class Config(Base):
|
|
|
238
244
|
"""
|
|
239
245
|
return ".".join([self.app_name, self.app_name])
|
|
240
246
|
|
|
241
|
-
@staticmethod
|
|
242
|
-
def check_deprecated_values(**kwargs):
|
|
243
|
-
"""Check for deprecated config values.
|
|
244
|
-
|
|
245
|
-
Args:
|
|
246
|
-
**kwargs: The kwargs passed to the config.
|
|
247
|
-
|
|
248
|
-
Raises:
|
|
249
|
-
ValueError: If a deprecated config value is found.
|
|
250
|
-
"""
|
|
251
|
-
if "db_config" in kwargs:
|
|
252
|
-
raise ValueError("db_config is deprecated - use db_url instead")
|
|
253
|
-
if "admin_dash" in kwargs:
|
|
254
|
-
raise ValueError(
|
|
255
|
-
"admin_dash is deprecated in the config - pass it as a param to rx.App instead"
|
|
256
|
-
)
|
|
257
|
-
if "env_path" in kwargs:
|
|
258
|
-
raise ValueError(
|
|
259
|
-
"env_path is deprecated - use environment variables instead"
|
|
260
|
-
)
|
|
261
|
-
|
|
262
247
|
def update_from_env(self) -> dict[str, Any]:
|
|
263
|
-
"""Update the config
|
|
248
|
+
"""Update the config values based on set environment variables.
|
|
264
249
|
|
|
265
250
|
Returns:
|
|
266
251
|
The updated config values.
|
|
@@ -300,20 +285,11 @@ class Config(Base):
|
|
|
300
285
|
return updated_values
|
|
301
286
|
|
|
302
287
|
def get_event_namespace(self) -> str:
|
|
303
|
-
"""Get the
|
|
288
|
+
"""Get the path that the backend Websocket server lists on.
|
|
304
289
|
|
|
305
290
|
Returns:
|
|
306
291
|
The namespace for websocket.
|
|
307
292
|
"""
|
|
308
|
-
if self.event_namespace:
|
|
309
|
-
console.deprecate(
|
|
310
|
-
feature_name="Passing event_namespace in the config",
|
|
311
|
-
reason="",
|
|
312
|
-
deprecation_version="0.3.5",
|
|
313
|
-
removal_version="0.5.0",
|
|
314
|
-
)
|
|
315
|
-
return f'/{self.event_namespace.strip("/")}'
|
|
316
|
-
|
|
317
293
|
event_url = constants.Endpoint.EVENT.get_url()
|
|
318
294
|
return urllib.parse.urlsplit(event_url).path
|
|
319
295
|
|
reflex/constants/__init__.py
CHANGED
|
@@ -4,7 +4,6 @@ from .base import (
|
|
|
4
4
|
COOKIES,
|
|
5
5
|
ENV_MODE_ENV_VAR,
|
|
6
6
|
IS_WINDOWS,
|
|
7
|
-
IS_WINDOWS_BUN_SUPPORTED_MACHINE, # type: ignore
|
|
8
7
|
LOCAL_STORAGE,
|
|
9
8
|
POLLING_MAX_HTTP_BUFFER_SIZE,
|
|
10
9
|
PYTEST_CURRENT_TEST,
|
|
@@ -87,7 +86,6 @@ __ALL__ = [
|
|
|
87
86
|
Hooks,
|
|
88
87
|
Imports,
|
|
89
88
|
IS_WINDOWS,
|
|
90
|
-
IS_WINDOWS_BUN_SUPPORTED_MACHINE,
|
|
91
89
|
LOCAL_STORAGE,
|
|
92
90
|
LogLevel,
|
|
93
91
|
MemoizationDisposition,
|
reflex/constants/base.py
CHANGED
|
@@ -11,11 +11,6 @@ from types import SimpleNamespace
|
|
|
11
11
|
from platformdirs import PlatformDirs
|
|
12
12
|
|
|
13
13
|
IS_WINDOWS = platform.system() == "Windows"
|
|
14
|
-
# https://github.com/oven-sh/bun/blob/main/src/cli/install.ps1
|
|
15
|
-
IS_WINDOWS_BUN_SUPPORTED_MACHINE = IS_WINDOWS and platform.machine() in [
|
|
16
|
-
"AMD64",
|
|
17
|
-
"x86_64",
|
|
18
|
-
] # filter out 32 bit + ARM
|
|
19
14
|
|
|
20
15
|
|
|
21
16
|
class Dirs(SimpleNamespace):
|