reflex 0.3.2__py3-none-any.whl → 0.3.3a1__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/web/pages/custom_component.js.jinja2 +20 -3
- reflex/.templates/web/next.config.js +1 -0
- reflex/.templates/web/utils/helpers/range.js +43 -0
- reflex/.templates/web/utils/state.js +10 -6
- reflex/__init__.py +312 -40
- reflex/__init__.pyi +477 -0
- reflex/compiler/compiler.py +3 -0
- reflex/components/__init__.py +138 -138
- reflex/components/component.py +29 -22
- reflex/components/datadisplay/__init__.py +3 -1
- reflex/components/datadisplay/code.py +388 -14
- reflex/components/datadisplay/code.pyi +1146 -10
- reflex/components/forms/button.py +3 -0
- reflex/components/forms/checkbox.py +3 -0
- reflex/components/forms/form.py +90 -27
- reflex/components/forms/input.py +3 -0
- reflex/components/forms/numberinput.py +3 -0
- reflex/components/forms/pininput.py +77 -21
- reflex/components/forms/radio.py +3 -0
- reflex/components/forms/rangeslider.py +3 -0
- reflex/components/forms/select.py +3 -0
- reflex/components/forms/slider.py +3 -0
- reflex/components/forms/switch.py +3 -0
- reflex/components/forms/textarea.py +3 -0
- reflex/components/libs/chakra.py +2 -0
- reflex/components/libs/chakra.pyi +323 -24
- reflex/components/tags/tag.py +3 -2
- reflex/components/typography/markdown.py +10 -0
- reflex/constants/installer.py +4 -4
- reflex/event.py +4 -0
- reflex/page.py +3 -4
- reflex/page.pyi +17 -0
- reflex/reflex.py +3 -0
- reflex/state.py +31 -12
- reflex/testing.py +1 -1
- reflex/utils/build.py +24 -19
- reflex/utils/console.py +5 -1
- reflex/utils/format.py +26 -9
- reflex/utils/prerequisites.py +27 -28
- reflex/utils/processes.py +5 -4
- reflex/vars.py +80 -12
- reflex/vars.pyi +7 -0
- {reflex-0.3.2.dist-info → reflex-0.3.3a1.dist-info}/METADATA +3 -2
- {reflex-0.3.2.dist-info → reflex-0.3.3a1.dist-info}/RECORD +47 -45
- reflex/.templates/web/styles/code/prism.js +0 -1015
- {reflex-0.3.2.dist-info → reflex-0.3.3a1.dist-info}/LICENSE +0 -0
- {reflex-0.3.2.dist-info → reflex-0.3.3a1.dist-info}/WHEEL +0 -0
- {reflex-0.3.2.dist-info → reflex-0.3.3a1.dist-info}/entry_points.txt +0 -0
|
@@ -56,6 +56,9 @@ class Button(ChakraComponent):
|
|
|
56
56
|
# Components that are not allowed as children.
|
|
57
57
|
invalid_children: List[str] = ["Button", "MenuButton"]
|
|
58
58
|
|
|
59
|
+
# The name of the form field
|
|
60
|
+
name: Var[str]
|
|
61
|
+
|
|
59
62
|
|
|
60
63
|
class ButtonGroup(ChakraComponent):
|
|
61
64
|
"""A group of buttons."""
|
|
@@ -50,6 +50,9 @@ class Checkbox(ChakraComponent):
|
|
|
50
50
|
# The name of the input field in a checkbox (Useful for form submission).
|
|
51
51
|
name: Var[str]
|
|
52
52
|
|
|
53
|
+
# The value of the input field when checked (use is_checked prop for a bool)
|
|
54
|
+
value: Var[str] = Var.create(True) # type: ignore
|
|
55
|
+
|
|
53
56
|
# The spacing between the checkbox and its label text (0.5rem)
|
|
54
57
|
spacing: Var[str]
|
|
55
58
|
|
reflex/components/forms/form.py
CHANGED
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
"""Form components."""
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
|
-
from typing import Any,
|
|
4
|
+
from typing import Any, Dict
|
|
5
|
+
|
|
6
|
+
from jinja2 import Environment
|
|
5
7
|
|
|
6
8
|
from reflex.components.component import Component
|
|
7
9
|
from reflex.components.libs.chakra import ChakraComponent
|
|
10
|
+
from reflex.components.tags import Tag
|
|
8
11
|
from reflex.constants import EventTriggers
|
|
9
|
-
from reflex.event import EventChain
|
|
10
|
-
from reflex.
|
|
12
|
+
from reflex.event import EventChain
|
|
13
|
+
from reflex.utils import imports
|
|
14
|
+
from reflex.utils.format import format_event_chain, to_camel_case
|
|
15
|
+
from reflex.utils.serializers import serialize
|
|
16
|
+
from reflex.vars import BaseVar, Var, get_unique_variable_name
|
|
17
|
+
|
|
18
|
+
FORM_DATA = Var.create("form_data")
|
|
19
|
+
HANDLE_SUBMIT_JS_JINJA2 = Environment().from_string(
|
|
20
|
+
"""
|
|
21
|
+
const handleSubmit{{ handle_submit_unique_name }} = useCallback((ev) => {
|
|
22
|
+
const $form = ev.target
|
|
23
|
+
ev.preventDefault()
|
|
24
|
+
const {{ form_data }} = {...Object.fromEntries(new FormData($form).entries()), ...{{ field_ref_mapping }}}
|
|
25
|
+
|
|
26
|
+
{{ on_submit_event_chain }}
|
|
27
|
+
|
|
28
|
+
if ({{ reset_on_submit }}) {
|
|
29
|
+
$form.reset()
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
"""
|
|
33
|
+
)
|
|
11
34
|
|
|
12
35
|
|
|
13
36
|
class Form(ChakraComponent):
|
|
@@ -18,35 +41,68 @@ class Form(ChakraComponent):
|
|
|
18
41
|
# What the form renders to.
|
|
19
42
|
as_: Var[str] = "form" # type: ignore
|
|
20
43
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
event_trigger: str,
|
|
24
|
-
value: Var
|
|
25
|
-
| EventHandler
|
|
26
|
-
| EventSpec
|
|
27
|
-
| List[EventHandler | EventSpec]
|
|
28
|
-
| Callable[..., Any],
|
|
29
|
-
) -> EventChain | Var:
|
|
30
|
-
"""Override the event chain creation to preventDefault for on_submit.
|
|
44
|
+
# If true, the form will be cleared after submit.
|
|
45
|
+
reset_on_submit: Var[bool] = False # type: ignore
|
|
31
46
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
value: The value of the event trigger.
|
|
47
|
+
# The name used to make this form's submit handler function unique
|
|
48
|
+
handle_submit_unique_name: Var[str]
|
|
35
49
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"""
|
|
39
|
-
chain = super()._create_event_chain(event_trigger, value)
|
|
40
|
-
if event_trigger == EventTriggers.ON_SUBMIT and isinstance(chain, EventChain):
|
|
41
|
-
return chain.prevent_default
|
|
42
|
-
return chain
|
|
50
|
+
@classmethod
|
|
51
|
+
def create(cls, *children, **props) -> Component:
|
|
52
|
+
"""Create a form component.
|
|
43
53
|
|
|
44
|
-
|
|
45
|
-
|
|
54
|
+
Args:
|
|
55
|
+
*children: The children of the form.
|
|
56
|
+
**props: The properties of the form.
|
|
46
57
|
|
|
47
58
|
Returns:
|
|
48
|
-
|
|
59
|
+
The form component.
|
|
49
60
|
"""
|
|
61
|
+
if "handle_submit_unique_name" not in props:
|
|
62
|
+
props["handle_submit_unique_name"] = get_unique_variable_name()
|
|
63
|
+
return super().create(*children, **props)
|
|
64
|
+
|
|
65
|
+
def _get_imports(self) -> imports.ImportDict:
|
|
66
|
+
return imports.merge_imports(
|
|
67
|
+
super()._get_imports(),
|
|
68
|
+
{"react": {imports.ImportVar(tag="useCallback")}},
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def _get_hooks(self) -> str | None:
|
|
72
|
+
if EventTriggers.ON_SUBMIT not in self.event_triggers:
|
|
73
|
+
return
|
|
74
|
+
return HANDLE_SUBMIT_JS_JINJA2.render(
|
|
75
|
+
handle_submit_unique_name=self.handle_submit_unique_name,
|
|
76
|
+
form_data=FORM_DATA,
|
|
77
|
+
field_ref_mapping=serialize(self._get_form_refs()),
|
|
78
|
+
on_submit_event_chain=format_event_chain(
|
|
79
|
+
self.event_triggers[EventTriggers.ON_SUBMIT]
|
|
80
|
+
),
|
|
81
|
+
reset_on_submit=self.reset_on_submit,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def _render(self) -> Tag:
|
|
85
|
+
render_tag = (
|
|
86
|
+
super()
|
|
87
|
+
._render()
|
|
88
|
+
.remove_props(
|
|
89
|
+
"reset_on_submit",
|
|
90
|
+
"handle_submit_unique_name",
|
|
91
|
+
to_camel_case(EventTriggers.ON_SUBMIT),
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
if EventTriggers.ON_SUBMIT in self.event_triggers:
|
|
95
|
+
render_tag.add_props(
|
|
96
|
+
**{
|
|
97
|
+
EventTriggers.ON_SUBMIT: BaseVar(
|
|
98
|
+
_var_name=f"handleSubmit{self.handle_submit_unique_name}",
|
|
99
|
+
_var_type=EventChain,
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
return render_tag
|
|
104
|
+
|
|
105
|
+
def _get_form_refs(self) -> Dict[str, Any]:
|
|
50
106
|
# Send all the input refs to the handler.
|
|
51
107
|
form_refs = {}
|
|
52
108
|
for ref in self.get_refs():
|
|
@@ -60,10 +116,17 @@ class Form(ChakraComponent):
|
|
|
60
116
|
form_refs[ref[4:]] = Var.create(
|
|
61
117
|
f"getRefValue({ref})", _var_is_local=False
|
|
62
118
|
)
|
|
119
|
+
return form_refs
|
|
63
120
|
|
|
121
|
+
def get_event_triggers(self) -> Dict[str, Any]:
|
|
122
|
+
"""Get the event triggers that pass the component's value to the handler.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
A dict mapping the event trigger to the var that is passed to the handler.
|
|
126
|
+
"""
|
|
64
127
|
return {
|
|
65
128
|
**super().get_event_triggers(),
|
|
66
|
-
EventTriggers.ON_SUBMIT: lambda e0: [
|
|
129
|
+
EventTriggers.ON_SUBMIT: lambda e0: [FORM_DATA],
|
|
67
130
|
}
|
|
68
131
|
|
|
69
132
|
|
reflex/components/forms/input.py
CHANGED
|
@@ -68,6 +68,9 @@ class NumberInput(ChakraComponent):
|
|
|
68
68
|
# "outline" | "filled" | "flushed" | "unstyled"
|
|
69
69
|
variant: Var[LiteralInputVariant]
|
|
70
70
|
|
|
71
|
+
# The name of the form field
|
|
72
|
+
name: Var[str]
|
|
73
|
+
|
|
71
74
|
def get_event_triggers(self) -> Dict[str, Any]:
|
|
72
75
|
"""Get the event triggers that pass the component's value to the handler.
|
|
73
76
|
|
|
@@ -4,10 +4,11 @@ from __future__ import annotations
|
|
|
4
4
|
from typing import Any, Optional, Union
|
|
5
5
|
|
|
6
6
|
from reflex.components.component import Component
|
|
7
|
-
from reflex.components.layout import Foreach
|
|
8
7
|
from reflex.components.libs.chakra import ChakraComponent, LiteralInputVariant
|
|
8
|
+
from reflex.components.tags.tag import Tag
|
|
9
9
|
from reflex.constants import EventTriggers
|
|
10
10
|
from reflex.utils import format
|
|
11
|
+
from reflex.utils.imports import ImportDict, merge_imports
|
|
11
12
|
from reflex.vars import Var
|
|
12
13
|
|
|
13
14
|
|
|
@@ -58,6 +59,20 @@ class PinInput(ChakraComponent):
|
|
|
58
59
|
# "outline" | "flushed" | "filled" | "unstyled"
|
|
59
60
|
variant: Var[LiteralInputVariant]
|
|
60
61
|
|
|
62
|
+
# The name of the form field
|
|
63
|
+
name: Var[str]
|
|
64
|
+
|
|
65
|
+
def _get_imports(self) -> ImportDict:
|
|
66
|
+
"""Include PinInputField explicitly because it may not be a child component at compile time.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
The merged import dict.
|
|
70
|
+
"""
|
|
71
|
+
return merge_imports(
|
|
72
|
+
super()._get_imports(),
|
|
73
|
+
PinInputField().get_imports(), # type: ignore
|
|
74
|
+
)
|
|
75
|
+
|
|
61
76
|
def get_event_triggers(self) -> dict[str, Union[Var, Any]]:
|
|
62
77
|
"""Get the event triggers that pass the component's value to the handler.
|
|
63
78
|
|
|
@@ -70,13 +85,24 @@ class PinInput(ChakraComponent):
|
|
|
70
85
|
EventTriggers.ON_COMPLETE: lambda e0: [e0],
|
|
71
86
|
}
|
|
72
87
|
|
|
73
|
-
def get_ref(self):
|
|
74
|
-
"""
|
|
88
|
+
def get_ref(self) -> str | None:
|
|
89
|
+
"""Override ref handling to handle array refs.
|
|
90
|
+
|
|
91
|
+
PinInputFields may be created dynamically, so it's not possible
|
|
92
|
+
to compute their ref at compile time, so we return a cheating
|
|
93
|
+
guess if the id is specified.
|
|
94
|
+
|
|
95
|
+
The `ref` for this outer component will always be stripped off, so what
|
|
96
|
+
is returned here only matters for form ref collection purposes.
|
|
75
97
|
|
|
76
98
|
Returns:
|
|
77
99
|
None.
|
|
78
100
|
"""
|
|
79
|
-
|
|
101
|
+
if any(isinstance(c, PinInputField) for c in self.children):
|
|
102
|
+
return None
|
|
103
|
+
if self.id:
|
|
104
|
+
return format.format_array_ref(self.id, idx=self.length)
|
|
105
|
+
return super().get_ref()
|
|
80
106
|
|
|
81
107
|
def _get_ref_hook(self) -> Optional[str]:
|
|
82
108
|
"""Override the base _get_ref_hook to handle array refs.
|
|
@@ -86,10 +112,22 @@ class PinInput(ChakraComponent):
|
|
|
86
112
|
"""
|
|
87
113
|
if self.id:
|
|
88
114
|
ref = format.format_array_ref(self.id, None)
|
|
115
|
+
refs_declaration = Var.range(self.length).foreach(
|
|
116
|
+
lambda: Var.create_safe("useRef(null)", _var_is_string=False),
|
|
117
|
+
)
|
|
118
|
+
refs_declaration._var_is_local = True
|
|
89
119
|
if ref:
|
|
90
|
-
return f"const {ref} =
|
|
120
|
+
return f"const {ref} = {refs_declaration}"
|
|
91
121
|
return super()._get_ref_hook()
|
|
92
122
|
|
|
123
|
+
def _render(self) -> Tag:
|
|
124
|
+
"""Override the base _render to remove the fake get_ref.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
The rendered component.
|
|
128
|
+
"""
|
|
129
|
+
return super()._render().remove_props("ref")
|
|
130
|
+
|
|
93
131
|
@classmethod
|
|
94
132
|
def create(cls, *children, **props) -> Component:
|
|
95
133
|
"""Create a pin input component.
|
|
@@ -104,22 +142,17 @@ class PinInput(ChakraComponent):
|
|
|
104
142
|
Returns:
|
|
105
143
|
The pin input component.
|
|
106
144
|
"""
|
|
107
|
-
if
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
),
|
|
119
|
-
)
|
|
120
|
-
]
|
|
121
|
-
else:
|
|
122
|
-
children = [PinInputField()] * length
|
|
145
|
+
if children:
|
|
146
|
+
props.pop("length", None)
|
|
147
|
+
elif "length" in props:
|
|
148
|
+
field_props = {}
|
|
149
|
+
if "id" in props:
|
|
150
|
+
field_props["id"] = props["id"]
|
|
151
|
+
if "name" in props:
|
|
152
|
+
field_props["name"] = props["name"]
|
|
153
|
+
children = [
|
|
154
|
+
PinInputField.for_length(props["length"], **field_props),
|
|
155
|
+
]
|
|
123
156
|
return super().create(*children, **props)
|
|
124
157
|
|
|
125
158
|
|
|
@@ -132,6 +165,29 @@ class PinInputField(ChakraComponent):
|
|
|
132
165
|
# Default to None because it is assigned by PinInput when created.
|
|
133
166
|
index: Optional[Var[int]] = None
|
|
134
167
|
|
|
168
|
+
# The name of the form field
|
|
169
|
+
name: Var[str]
|
|
170
|
+
|
|
171
|
+
@classmethod
|
|
172
|
+
def for_length(cls, length: Var | int, **props) -> Var:
|
|
173
|
+
"""Create a PinInputField for a PinInput with a given length.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
length: The length of the PinInput.
|
|
177
|
+
props: The props of each PinInputField (name will become indexed).
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
The PinInputField.
|
|
181
|
+
"""
|
|
182
|
+
name = props.get("name")
|
|
183
|
+
|
|
184
|
+
def _create(i):
|
|
185
|
+
if name is not None:
|
|
186
|
+
props["name"] = f"{name}-{i}"
|
|
187
|
+
return PinInputField.create(**props, index=i, key=i)
|
|
188
|
+
|
|
189
|
+
return Var.range(length).foreach(_create) # type: ignore
|
|
190
|
+
|
|
135
191
|
def _get_ref_hook(self) -> Optional[str]:
|
|
136
192
|
return None
|
|
137
193
|
|
reflex/components/forms/radio.py
CHANGED
|
@@ -23,6 +23,9 @@ class RadioGroup(ChakraComponent):
|
|
|
23
23
|
# The default value.
|
|
24
24
|
default_value: Var[Any]
|
|
25
25
|
|
|
26
|
+
# The name of the form field
|
|
27
|
+
name: Var[str]
|
|
28
|
+
|
|
26
29
|
def get_event_triggers(self) -> Dict[str, Union[Var, Any]]:
|
|
27
30
|
"""Get the event triggers that pass the component's value to the handler.
|
|
28
31
|
|
|
@@ -45,6 +45,9 @@ class RangeSlider(ChakraComponent):
|
|
|
45
45
|
# The minimum distance between slider thumbs. Useful for preventing the thumbs from being too close together.
|
|
46
46
|
min_steps_between_thumbs: Var[int]
|
|
47
47
|
|
|
48
|
+
# The name of the form field
|
|
49
|
+
name: Var[str]
|
|
50
|
+
|
|
48
51
|
def get_event_triggers(self) -> dict[str, Union[Var, Any]]:
|
|
49
52
|
"""Get the event triggers that pass the component's value to the handler.
|
|
50
53
|
|
|
@@ -46,6 +46,9 @@ class Select(ChakraComponent):
|
|
|
46
46
|
# The size of the select.
|
|
47
47
|
size: Var[str]
|
|
48
48
|
|
|
49
|
+
# The name of the form field
|
|
50
|
+
name: Var[str]
|
|
51
|
+
|
|
49
52
|
def get_event_triggers(self) -> Dict[str, Union[Var, Any]]:
|
|
50
53
|
"""Get the event triggers that pass the component's value to the handler.
|
|
51
54
|
|
|
@@ -66,6 +66,9 @@ class Slider(ChakraComponent):
|
|
|
66
66
|
# Maximum width of the slider.
|
|
67
67
|
max_w: Var[str]
|
|
68
68
|
|
|
69
|
+
# The name of the form field
|
|
70
|
+
name: Var[str]
|
|
71
|
+
|
|
69
72
|
def get_event_triggers(self) -> dict[str, Union[Var, Any]]:
|
|
70
73
|
"""Get the event triggers that pass the component's value to the handler.
|
|
71
74
|
|
|
@@ -34,6 +34,9 @@ class Switch(ChakraComponent):
|
|
|
34
34
|
# The name of the input field in a switch (Useful for form submission).
|
|
35
35
|
name: Var[str]
|
|
36
36
|
|
|
37
|
+
# The value of the input field when checked (use is_checked prop for a bool)
|
|
38
|
+
value: Var[str] = Var.create(True) # type: ignore
|
|
39
|
+
|
|
37
40
|
# The spacing between the switch and its label text (0.5rem)
|
|
38
41
|
spacing: Var[str]
|
|
39
42
|
|
|
@@ -45,6 +45,9 @@ class TextArea(ChakraComponent):
|
|
|
45
45
|
# "outline" | "filled" | "flushed" | "unstyled"
|
|
46
46
|
variant: Var[LiteralInputVariant]
|
|
47
47
|
|
|
48
|
+
# The name of the form field
|
|
49
|
+
name: Var[str]
|
|
50
|
+
|
|
48
51
|
def get_event_triggers(self) -> dict[str, Union[Var, Any]]:
|
|
49
52
|
"""Get the event triggers that pass the component's value to the handler.
|
|
50
53
|
|
reflex/components/libs/chakra.py
CHANGED
|
@@ -122,6 +122,8 @@ LiteralColorScheme = Literal[
|
|
|
122
122
|
LiteralVariant = Literal["solid", "subtle", "outline"]
|
|
123
123
|
LiteralDividerVariant = Literal["solid", "dashed"]
|
|
124
124
|
LiteralTheme = Literal["light", "dark"]
|
|
125
|
+
|
|
126
|
+
|
|
125
127
|
LiteralTagColorScheme = Literal[
|
|
126
128
|
"gray",
|
|
127
129
|
"red",
|