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.

Files changed (133) hide show
  1. reflex/.templates/apps/blank/code/blank.py +19 -16
  2. reflex/.templates/apps/demo/code/demo.py +1 -1
  3. reflex/.templates/apps/demo/code/pages/datatable.py +4 -4
  4. reflex/.templates/apps/demo/code/pages/forms.py +2 -2
  5. reflex/.templates/jinja/web/tailwind.config.js.jinja2 +12 -0
  6. reflex/.templates/web/utils/helpers/debounce.js +17 -0
  7. reflex/.templates/web/utils/helpers/throttle.js +22 -0
  8. reflex/.templates/web/utils/state.js +21 -3
  9. reflex/__init__.py +6 -1
  10. reflex/__init__.pyi +4 -1
  11. reflex/app.py +160 -140
  12. reflex/app_module_for_backend.py +1 -1
  13. reflex/base.py +13 -15
  14. reflex/compiler/compiler.py +10 -1
  15. reflex/compiler/utils.py +3 -30
  16. reflex/components/__init__.py +1 -0
  17. reflex/components/chakra/datadisplay/list.py +1 -3
  18. reflex/components/chakra/datadisplay/list.pyi +3 -3
  19. reflex/components/chakra/disclosure/accordion.py +1 -1
  20. reflex/components/chakra/forms/pininput.pyi +1 -1
  21. reflex/components/chakra/media/icon.py +2 -2
  22. reflex/components/component.py +275 -32
  23. reflex/components/core/__init__.py +2 -2
  24. reflex/components/core/cond.py +1 -10
  25. reflex/components/core/debounce.py +5 -2
  26. reflex/components/core/debounce.pyi +4 -2
  27. reflex/components/core/foreach.py +60 -49
  28. reflex/components/core/html.py +6 -0
  29. reflex/components/core/match.py +2 -17
  30. reflex/components/core/upload.py +42 -1
  31. reflex/components/core/upload.pyi +199 -1
  32. reflex/components/datadisplay/code.py +7 -3
  33. reflex/components/datadisplay/code.pyi +3 -1
  34. reflex/components/el/elements/forms.py +1 -1
  35. reflex/components/el/elements/forms.pyi +1 -1
  36. reflex/components/lucide/icon.py +5 -13
  37. reflex/components/lucide/icon.pyi +0 -1
  38. reflex/components/markdown/markdown.py +5 -23
  39. reflex/components/markdown/markdown.pyi +1 -4
  40. reflex/components/radix/primitives/accordion.py +265 -410
  41. reflex/components/radix/primitives/accordion.pyi +390 -36
  42. reflex/components/radix/primitives/form.py +33 -29
  43. reflex/components/radix/primitives/form.pyi +7 -2
  44. reflex/components/radix/primitives/progress.py +17 -9
  45. reflex/components/radix/primitives/progress.pyi +2 -0
  46. reflex/components/radix/primitives/slider.py +30 -18
  47. reflex/components/radix/primitives/slider.pyi +4 -0
  48. reflex/components/radix/themes/base.py +8 -1
  49. reflex/components/radix/themes/base.pyi +79 -1
  50. reflex/components/radix/themes/color_mode.py +88 -20
  51. reflex/components/radix/themes/color_mode.pyi +157 -139
  52. reflex/components/radix/themes/components/__init__.py +17 -0
  53. reflex/components/radix/themes/components/badge.py +2 -1
  54. reflex/components/radix/themes/components/badge.pyi +3 -1
  55. reflex/components/radix/themes/components/button.py +3 -1
  56. reflex/components/radix/themes/components/button.pyi +4 -1
  57. reflex/components/radix/themes/components/checkbox_cards.py +48 -0
  58. reflex/components/radix/themes/components/checkbox_cards.pyi +264 -0
  59. reflex/components/radix/themes/components/checkbox_group.py +42 -0
  60. reflex/components/radix/themes/components/checkbox_group.pyi +253 -0
  61. reflex/components/radix/themes/components/data_list.py +63 -0
  62. reflex/components/radix/themes/components/data_list.pyi +426 -0
  63. reflex/components/radix/themes/components/icon_button.py +20 -17
  64. reflex/components/radix/themes/components/icon_button.pyi +5 -1
  65. reflex/components/radix/themes/components/progress.py +55 -0
  66. reflex/components/radix/themes/components/progress.pyi +180 -0
  67. reflex/components/radix/themes/components/radio.py +31 -0
  68. reflex/components/radix/themes/components/radio.pyi +169 -0
  69. reflex/components/radix/themes/components/radio_cards.py +48 -0
  70. reflex/components/radix/themes/components/radio_cards.pyi +264 -0
  71. reflex/components/radix/themes/components/radio_group.py +2 -4
  72. reflex/components/radix/themes/components/segmented_control.py +48 -0
  73. reflex/components/radix/themes/components/segmented_control.pyi +262 -0
  74. reflex/components/radix/themes/components/skeleton.py +32 -0
  75. reflex/components/radix/themes/components/skeleton.pyi +106 -0
  76. reflex/components/radix/themes/components/spinner.py +26 -0
  77. reflex/components/radix/themes/components/spinner.pyi +101 -0
  78. reflex/components/radix/themes/components/tabs.py +26 -1
  79. reflex/components/radix/themes/components/tabs.pyi +69 -9
  80. reflex/components/radix/themes/components/text_field.py +101 -71
  81. reflex/components/radix/themes/components/text_field.pyi +81 -499
  82. reflex/components/radix/themes/layout/base.py +2 -2
  83. reflex/components/radix/themes/layout/base.pyi +4 -4
  84. reflex/components/radix/themes/layout/center.py +8 -3
  85. reflex/components/radix/themes/layout/center.pyi +2 -1
  86. reflex/components/radix/themes/layout/container.py +30 -2
  87. reflex/components/radix/themes/layout/container.pyi +9 -30
  88. reflex/components/radix/themes/layout/list.py +10 -5
  89. reflex/components/radix/themes/layout/list.pyi +5 -21
  90. reflex/components/radix/themes/layout/spacer.py +8 -3
  91. reflex/components/radix/themes/layout/spacer.pyi +2 -1
  92. reflex/components/radix/themes/layout/stack.py +7 -1
  93. reflex/components/radix/themes/layout/stack.pyi +3 -3
  94. reflex/components/radix/themes/typography/link.py +10 -2
  95. reflex/components/radix/themes/typography/link.pyi +5 -4
  96. reflex/components/sonner/__init__.py +3 -0
  97. reflex/components/sonner/toast.py +267 -0
  98. reflex/components/sonner/toast.pyi +205 -0
  99. reflex/components/tags/iter_tag.py +9 -6
  100. reflex/config.py +30 -54
  101. reflex/constants/__init__.py +0 -2
  102. reflex/constants/base.py +0 -5
  103. reflex/constants/colors.py +2 -0
  104. reflex/constants/installer.py +6 -1
  105. reflex/constants/route.py +4 -0
  106. reflex/custom_components/custom_components.py +24 -2
  107. reflex/event.py +75 -30
  108. reflex/experimental/__init__.py +5 -0
  109. reflex/experimental/layout.py +24 -6
  110. reflex/model.py +2 -1
  111. reflex/page.py +7 -4
  112. reflex/reflex.py +8 -3
  113. reflex/route.py +39 -0
  114. reflex/state.py +128 -131
  115. reflex/style.py +25 -3
  116. reflex/testing.py +10 -6
  117. reflex/utils/console.py +3 -1
  118. reflex/utils/exec.py +20 -7
  119. reflex/utils/format.py +1 -1
  120. reflex/utils/imports.py +3 -1
  121. reflex/utils/prerequisites.py +141 -20
  122. reflex/utils/processes.py +21 -1
  123. reflex/utils/pyi_generator.py +100 -5
  124. reflex/utils/serializers.py +1 -1
  125. reflex/utils/telemetry.py +26 -4
  126. reflex/utils/types.py +62 -18
  127. reflex/vars.py +11 -5
  128. {reflex-0.4.9a1.dist-info → reflex-0.5.0.dist-info}/METADATA +16 -4
  129. {reflex-0.4.9a1.dist-info → reflex-0.5.0.dist-info}/RECORD +132 -110
  130. {reflex-0.4.9a1.dist-info → reflex-0.5.0.dist-info}/WHEEL +1 -1
  131. reflex/app.pyi +0 -149
  132. {reflex-0.4.9a1.dist-info → reflex-0.5.0.dist-info}/LICENSE +0 -0
  133. {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
- return (
37
- self.iterable._var_type
38
- if self.iterable._var_type.mro()[0] == dict
39
- else self.iterable._var_type.__args__[0]
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 TYPE_CHECKING, Any, Dict, List, Optional, Set
9
+ from typing import Any, Dict, List, Optional, Set
10
10
 
11
11
  try:
12
- # TODO The type checking guard can be removed once
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
- """A Reflex config."""
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 from environment variables.
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 websocket event namespace.
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
 
@@ -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):
@@ -37,6 +37,8 @@ ColorType = Literal[
37
37
  "bronze",
38
38
  "gray",
39
39
  "accent",
40
+ "black",
41
+ "white",
40
42
  ]
41
43
 
42
44
  ShadeType = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]