reflex 0.6.0__py3-none-any.whl → 0.6.0a1__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/jinja/custom_components/pyproject.toml.jinja2 +2 -2
- reflex/.templates/jinja/web/pages/_app.js.jinja2 +1 -1
- reflex/.templates/jinja/web/pages/utils.js.jinja2 +2 -2
- reflex/.templates/web/components/reflex/chakra_color_mode_provider.js +36 -0
- reflex/.templates/web/utils/state.js +1 -3
- reflex/__init__.py +2 -8
- reflex/__init__.pyi +1 -2
- reflex/app.py +2 -4
- reflex/app_module_for_backend.py +1 -1
- reflex/base.py +1 -1
- reflex/compiler/compiler.py +2 -2
- reflex/compiler/utils.py +3 -3
- reflex/components/base/app_wrap.py +2 -2
- reflex/components/base/app_wrap.pyi +27 -17
- reflex/components/base/bare.py +5 -4
- reflex/components/base/body.pyi +27 -17
- reflex/components/base/document.pyi +131 -81
- reflex/components/base/error_boundary.py +7 -6
- reflex/components/base/error_boundary.pyi +33 -20
- reflex/components/base/fragment.pyi +27 -17
- reflex/components/base/head.pyi +53 -33
- reflex/components/base/link.py +1 -1
- reflex/components/base/link.pyi +54 -33
- reflex/components/base/meta.pyi +105 -65
- reflex/components/base/script.py +2 -1
- reflex/components/base/script.pyi +38 -21
- reflex/components/component.py +47 -53
- reflex/components/core/banner.py +27 -23
- reflex/components/core/banner.pyi +171 -134
- reflex/components/core/client_side_routing.py +3 -2
- reflex/components/core/client_side_routing.pyi +54 -33
- reflex/components/core/clipboard.py +1 -2
- reflex/components/core/clipboard.pyi +33 -20
- reflex/components/core/cond.py +5 -5
- reflex/components/core/debounce.py +5 -5
- reflex/components/core/debounce.pyi +33 -20
- reflex/components/core/foreach.py +4 -3
- reflex/components/core/html.py +1 -1
- reflex/components/core/html.pyi +46 -35
- reflex/components/core/match.py +17 -17
- reflex/components/core/upload.py +23 -17
- reflex/components/core/upload.pyi +124 -78
- reflex/components/datadisplay/code.py +10 -9
- reflex/components/datadisplay/code.pyi +409 -299
- reflex/components/datadisplay/dataeditor.py +10 -8
- reflex/components/datadisplay/dataeditor.pyi +53 -40
- reflex/components/el/element.pyi +27 -17
- reflex/components/el/elements/base.py +1 -1
- reflex/components/el/elements/base.pyi +45 -34
- reflex/components/el/elements/forms.py +16 -16
- reflex/components/el/elements/forms.pyi +707 -554
- reflex/components/el/elements/inline.py +1 -1
- reflex/components/el/elements/inline.pyi +1218 -937
- reflex/components/el/elements/media.py +1 -1
- reflex/components/el/elements/media.pyi +997 -786
- reflex/components/el/elements/metadata.py +6 -3
- reflex/components/el/elements/metadata.pyi +242 -181
- reflex/components/el/elements/other.py +1 -1
- reflex/components/el/elements/other.pyi +306 -235
- reflex/components/el/elements/scripts.py +1 -1
- reflex/components/el/elements/scripts.pyi +140 -109
- reflex/components/el/elements/sectioning.py +2 -0
- reflex/components/el/elements/sectioning.pyi +647 -496
- reflex/components/el/elements/tables.py +1 -1
- reflex/components/el/elements/tables.pyi +452 -351
- reflex/components/el/elements/typography.py +1 -1
- reflex/components/el/elements/typography.pyi +657 -506
- reflex/components/gridjs/datatable.py +9 -6
- reflex/components/gridjs/datatable.pyi +56 -35
- reflex/components/lucide/icon.py +1 -1
- reflex/components/lucide/icon.pyi +54 -33
- reflex/components/markdown/markdown.py +31 -26
- reflex/components/markdown/markdown.pyi +37 -27
- reflex/components/moment/moment.py +12 -13
- reflex/components/moment/moment.pyi +35 -23
- reflex/components/next/base.pyi +27 -17
- reflex/components/next/image.py +1 -1
- reflex/components/next/image.pyi +37 -22
- reflex/components/next/link.py +1 -1
- reflex/components/next/link.pyi +28 -17
- reflex/components/next/video.py +1 -1
- reflex/components/next/video.pyi +28 -17
- reflex/components/plotly/plotly.py +13 -12
- reflex/components/plotly/plotly.pyi +54 -39
- reflex/components/props.py +1 -1
- reflex/components/radix/__init__.pyi +0 -1
- reflex/components/radix/primitives/__init__.pyi +0 -1
- reflex/components/radix/primitives/accordion.py +4 -4
- reflex/components/radix/primitives/accordion.pyi +495 -424
- reflex/components/radix/primitives/base.py +1 -1
- reflex/components/radix/primitives/base.pyi +54 -33
- reflex/components/radix/primitives/drawer.py +1 -1
- reflex/components/radix/primitives/drawer.pyi +273 -172
- reflex/components/radix/primitives/form.py +1 -1
- reflex/components/radix/primitives/form.pyi +364 -257
- reflex/components/radix/primitives/progress.py +1 -1
- reflex/components/radix/primitives/progress.pyi +282 -231
- reflex/components/radix/primitives/slider.py +1 -1
- reflex/components/radix/primitives/slider.pyi +138 -87
- reflex/components/radix/themes/base.py +24 -3
- reflex/components/radix/themes/base.pyi +250 -178
- reflex/components/radix/themes/color_mode.py +5 -5
- reflex/components/radix/themes/color_mode.pyi +220 -187
- reflex/components/radix/themes/components/alert_dialog.py +1 -1
- reflex/components/radix/themes/components/alert_dialog.pyi +207 -136
- reflex/components/radix/themes/components/aspect_ratio.py +1 -1
- reflex/components/radix/themes/components/aspect_ratio.pyi +28 -17
- reflex/components/radix/themes/components/avatar.py +1 -1
- reflex/components/radix/themes/components/avatar.pyi +81 -70
- reflex/components/radix/themes/components/badge.py +1 -1
- reflex/components/radix/themes/components/badge.pyi +99 -88
- reflex/components/radix/themes/components/button.py +1 -1
- reflex/components/radix/themes/components/button.pyi +109 -98
- reflex/components/radix/themes/components/callout.py +1 -1
- reflex/components/radix/themes/components/callout.pyi +373 -322
- reflex/components/radix/themes/components/card.py +1 -1
- reflex/components/radix/themes/components/card.pyi +49 -38
- reflex/components/radix/themes/components/checkbox.py +2 -1
- reflex/components/radix/themes/components/checkbox.pyi +245 -208
- reflex/components/radix/themes/components/checkbox_cards.py +1 -1
- reflex/components/radix/themes/components/checkbox_cards.pyi +115 -94
- reflex/components/radix/themes/components/checkbox_group.py +1 -1
- reflex/components/radix/themes/components/checkbox_group.pyi +107 -86
- reflex/components/radix/themes/components/context_menu.py +1 -1
- reflex/components/radix/themes/components/context_menu.pyi +319 -238
- reflex/components/radix/themes/components/data_list.py +1 -1
- reflex/components/radix/themes/components/data_list.pyi +171 -130
- reflex/components/radix/themes/components/dialog.py +1 -1
- reflex/components/radix/themes/components/dialog.pyi +210 -139
- reflex/components/radix/themes/components/dropdown_menu.py +1 -1
- reflex/components/radix/themes/components/dropdown_menu.pyi +332 -249
- reflex/components/radix/themes/components/hover_card.py +1 -1
- reflex/components/radix/themes/components/hover_card.pyi +131 -90
- reflex/components/radix/themes/components/icon_button.py +3 -2
- reflex/components/radix/themes/components/icon_button.pyi +109 -98
- reflex/components/radix/themes/components/inset.py +1 -1
- reflex/components/radix/themes/components/inset.pyi +58 -47
- reflex/components/radix/themes/components/popover.py +1 -1
- reflex/components/radix/themes/components/popover.pyi +136 -95
- reflex/components/radix/themes/components/progress.py +1 -1
- reflex/components/radix/themes/components/progress.pyi +82 -71
- reflex/components/radix/themes/components/radio.py +1 -1
- reflex/components/radix/themes/components/radio.pyi +80 -69
- reflex/components/radix/themes/components/radio_cards.py +1 -1
- reflex/components/radix/themes/components/radio_cards.pyi +119 -98
- reflex/components/radix/themes/components/radio_group.py +11 -8
- reflex/components/radix/themes/components/radio_group.pyi +271 -228
- reflex/components/radix/themes/components/scroll_area.py +1 -1
- reflex/components/radix/themes/components/scroll_area.pyi +32 -21
- reflex/components/radix/themes/components/segmented_control.py +1 -1
- reflex/components/radix/themes/components/segmented_control.pyi +113 -90
- reflex/components/radix/themes/components/select.py +3 -2
- reflex/components/radix/themes/components/select.pyi +471 -374
- reflex/components/radix/themes/components/separator.py +2 -1
- reflex/components/radix/themes/components/separator.pyi +80 -69
- reflex/components/radix/themes/components/skeleton.py +1 -1
- reflex/components/radix/themes/components/skeleton.pyi +34 -23
- reflex/components/radix/themes/components/slider.py +3 -2
- reflex/components/radix/themes/components/slider.pyi +88 -75
- reflex/components/radix/themes/components/spinner.py +1 -1
- reflex/components/radix/themes/components/spinner.pyi +30 -19
- reflex/components/radix/themes/components/switch.py +1 -1
- reflex/components/radix/themes/components/switch.pyi +84 -71
- reflex/components/radix/themes/components/table.py +1 -1
- reflex/components/radix/themes/components/table.pyi +332 -261
- reflex/components/radix/themes/components/tabs.py +1 -1
- reflex/components/radix/themes/components/tabs.pyi +194 -139
- reflex/components/radix/themes/components/text_area.py +1 -1
- reflex/components/radix/themes/components/text_area.pyi +111 -96
- reflex/components/radix/themes/components/text_field.py +1 -1
- reflex/components/radix/themes/components/text_field.pyi +286 -247
- reflex/components/radix/themes/components/tooltip.py +1 -1
- reflex/components/radix/themes/components/tooltip.pyi +37 -26
- reflex/components/radix/themes/layout/__init__.pyi +0 -1
- reflex/components/radix/themes/layout/base.py +1 -1
- reflex/components/radix/themes/layout/base.pyi +67 -56
- reflex/components/radix/themes/layout/box.pyi +45 -34
- reflex/components/radix/themes/layout/center.pyi +67 -56
- reflex/components/radix/themes/layout/container.py +2 -1
- reflex/components/radix/themes/layout/container.pyi +47 -36
- reflex/components/radix/themes/layout/flex.py +1 -1
- reflex/components/radix/themes/layout/flex.pyi +67 -56
- reflex/components/radix/themes/layout/grid.py +1 -1
- reflex/components/radix/themes/layout/grid.pyi +75 -64
- reflex/components/radix/themes/layout/list.py +6 -5
- reflex/components/radix/themes/layout/list.pyi +244 -193
- reflex/components/radix/themes/layout/section.py +2 -1
- reflex/components/radix/themes/layout/section.pyi +47 -36
- reflex/components/radix/themes/layout/spacer.pyi +67 -56
- reflex/components/radix/themes/layout/stack.py +1 -1
- reflex/components/radix/themes/layout/stack.pyi +159 -128
- reflex/components/radix/themes/typography/blockquote.py +1 -1
- reflex/components/radix/themes/typography/blockquote.pyi +100 -89
- reflex/components/radix/themes/typography/code.py +1 -1
- reflex/components/radix/themes/typography/code.pyi +101 -90
- reflex/components/radix/themes/typography/heading.py +1 -1
- reflex/components/radix/themes/typography/heading.pyi +107 -96
- reflex/components/radix/themes/typography/link.py +1 -1
- reflex/components/radix/themes/typography/link.pyi +113 -102
- reflex/components/radix/themes/typography/text.py +1 -1
- reflex/components/radix/themes/typography/text.pyi +572 -501
- reflex/components/react_player/audio.pyi +60 -33
- reflex/components/react_player/react_player.py +1 -1
- reflex/components/react_player/react_player.pyi +60 -33
- reflex/components/react_player/video.pyi +60 -33
- reflex/components/recharts/cartesian.py +3 -2
- reflex/components/recharts/cartesian.pyi +861 -678
- reflex/components/recharts/charts.py +5 -4
- reflex/components/recharts/charts.pyi +357 -252
- reflex/components/recharts/general.py +2 -1
- reflex/components/recharts/general.pyi +231 -180
- reflex/components/recharts/polar.py +5 -4
- reflex/components/recharts/polar.pyi +181 -144
- reflex/components/recharts/recharts.pyi +53 -33
- reflex/components/sonner/toast.py +17 -16
- reflex/components/sonner/toast.pyi +47 -36
- reflex/components/suneditor/editor.py +3 -2
- reflex/components/suneditor/editor.pyi +78 -55
- reflex/components/tags/cond_tag.py +4 -6
- reflex/components/tags/iter_tag.py +16 -28
- reflex/components/tags/match_tag.py +4 -6
- reflex/components/tags/tag.py +23 -40
- reflex/custom_components/custom_components.py +1 -3
- reflex/event.py +65 -113
- reflex/experimental/client_state.py +24 -25
- reflex/experimental/hooks.py +16 -16
- reflex/experimental/layout.py +5 -5
- reflex/experimental/layout.pyi +187 -136
- reflex/{vars → ivars}/__init__.py +2 -6
- reflex/{vars → ivars}/base.py +216 -599
- reflex/{vars → ivars}/function.py +19 -15
- reflex/{vars → ivars}/number.py +20 -41
- reflex/{vars → ivars}/object.py +30 -28
- reflex/{vars → ivars}/sequence.py +50 -53
- reflex/middleware/hydrate_middleware.py +0 -2
- reflex/middleware/middleware.py +3 -3
- reflex/state.py +82 -148
- reflex/style.py +22 -21
- reflex/utils/exceptions.py +0 -20
- reflex/utils/format.py +34 -54
- reflex/utils/imports.py +73 -16
- reflex/utils/prerequisites.py +15 -35
- reflex/utils/pyi_generator.py +8 -13
- reflex/utils/serializers.py +22 -12
- reflex/utils/telemetry.py +2 -3
- reflex/utils/types.py +5 -10
- reflex/vars.py +501 -0
- {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/METADATA +5 -4
- reflex-0.6.0a1.dist-info/RECORD +384 -0
- reflex-0.6.0.dist-info/RECORD +0 -382
- {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/LICENSE +0 -0
- {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/WHEEL +0 -0
- {reflex-0.6.0.dist-info → reflex-0.6.0a1.dist-info}/entry_points.txt +0 -0
|
@@ -2,43 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import dataclasses
|
|
6
5
|
import inspect
|
|
7
|
-
from typing import
|
|
8
|
-
TYPE_CHECKING,
|
|
9
|
-
Any,
|
|
10
|
-
Callable,
|
|
11
|
-
Iterable,
|
|
12
|
-
Tuple,
|
|
13
|
-
Type,
|
|
14
|
-
Union,
|
|
15
|
-
get_args,
|
|
16
|
-
)
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Callable, List, Tuple, Type, Union, get_args
|
|
17
7
|
|
|
18
8
|
from reflex.components.tags.tag import Tag
|
|
19
|
-
from reflex.
|
|
9
|
+
from reflex.ivars.base import ImmutableVar
|
|
10
|
+
from reflex.vars import Var
|
|
20
11
|
|
|
21
12
|
if TYPE_CHECKING:
|
|
22
13
|
from reflex.components.component import Component
|
|
23
14
|
|
|
24
15
|
|
|
25
|
-
@dataclasses.dataclass()
|
|
26
16
|
class IterTag(Tag):
|
|
27
17
|
"""An iterator tag."""
|
|
28
18
|
|
|
29
19
|
# The var to iterate over.
|
|
30
|
-
iterable: Var[
|
|
31
|
-
default_factory=lambda: LiteralArrayVar.create([])
|
|
32
|
-
)
|
|
20
|
+
iterable: Var[List]
|
|
33
21
|
|
|
34
22
|
# The component render function for each item in the iterable.
|
|
35
|
-
render_fn: Callable
|
|
23
|
+
render_fn: Callable
|
|
36
24
|
|
|
37
25
|
# The name of the arg var.
|
|
38
|
-
arg_var_name: str
|
|
26
|
+
arg_var_name: str
|
|
39
27
|
|
|
40
28
|
# The name of the index var.
|
|
41
|
-
index_var_name: str
|
|
29
|
+
index_var_name: str
|
|
42
30
|
|
|
43
31
|
def get_iterable_var_type(self) -> Type:
|
|
44
32
|
"""Get the type of the iterable var.
|
|
@@ -46,7 +34,7 @@ class IterTag(Tag):
|
|
|
46
34
|
Returns:
|
|
47
35
|
The type of the iterable var.
|
|
48
36
|
"""
|
|
49
|
-
iterable = self.iterable
|
|
37
|
+
iterable = self.iterable.upcast()
|
|
50
38
|
try:
|
|
51
39
|
if iterable._var_type.mro()[0] == dict:
|
|
52
40
|
# Arg is a tuple of (key, value).
|
|
@@ -67,8 +55,8 @@ class IterTag(Tag):
|
|
|
67
55
|
Returns:
|
|
68
56
|
The index var.
|
|
69
57
|
"""
|
|
70
|
-
return
|
|
71
|
-
|
|
58
|
+
return ImmutableVar(
|
|
59
|
+
_var_name=self.index_var_name,
|
|
72
60
|
_var_type=int,
|
|
73
61
|
).guess_type()
|
|
74
62
|
|
|
@@ -80,8 +68,8 @@ class IterTag(Tag):
|
|
|
80
68
|
Returns:
|
|
81
69
|
The arg var.
|
|
82
70
|
"""
|
|
83
|
-
return
|
|
84
|
-
|
|
71
|
+
return ImmutableVar(
|
|
72
|
+
_var_name=self.arg_var_name,
|
|
85
73
|
_var_type=self.get_iterable_var_type(),
|
|
86
74
|
).guess_type()
|
|
87
75
|
|
|
@@ -93,8 +81,8 @@ class IterTag(Tag):
|
|
|
93
81
|
Returns:
|
|
94
82
|
The index var.
|
|
95
83
|
"""
|
|
96
|
-
return
|
|
97
|
-
|
|
84
|
+
return ImmutableVar(
|
|
85
|
+
_var_name=self.index_var_name,
|
|
98
86
|
_var_type=int,
|
|
99
87
|
).guess_type()
|
|
100
88
|
|
|
@@ -106,8 +94,8 @@ class IterTag(Tag):
|
|
|
106
94
|
Returns:
|
|
107
95
|
The arg var.
|
|
108
96
|
"""
|
|
109
|
-
return
|
|
110
|
-
|
|
97
|
+
return ImmutableVar(
|
|
98
|
+
_var_name=self.arg_var_name,
|
|
111
99
|
_var_type=self.get_iterable_var_type(),
|
|
112
100
|
).guess_type()
|
|
113
101
|
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
"""Tag to conditionally match cases."""
|
|
2
2
|
|
|
3
|
-
import dataclasses
|
|
4
3
|
from typing import Any, List
|
|
5
4
|
|
|
6
5
|
from reflex.components.tags.tag import Tag
|
|
7
|
-
from reflex.vars
|
|
6
|
+
from reflex.vars import Var
|
|
8
7
|
|
|
9
8
|
|
|
10
|
-
@dataclasses.dataclass()
|
|
11
9
|
class MatchTag(Tag):
|
|
12
10
|
"""A match tag."""
|
|
13
11
|
|
|
14
12
|
# The condition to determine which case to match.
|
|
15
|
-
cond: Var[Any]
|
|
13
|
+
cond: Var[Any]
|
|
16
14
|
|
|
17
15
|
# The list of match cases to be matched.
|
|
18
|
-
match_cases: List[Any]
|
|
16
|
+
match_cases: List[Any]
|
|
19
17
|
|
|
20
18
|
# The catchall case to match.
|
|
21
|
-
default: Any
|
|
19
|
+
default: Any
|
reflex/components/tags/tag.py
CHANGED
|
@@ -2,23 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
5
|
+
from typing import Any, Dict, List, Optional, Set, Tuple, Union
|
|
7
6
|
|
|
7
|
+
from reflex.base import Base
|
|
8
8
|
from reflex.event import EventChain
|
|
9
|
+
from reflex.ivars.base import ImmutableVar, LiteralVar
|
|
9
10
|
from reflex.utils import format, types
|
|
10
|
-
from reflex.vars.base import LiteralVar, Var
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
class Tag:
|
|
13
|
+
class Tag(Base):
|
|
15
14
|
"""A React tag."""
|
|
16
15
|
|
|
17
16
|
# The name of the tag.
|
|
18
17
|
name: str = ""
|
|
19
18
|
|
|
20
19
|
# The props of the tag.
|
|
21
|
-
props: Dict[str, Any] =
|
|
20
|
+
props: Dict[str, Any] = {}
|
|
22
21
|
|
|
23
22
|
# The inner contents of the tag.
|
|
24
23
|
contents: str = ""
|
|
@@ -27,18 +26,25 @@ class Tag:
|
|
|
27
26
|
args: Optional[Tuple[str, ...]] = None
|
|
28
27
|
|
|
29
28
|
# Special props that aren't key value pairs.
|
|
30
|
-
special_props:
|
|
29
|
+
special_props: Set[ImmutableVar] = set()
|
|
31
30
|
|
|
32
31
|
# The children components.
|
|
33
|
-
children: List[Any] =
|
|
34
|
-
|
|
35
|
-
def
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
children: List[Any] = []
|
|
33
|
+
|
|
34
|
+
def __init__(self, *args, **kwargs):
|
|
35
|
+
"""Initialize the tag.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
*args: Args to initialize the tag.
|
|
39
|
+
**kwargs: Kwargs to initialize the tag.
|
|
40
|
+
"""
|
|
41
|
+
# Convert any props to vars.
|
|
42
|
+
if "props" in kwargs:
|
|
43
|
+
kwargs["props"] = {
|
|
44
|
+
name: LiteralVar.create(value)
|
|
45
|
+
for name, value in kwargs["props"].items()
|
|
46
|
+
}
|
|
47
|
+
super().__init__(*args, **kwargs)
|
|
42
48
|
|
|
43
49
|
def format_props(self) -> List:
|
|
44
50
|
"""Format the tag's props.
|
|
@@ -48,29 +54,6 @@ class Tag:
|
|
|
48
54
|
"""
|
|
49
55
|
return format.format_props(*self.special_props, **self.props)
|
|
50
56
|
|
|
51
|
-
def set(self, **kwargs: Any):
|
|
52
|
-
"""Set the tag's fields.
|
|
53
|
-
|
|
54
|
-
Args:
|
|
55
|
-
kwargs: The fields to set.
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
The tag with the fields
|
|
59
|
-
"""
|
|
60
|
-
for name, value in kwargs.items():
|
|
61
|
-
setattr(self, name, value)
|
|
62
|
-
|
|
63
|
-
return self
|
|
64
|
-
|
|
65
|
-
def __iter__(self):
|
|
66
|
-
"""Iterate over the tag's fields.
|
|
67
|
-
|
|
68
|
-
Yields:
|
|
69
|
-
Tuple[str, Any]: The field name and value.
|
|
70
|
-
"""
|
|
71
|
-
for field in dataclasses.fields(self):
|
|
72
|
-
yield field.name, getattr(self, field.name)
|
|
73
|
-
|
|
74
57
|
def add_props(self, **kwargs: Optional[Any]) -> Tag:
|
|
75
58
|
"""Add props to the tag.
|
|
76
59
|
|
|
@@ -109,7 +92,7 @@ class Tag:
|
|
|
109
92
|
return self
|
|
110
93
|
|
|
111
94
|
@staticmethod
|
|
112
|
-
def is_valid_prop(prop: Optional[
|
|
95
|
+
def is_valid_prop(prop: Optional[ImmutableVar]) -> bool:
|
|
113
96
|
"""Check if the prop is valid.
|
|
114
97
|
|
|
115
98
|
Args:
|
|
@@ -65,9 +65,7 @@ def _create_package_config(module_name: str, package_name: str):
|
|
|
65
65
|
with open(CustomComponents.PYPROJECT_TOML, "w") as f:
|
|
66
66
|
f.write(
|
|
67
67
|
templates.CUSTOM_COMPONENTS_PYPROJECT_TOML.render(
|
|
68
|
-
module_name=module_name,
|
|
69
|
-
package_name=package_name,
|
|
70
|
-
reflex_version=constants.Reflex.VERSION,
|
|
68
|
+
module_name=module_name, package_name=package_name
|
|
71
69
|
)
|
|
72
70
|
)
|
|
73
71
|
|
reflex/event.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import dataclasses
|
|
6
5
|
import inspect
|
|
7
6
|
import types
|
|
8
7
|
import urllib.parse
|
|
@@ -19,13 +18,14 @@ from typing import (
|
|
|
19
18
|
)
|
|
20
19
|
|
|
21
20
|
from reflex import constants
|
|
21
|
+
from reflex.base import Base
|
|
22
|
+
from reflex.ivars.base import ImmutableVar, LiteralVar
|
|
23
|
+
from reflex.ivars.function import FunctionStringVar, FunctionVar
|
|
24
|
+
from reflex.ivars.object import ObjectVar
|
|
22
25
|
from reflex.utils import format
|
|
23
26
|
from reflex.utils.exceptions import EventFnArgMismatch, EventHandlerArgMismatch
|
|
24
27
|
from reflex.utils.types import ArgsSpec
|
|
25
|
-
from reflex.vars import VarData
|
|
26
|
-
from reflex.vars.base import LiteralVar, Var
|
|
27
|
-
from reflex.vars.function import FunctionStringVar, FunctionVar
|
|
28
|
-
from reflex.vars.object import ObjectVar
|
|
28
|
+
from reflex.vars import Var, VarData
|
|
29
29
|
|
|
30
30
|
try:
|
|
31
31
|
from typing import Annotated
|
|
@@ -33,11 +33,7 @@ except ImportError:
|
|
|
33
33
|
from typing_extensions import Annotated
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
init=True,
|
|
38
|
-
frozen=True,
|
|
39
|
-
)
|
|
40
|
-
class Event:
|
|
36
|
+
class Event(Base):
|
|
41
37
|
"""An event that describes any state change in the app."""
|
|
42
38
|
|
|
43
39
|
# The token to specify the client that the event is for.
|
|
@@ -47,10 +43,10 @@ class Event:
|
|
|
47
43
|
name: str
|
|
48
44
|
|
|
49
45
|
# The routing data where event occurred
|
|
50
|
-
router_data: Dict[str, Any] =
|
|
46
|
+
router_data: Dict[str, Any] = {}
|
|
51
47
|
|
|
52
48
|
# The event payload.
|
|
53
|
-
payload: Dict[str, Any] =
|
|
49
|
+
payload: Dict[str, Any] = {}
|
|
54
50
|
|
|
55
51
|
@property
|
|
56
52
|
def substate_token(self) -> str:
|
|
@@ -85,15 +81,11 @@ def background(fn):
|
|
|
85
81
|
return fn
|
|
86
82
|
|
|
87
83
|
|
|
88
|
-
|
|
89
|
-
init=True,
|
|
90
|
-
frozen=True,
|
|
91
|
-
)
|
|
92
|
-
class EventActionsMixin:
|
|
84
|
+
class EventActionsMixin(Base):
|
|
93
85
|
"""Mixin for DOM event actions."""
|
|
94
86
|
|
|
95
87
|
# Whether to `preventDefault` or `stopPropagation` on the event.
|
|
96
|
-
event_actions: Dict[str, Union[bool, int]] =
|
|
88
|
+
event_actions: Dict[str, Union[bool, int]] = {}
|
|
97
89
|
|
|
98
90
|
@property
|
|
99
91
|
def stop_propagation(self):
|
|
@@ -102,9 +94,8 @@ class EventActionsMixin:
|
|
|
102
94
|
Returns:
|
|
103
95
|
New EventHandler-like with stopPropagation set to True.
|
|
104
96
|
"""
|
|
105
|
-
return
|
|
106
|
-
self,
|
|
107
|
-
event_actions={"stopPropagation": True, **self.event_actions},
|
|
97
|
+
return self.copy(
|
|
98
|
+
update={"event_actions": {"stopPropagation": True, **self.event_actions}},
|
|
108
99
|
)
|
|
109
100
|
|
|
110
101
|
@property
|
|
@@ -114,9 +105,8 @@ class EventActionsMixin:
|
|
|
114
105
|
Returns:
|
|
115
106
|
New EventHandler-like with preventDefault set to True.
|
|
116
107
|
"""
|
|
117
|
-
return
|
|
118
|
-
self,
|
|
119
|
-
event_actions={"preventDefault": True, **self.event_actions},
|
|
108
|
+
return self.copy(
|
|
109
|
+
update={"event_actions": {"preventDefault": True, **self.event_actions}},
|
|
120
110
|
)
|
|
121
111
|
|
|
122
112
|
def throttle(self, limit_ms: int):
|
|
@@ -128,9 +118,8 @@ class EventActionsMixin:
|
|
|
128
118
|
Returns:
|
|
129
119
|
New EventHandler-like with throttle set to limit_ms.
|
|
130
120
|
"""
|
|
131
|
-
return
|
|
132
|
-
self,
|
|
133
|
-
event_actions={"throttle": limit_ms, **self.event_actions},
|
|
121
|
+
return self.copy(
|
|
122
|
+
update={"event_actions": {"throttle": limit_ms, **self.event_actions}},
|
|
134
123
|
)
|
|
135
124
|
|
|
136
125
|
def debounce(self, delay_ms: int):
|
|
@@ -142,25 +131,26 @@ class EventActionsMixin:
|
|
|
142
131
|
Returns:
|
|
143
132
|
New EventHandler-like with debounce set to delay_ms.
|
|
144
133
|
"""
|
|
145
|
-
return
|
|
146
|
-
self,
|
|
147
|
-
event_actions={"debounce": delay_ms, **self.event_actions},
|
|
134
|
+
return self.copy(
|
|
135
|
+
update={"event_actions": {"debounce": delay_ms, **self.event_actions}},
|
|
148
136
|
)
|
|
149
137
|
|
|
150
138
|
|
|
151
|
-
@dataclasses.dataclass(
|
|
152
|
-
init=True,
|
|
153
|
-
frozen=True,
|
|
154
|
-
)
|
|
155
139
|
class EventHandler(EventActionsMixin):
|
|
156
140
|
"""An event handler responds to an event to update the state."""
|
|
157
141
|
|
|
158
142
|
# The function to call in response to the event.
|
|
159
|
-
fn: Any
|
|
143
|
+
fn: Any
|
|
160
144
|
|
|
161
145
|
# The full name of the state class this event handler is attached to.
|
|
162
146
|
# Empty string means this event handler is a server side event.
|
|
163
|
-
state_full_name: str =
|
|
147
|
+
state_full_name: str = ""
|
|
148
|
+
|
|
149
|
+
class Config:
|
|
150
|
+
"""The Pydantic config."""
|
|
151
|
+
|
|
152
|
+
# Needed to allow serialization of Callable.
|
|
153
|
+
frozen = True
|
|
164
154
|
|
|
165
155
|
@classmethod
|
|
166
156
|
def __class_getitem__(cls, args_spec: str) -> Annotated:
|
|
@@ -201,7 +191,7 @@ class EventHandler(EventActionsMixin):
|
|
|
201
191
|
|
|
202
192
|
# Get the function args.
|
|
203
193
|
fn_args = inspect.getfullargspec(self.fn).args[1:]
|
|
204
|
-
fn_args = (
|
|
194
|
+
fn_args = (ImmutableVar.create_safe(arg) for arg in fn_args)
|
|
205
195
|
|
|
206
196
|
# Construct the payload.
|
|
207
197
|
values = []
|
|
@@ -225,10 +215,6 @@ class EventHandler(EventActionsMixin):
|
|
|
225
215
|
)
|
|
226
216
|
|
|
227
217
|
|
|
228
|
-
@dataclasses.dataclass(
|
|
229
|
-
init=True,
|
|
230
|
-
frozen=True,
|
|
231
|
-
)
|
|
232
218
|
class EventSpec(EventActionsMixin):
|
|
233
219
|
"""An event specification.
|
|
234
220
|
|
|
@@ -237,37 +223,23 @@ class EventSpec(EventActionsMixin):
|
|
|
237
223
|
"""
|
|
238
224
|
|
|
239
225
|
# The event handler.
|
|
240
|
-
handler: EventHandler
|
|
226
|
+
handler: EventHandler
|
|
241
227
|
|
|
242
228
|
# The handler on the client to process event.
|
|
243
|
-
client_handler_name: str =
|
|
229
|
+
client_handler_name: str = ""
|
|
244
230
|
|
|
245
231
|
# The arguments to pass to the function.
|
|
246
|
-
args: Tuple[Tuple[
|
|
232
|
+
args: Tuple[Tuple[ImmutableVar, ImmutableVar], ...] = ()
|
|
247
233
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
handler: EventHandler,
|
|
251
|
-
event_actions: Dict[str, Union[bool, int]] | None = None,
|
|
252
|
-
client_handler_name: str = "",
|
|
253
|
-
args: Tuple[Tuple[Var, Var], ...] = tuple(),
|
|
254
|
-
):
|
|
255
|
-
"""Initialize an EventSpec.
|
|
234
|
+
class Config:
|
|
235
|
+
"""The Pydantic config."""
|
|
256
236
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if event_actions is None:
|
|
264
|
-
event_actions = {}
|
|
265
|
-
object.__setattr__(self, "event_actions", event_actions)
|
|
266
|
-
object.__setattr__(self, "handler", handler)
|
|
267
|
-
object.__setattr__(self, "client_handler_name", client_handler_name)
|
|
268
|
-
object.__setattr__(self, "args", args or tuple())
|
|
269
|
-
|
|
270
|
-
def with_args(self, args: Tuple[Tuple[Var, Var], ...]) -> EventSpec:
|
|
237
|
+
# Required to allow tuple fields.
|
|
238
|
+
frozen = True
|
|
239
|
+
|
|
240
|
+
def with_args(
|
|
241
|
+
self, args: Tuple[Tuple[ImmutableVar, ImmutableVar], ...]
|
|
242
|
+
) -> EventSpec:
|
|
271
243
|
"""Copy the event spec, with updated args.
|
|
272
244
|
|
|
273
245
|
Args:
|
|
@@ -283,7 +255,7 @@ class EventSpec(EventActionsMixin):
|
|
|
283
255
|
event_actions=self.event_actions.copy(),
|
|
284
256
|
)
|
|
285
257
|
|
|
286
|
-
def add_args(self, *args:
|
|
258
|
+
def add_args(self, *args: ImmutableVar) -> EventSpec:
|
|
287
259
|
"""Add arguments to the event spec.
|
|
288
260
|
|
|
289
261
|
Args:
|
|
@@ -299,7 +271,7 @@ class EventSpec(EventActionsMixin):
|
|
|
299
271
|
|
|
300
272
|
# Get the remaining unfilled function args.
|
|
301
273
|
fn_args = inspect.getfullargspec(self.handler.fn).args[1 + len(self.args) :]
|
|
302
|
-
fn_args = (
|
|
274
|
+
fn_args = (ImmutableVar.create_safe(arg) for arg in fn_args)
|
|
303
275
|
|
|
304
276
|
# Construct the payload.
|
|
305
277
|
values = []
|
|
@@ -314,9 +286,6 @@ class EventSpec(EventActionsMixin):
|
|
|
314
286
|
return self.with_args(self.args + new_payload)
|
|
315
287
|
|
|
316
288
|
|
|
317
|
-
@dataclasses.dataclass(
|
|
318
|
-
frozen=True,
|
|
319
|
-
)
|
|
320
289
|
class CallableEventSpec(EventSpec):
|
|
321
290
|
"""Decorate an EventSpec-returning function to act as both a EventSpec and a function.
|
|
322
291
|
|
|
@@ -336,13 +305,10 @@ class CallableEventSpec(EventSpec):
|
|
|
336
305
|
if fn is not None:
|
|
337
306
|
default_event_spec = fn()
|
|
338
307
|
super().__init__(
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
args=default_event_spec.args,
|
|
342
|
-
handler=default_event_spec.handler,
|
|
308
|
+
fn=fn, # type: ignore
|
|
309
|
+
**default_event_spec.dict(),
|
|
343
310
|
**kwargs,
|
|
344
311
|
)
|
|
345
|
-
object.__setattr__(self, "fn", fn)
|
|
346
312
|
else:
|
|
347
313
|
super().__init__(**kwargs)
|
|
348
314
|
|
|
@@ -366,16 +332,12 @@ class CallableEventSpec(EventSpec):
|
|
|
366
332
|
return self.fn(*args, **kwargs)
|
|
367
333
|
|
|
368
334
|
|
|
369
|
-
@dataclasses.dataclass(
|
|
370
|
-
init=True,
|
|
371
|
-
frozen=True,
|
|
372
|
-
)
|
|
373
335
|
class EventChain(EventActionsMixin):
|
|
374
336
|
"""Container for a chain of events that will be executed in order."""
|
|
375
337
|
|
|
376
|
-
events: List[EventSpec]
|
|
338
|
+
events: List[EventSpec]
|
|
377
339
|
|
|
378
|
-
args_spec: Optional[Callable]
|
|
340
|
+
args_spec: Optional[Callable]
|
|
379
341
|
|
|
380
342
|
|
|
381
343
|
# These chains can be used for their side effects when no other events are desired.
|
|
@@ -383,22 +345,14 @@ stop_propagation = EventChain(events=[], args_spec=lambda: []).stop_propagation
|
|
|
383
345
|
prevent_default = EventChain(events=[], args_spec=lambda: []).prevent_default
|
|
384
346
|
|
|
385
347
|
|
|
386
|
-
|
|
387
|
-
init=True,
|
|
388
|
-
frozen=True,
|
|
389
|
-
)
|
|
390
|
-
class Target:
|
|
348
|
+
class Target(Base):
|
|
391
349
|
"""A Javascript event target."""
|
|
392
350
|
|
|
393
351
|
checked: bool = False
|
|
394
352
|
value: Any = None
|
|
395
353
|
|
|
396
354
|
|
|
397
|
-
|
|
398
|
-
init=True,
|
|
399
|
-
frozen=True,
|
|
400
|
-
)
|
|
401
|
-
class FrontendEvent:
|
|
355
|
+
class FrontendEvent(Base):
|
|
402
356
|
"""A Javascript event."""
|
|
403
357
|
|
|
404
358
|
target: Target = Target()
|
|
@@ -406,11 +360,7 @@ class FrontendEvent:
|
|
|
406
360
|
value: Any = None
|
|
407
361
|
|
|
408
362
|
|
|
409
|
-
|
|
410
|
-
init=True,
|
|
411
|
-
frozen=True,
|
|
412
|
-
)
|
|
413
|
-
class FileUpload:
|
|
363
|
+
class FileUpload(Base):
|
|
414
364
|
"""Class to represent a file upload."""
|
|
415
365
|
|
|
416
366
|
upload_id: Optional[str] = None
|
|
@@ -445,15 +395,15 @@ class FileUpload:
|
|
|
445
395
|
upload_id = self.upload_id or DEFAULT_UPLOAD_ID
|
|
446
396
|
spec_args = [
|
|
447
397
|
(
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
398
|
+
ImmutableVar.create_safe("files"),
|
|
399
|
+
ImmutableVar(
|
|
400
|
+
_var_name="filesById",
|
|
451
401
|
_var_type=Dict[str, Any],
|
|
452
402
|
_var_data=VarData.merge(upload_files_context_var_data),
|
|
453
403
|
).to(ObjectVar)[LiteralVar.create(upload_id)],
|
|
454
404
|
),
|
|
455
405
|
(
|
|
456
|
-
|
|
406
|
+
ImmutableVar.create_safe("upload_id"),
|
|
457
407
|
LiteralVar.create(upload_id),
|
|
458
408
|
),
|
|
459
409
|
]
|
|
@@ -473,7 +423,7 @@ class FileUpload:
|
|
|
473
423
|
) # type: ignore
|
|
474
424
|
else:
|
|
475
425
|
raise ValueError(f"{on_upload_progress} is not a valid event handler.")
|
|
476
|
-
if isinstance(events,
|
|
426
|
+
if isinstance(events, ImmutableVar):
|
|
477
427
|
raise ValueError(f"{on_upload_progress} cannot return a var {events}.")
|
|
478
428
|
on_upload_progress_chain = EventChain(
|
|
479
429
|
events=events,
|
|
@@ -482,7 +432,7 @@ class FileUpload:
|
|
|
482
432
|
formatted_chain = str(format.format_prop(on_upload_progress_chain))
|
|
483
433
|
spec_args.append(
|
|
484
434
|
(
|
|
485
|
-
|
|
435
|
+
ImmutableVar.create_safe("on_upload_progress"),
|
|
486
436
|
FunctionStringVar(
|
|
487
437
|
formatted_chain.strip("{}"),
|
|
488
438
|
).to(FunctionVar, EventChain),
|
|
@@ -522,7 +472,7 @@ def server_side(name: str, sig: inspect.Signature, **kwargs) -> EventSpec:
|
|
|
522
472
|
handler=EventHandler(fn=fn),
|
|
523
473
|
args=tuple(
|
|
524
474
|
(
|
|
525
|
-
|
|
475
|
+
ImmutableVar.create_safe(k),
|
|
526
476
|
LiteralVar.create(v),
|
|
527
477
|
)
|
|
528
478
|
for k, v in kwargs.items()
|
|
@@ -728,9 +678,9 @@ def set_clipboard(content: str) -> EventSpec:
|
|
|
728
678
|
|
|
729
679
|
|
|
730
680
|
def download(
|
|
731
|
-
url: str |
|
|
732
|
-
filename: Optional[str |
|
|
733
|
-
data: str | bytes |
|
|
681
|
+
url: str | ImmutableVar | None = None,
|
|
682
|
+
filename: Optional[str | ImmutableVar] = None,
|
|
683
|
+
data: str | bytes | ImmutableVar | None = None,
|
|
734
684
|
) -> EventSpec:
|
|
735
685
|
"""Download the file at a given path or with the specified data.
|
|
736
686
|
|
|
@@ -766,7 +716,7 @@ def download(
|
|
|
766
716
|
if isinstance(data, str):
|
|
767
717
|
# Caller provided a plain text string to download.
|
|
768
718
|
url = "data:text/plain," + urllib.parse.quote(data)
|
|
769
|
-
elif isinstance(data,
|
|
719
|
+
elif isinstance(data, ImmutableVar):
|
|
770
720
|
# Need to check on the frontend if the Var already looks like a data: URI.
|
|
771
721
|
|
|
772
722
|
is_data_url = (data.js_type() == "string") & (
|
|
@@ -923,13 +873,15 @@ def parse_args_spec(arg_spec: ArgsSpec):
|
|
|
923
873
|
annotations = get_type_hints(arg_spec)
|
|
924
874
|
return arg_spec(
|
|
925
875
|
*[
|
|
926
|
-
|
|
876
|
+
ImmutableVar(f"_{l_arg}").to(
|
|
877
|
+
ObjectVar, annotations.get(l_arg, FrontendEvent)
|
|
878
|
+
)
|
|
927
879
|
for l_arg in spec.args
|
|
928
880
|
]
|
|
929
881
|
)
|
|
930
882
|
|
|
931
883
|
|
|
932
|
-
def call_event_fn(fn: Callable, arg_spec: ArgsSpec) -> list[EventSpec] |
|
|
884
|
+
def call_event_fn(fn: Callable, arg_spec: ArgsSpec) -> list[EventSpec] | ImmutableVar:
|
|
933
885
|
"""Call a function to a list of event specs.
|
|
934
886
|
|
|
935
887
|
The function should return a single EventSpec, a list of EventSpecs, or a
|
|
@@ -970,7 +922,7 @@ def call_event_fn(fn: Callable, arg_spec: ArgsSpec) -> list[EventSpec] | Var:
|
|
|
970
922
|
out = fn(*parsed_args)
|
|
971
923
|
|
|
972
924
|
# If the function returns a Var, assume it's an EventChain and render it directly.
|
|
973
|
-
if isinstance(out,
|
|
925
|
+
if isinstance(out, ImmutableVar):
|
|
974
926
|
return out
|
|
975
927
|
|
|
976
928
|
# Convert the output to a list.
|
|
@@ -999,7 +951,7 @@ def call_event_fn(fn: Callable, arg_spec: ArgsSpec) -> list[EventSpec] | Var:
|
|
|
999
951
|
|
|
1000
952
|
def get_handler_args(
|
|
1001
953
|
event_spec: EventSpec,
|
|
1002
|
-
) -> tuple[tuple[
|
|
954
|
+
) -> tuple[tuple[ImmutableVar, ImmutableVar], ...]:
|
|
1003
955
|
"""Get the handler args for the given event spec.
|
|
1004
956
|
|
|
1005
957
|
Args:
|
|
@@ -1050,7 +1002,7 @@ def fix_events(
|
|
|
1050
1002
|
e = e()
|
|
1051
1003
|
assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}."
|
|
1052
1004
|
name = format.format_event_handler(e.handler)
|
|
1053
|
-
payload = {k.
|
|
1005
|
+
payload = {k._var_name: v._decode() for k, v in e.args} # type: ignore
|
|
1054
1006
|
|
|
1055
1007
|
# Filter router_data to reduce payload size
|
|
1056
1008
|
event_router_data = {
|