reflex 0.7.12__py3-none-any.whl → 0.7.13a1__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/app/rxconfig.py.jinja2 +1 -0
- reflex/.templates/web/postcss.config.js +0 -1
- reflex/.templates/web/utils/state.js +1 -1
- reflex/__init__.py +1 -0
- reflex/__init__.pyi +1 -0
- reflex/app.py +87 -27
- reflex/compiler/compiler.py +11 -62
- reflex/compiler/templates.py +12 -3
- reflex/compiler/utils.py +20 -4
- reflex/components/component.py +366 -88
- reflex/components/datadisplay/code.py +1 -1
- reflex/components/datadisplay/shiki_code_block.py +97 -86
- reflex/components/datadisplay/shiki_code_block.pyi +4 -2
- reflex/components/el/elements/forms.py +1 -1
- reflex/components/lucide/icon.py +2 -1
- reflex/components/lucide/icon.pyi +1 -0
- reflex/components/plotly/plotly.py +2 -2
- reflex/components/plotly/plotly.pyi +2 -3
- reflex/components/radix/themes/base.py +4 -11
- reflex/components/radix/themes/components/icon_button.py +2 -2
- reflex/components/radix/themes/components/text_field.py +3 -0
- reflex/components/radix/themes/components/text_field.pyi +2 -0
- reflex/components/radix/themes/layout/list.py +1 -1
- reflex/components/tags/iter_tag.py +3 -5
- reflex/config.py +54 -7
- reflex/constants/__init__.py +0 -2
- reflex/event.py +154 -93
- reflex/plugins/__init__.py +7 -0
- reflex/plugins/base.py +101 -0
- reflex/plugins/tailwind_v3.py +255 -0
- reflex/plugins/tailwind_v4.py +257 -0
- reflex/state.py +24 -3
- reflex/utils/build.py +1 -1
- reflex/utils/console.py +1 -1
- reflex/utils/exec.py +18 -0
- reflex/utils/path_ops.py +26 -6
- reflex/utils/prerequisites.py +21 -90
- reflex/utils/pyi_generator.py +12 -2
- reflex/utils/types.py +15 -1
- reflex/vars/base.py +59 -4
- reflex/vars/object.py +8 -0
- {reflex-0.7.12.dist-info → reflex-0.7.13a1.dist-info}/METADATA +2 -2
- {reflex-0.7.12.dist-info → reflex-0.7.13a1.dist-info}/RECORD +47 -46
- scripts/hatch_build.py +17 -0
- reflex/.templates/jinja/web/tailwind.config.js.jinja2 +0 -66
- reflex/.templates/web/styles/tailwind.css +0 -6
- reflex/constants/style.py +0 -16
- {reflex-0.7.12.dist-info → reflex-0.7.13a1.dist-info}/WHEEL +0 -0
- {reflex-0.7.12.dist-info → reflex-0.7.13a1.dist-info}/entry_points.txt +0 -0
- {reflex-0.7.12.dist-info → reflex-0.7.13a1.dist-info}/licenses/LICENSE +0 -0
reflex/components/component.py
CHANGED
|
@@ -7,19 +7,32 @@ import copy
|
|
|
7
7
|
import dataclasses
|
|
8
8
|
import functools
|
|
9
9
|
import inspect
|
|
10
|
+
import sys
|
|
10
11
|
import typing
|
|
11
|
-
from abc import ABC, abstractmethod
|
|
12
|
+
from abc import ABC, ABCMeta, abstractmethod
|
|
12
13
|
from collections.abc import Callable, Iterator, Mapping, Sequence
|
|
14
|
+
from dataclasses import _MISSING_TYPE, MISSING
|
|
13
15
|
from functools import wraps
|
|
14
16
|
from hashlib import md5
|
|
15
17
|
from types import SimpleNamespace
|
|
16
|
-
from typing import
|
|
18
|
+
from typing import (
|
|
19
|
+
TYPE_CHECKING,
|
|
20
|
+
Annotated,
|
|
21
|
+
Any,
|
|
22
|
+
ClassVar,
|
|
23
|
+
ForwardRef,
|
|
24
|
+
Generic,
|
|
25
|
+
TypeVar,
|
|
26
|
+
_eval_type, # pyright: ignore [reportAttributeAccessIssue]
|
|
27
|
+
cast,
|
|
28
|
+
get_args,
|
|
29
|
+
get_origin,
|
|
30
|
+
)
|
|
17
31
|
|
|
18
|
-
import pydantic.v1
|
|
19
32
|
from rich.markup import escape
|
|
33
|
+
from typing_extensions import dataclass_transform
|
|
20
34
|
|
|
21
35
|
import reflex.state
|
|
22
|
-
from reflex.base import Base
|
|
23
36
|
from reflex.compiler.templates import STATEFUL_COMPONENT
|
|
24
37
|
from reflex.components.core.breakpoints import Breakpoints
|
|
25
38
|
from reflex.components.dynamic import load_dynamic_serializer
|
|
@@ -62,26 +75,311 @@ from reflex.vars.object import ObjectVar
|
|
|
62
75
|
from reflex.vars.sequence import LiteralArrayVar, LiteralStringVar, StringVar
|
|
63
76
|
|
|
64
77
|
|
|
65
|
-
|
|
78
|
+
def resolve_annotations(
|
|
79
|
+
raw_annotations: Mapping[str, type[Any]], module_name: str | None
|
|
80
|
+
) -> dict[str, type[Any]]:
|
|
81
|
+
"""Partially taken from typing.get_type_hints.
|
|
82
|
+
|
|
83
|
+
Resolve string or ForwardRef annotations into type objects if possible.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
raw_annotations: The raw annotations to resolve.
|
|
87
|
+
module_name: The name of the module.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
The resolved annotations.
|
|
91
|
+
"""
|
|
92
|
+
module = sys.modules.get(module_name, None) if module_name is not None else None
|
|
93
|
+
|
|
94
|
+
base_globals: dict[str, Any] | None = (
|
|
95
|
+
module.__dict__ if module is not None else None
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
annotations = {}
|
|
99
|
+
for name, value in raw_annotations.items():
|
|
100
|
+
if isinstance(value, str):
|
|
101
|
+
if sys.version_info == (3, 10, 0):
|
|
102
|
+
value = ForwardRef(value, is_argument=False)
|
|
103
|
+
else:
|
|
104
|
+
value = ForwardRef(value, is_argument=False, is_class=True)
|
|
105
|
+
try:
|
|
106
|
+
if sys.version_info >= (3, 13):
|
|
107
|
+
value = _eval_type(value, base_globals, None, type_params=())
|
|
108
|
+
else:
|
|
109
|
+
value = _eval_type(value, base_globals, None)
|
|
110
|
+
except NameError:
|
|
111
|
+
# this is ok, it can be fixed with update_forward_refs
|
|
112
|
+
pass
|
|
113
|
+
annotations[name] = value
|
|
114
|
+
return annotations
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
FIELD_TYPE = TypeVar("FIELD_TYPE")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
class ComponentField(Generic[FIELD_TYPE]):
|
|
121
|
+
"""A field for a component."""
|
|
122
|
+
|
|
123
|
+
def __init__(
|
|
124
|
+
self,
|
|
125
|
+
default: FIELD_TYPE | _MISSING_TYPE = MISSING,
|
|
126
|
+
default_factory: Callable[[], FIELD_TYPE] | None = None,
|
|
127
|
+
is_javascript: bool | None = None,
|
|
128
|
+
annotated_type: type[Any] | _MISSING_TYPE = MISSING,
|
|
129
|
+
) -> None:
|
|
130
|
+
"""Initialize the field.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
default: The default value for the field.
|
|
134
|
+
default_factory: The default factory for the field.
|
|
135
|
+
is_javascript: Whether the field is a javascript property.
|
|
136
|
+
annotated_type: The annotated type for the field.
|
|
137
|
+
"""
|
|
138
|
+
self.default = default
|
|
139
|
+
self.default_factory = default_factory
|
|
140
|
+
self.is_javascript = is_javascript
|
|
141
|
+
self.outer_type_ = self.annotated_type = annotated_type
|
|
142
|
+
type_origin = get_origin(annotated_type) or annotated_type
|
|
143
|
+
if type_origin is Annotated:
|
|
144
|
+
type_origin = annotated_type.__origin__ # pyright: ignore [reportAttributeAccessIssue]
|
|
145
|
+
self.type_ = self.type_origin = type_origin
|
|
146
|
+
|
|
147
|
+
def default_value(self) -> FIELD_TYPE:
|
|
148
|
+
"""Get the default value for the field.
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
The default value for the field.
|
|
152
|
+
|
|
153
|
+
Raises:
|
|
154
|
+
ValueError: If no default value or factory is provided.
|
|
155
|
+
"""
|
|
156
|
+
if self.default is not MISSING:
|
|
157
|
+
return self.default
|
|
158
|
+
if self.default_factory is not None:
|
|
159
|
+
return self.default_factory()
|
|
160
|
+
raise ValueError("No default value or factory provided.")
|
|
161
|
+
|
|
162
|
+
def __repr__(self) -> str:
|
|
163
|
+
"""Represent the field in a readable format.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
The string representation of the field.
|
|
167
|
+
"""
|
|
168
|
+
annotated_type_str = (
|
|
169
|
+
f", annotated_type={self.annotated_type!r}"
|
|
170
|
+
if self.annotated_type is not MISSING
|
|
171
|
+
else ""
|
|
172
|
+
)
|
|
173
|
+
if self.default is not MISSING:
|
|
174
|
+
return f"ComponentField(default={self.default!r}, is_javascript={self.is_javascript!r}{annotated_type_str})"
|
|
175
|
+
return f"ComponentField(default_factory={self.default_factory!r}, is_javascript={self.is_javascript!r}{annotated_type_str})"
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def field(
|
|
179
|
+
default: FIELD_TYPE | _MISSING_TYPE = MISSING,
|
|
180
|
+
default_factory: Callable[[], FIELD_TYPE] | None = None,
|
|
181
|
+
is_javascript_property: bool | None = None,
|
|
182
|
+
) -> FIELD_TYPE:
|
|
183
|
+
"""Create a field for a component.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
default: The default value for the field.
|
|
187
|
+
default_factory: The default factory for the field.
|
|
188
|
+
is_javascript_property: Whether the field is a javascript property.
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
The field for the component.
|
|
192
|
+
|
|
193
|
+
Raises:
|
|
194
|
+
ValueError: If both default and default_factory are specified.
|
|
195
|
+
"""
|
|
196
|
+
if default is not MISSING and default_factory is not None:
|
|
197
|
+
raise ValueError("cannot specify both default and default_factory")
|
|
198
|
+
return ComponentField( # pyright: ignore [reportReturnType]
|
|
199
|
+
default=default,
|
|
200
|
+
default_factory=default_factory,
|
|
201
|
+
is_javascript=is_javascript_property,
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
@dataclass_transform(kw_only_default=True, field_specifiers=(field,))
|
|
206
|
+
class BaseComponentMeta(ABCMeta):
|
|
207
|
+
"""Meta class for BaseComponent."""
|
|
208
|
+
|
|
209
|
+
if TYPE_CHECKING:
|
|
210
|
+
_inherited_fields: Mapping[str, ComponentField]
|
|
211
|
+
_own_fields: Mapping[str, ComponentField]
|
|
212
|
+
_fields: Mapping[str, ComponentField]
|
|
213
|
+
_js_fields: Mapping[str, ComponentField]
|
|
214
|
+
|
|
215
|
+
def __new__(cls, name: str, bases: tuple[type], namespace: dict[str, Any]) -> type:
|
|
216
|
+
"""Create a new class.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
name: The name of the class.
|
|
220
|
+
bases: The bases of the class.
|
|
221
|
+
namespace: The namespace of the class.
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
The new class.
|
|
225
|
+
"""
|
|
226
|
+
# Add the field to the class
|
|
227
|
+
inherited_fields: dict[str, ComponentField] = {}
|
|
228
|
+
own_fields: dict[str, ComponentField] = {}
|
|
229
|
+
resolved_annotations = resolve_annotations(
|
|
230
|
+
namespace.get("__annotations__", {}), namespace["__module__"]
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
for base in bases[::-1]:
|
|
234
|
+
if hasattr(base, "_inherited_fields"):
|
|
235
|
+
inherited_fields.update(base._inherited_fields)
|
|
236
|
+
for base in bases[::-1]:
|
|
237
|
+
if hasattr(base, "_own_fields"):
|
|
238
|
+
inherited_fields.update(base._own_fields)
|
|
239
|
+
|
|
240
|
+
for key, value, inherited_field in [
|
|
241
|
+
(key, value, inherited_field)
|
|
242
|
+
for key, value in namespace.items()
|
|
243
|
+
if key not in resolved_annotations
|
|
244
|
+
and ((inherited_field := inherited_fields.get(key)) is not None)
|
|
245
|
+
]:
|
|
246
|
+
new_value = ComponentField(
|
|
247
|
+
default=value,
|
|
248
|
+
is_javascript=inherited_field.is_javascript,
|
|
249
|
+
annotated_type=inherited_field.annotated_type,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
own_fields[key] = new_value
|
|
253
|
+
|
|
254
|
+
for key, annotation in resolved_annotations.items():
|
|
255
|
+
value = namespace.get(key, MISSING)
|
|
256
|
+
|
|
257
|
+
if types.is_classvar(annotation):
|
|
258
|
+
# If the annotation is a classvar, skip it.
|
|
259
|
+
continue
|
|
260
|
+
|
|
261
|
+
if value is MISSING:
|
|
262
|
+
value = ComponentField(
|
|
263
|
+
default=None,
|
|
264
|
+
is_javascript=(key[0] != "_"),
|
|
265
|
+
annotated_type=annotation,
|
|
266
|
+
)
|
|
267
|
+
elif not isinstance(value, ComponentField):
|
|
268
|
+
value = ComponentField(
|
|
269
|
+
default=value,
|
|
270
|
+
is_javascript=(
|
|
271
|
+
(key[0] != "_")
|
|
272
|
+
if (existing_field := inherited_fields.get(key)) is None
|
|
273
|
+
else existing_field.is_javascript
|
|
274
|
+
),
|
|
275
|
+
annotated_type=annotation,
|
|
276
|
+
)
|
|
277
|
+
else:
|
|
278
|
+
value = ComponentField(
|
|
279
|
+
default=value.default,
|
|
280
|
+
default_factory=value.default_factory,
|
|
281
|
+
is_javascript=value.is_javascript,
|
|
282
|
+
annotated_type=annotation,
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
own_fields[key] = value
|
|
286
|
+
|
|
287
|
+
namespace["_own_fields"] = own_fields
|
|
288
|
+
namespace["_inherited_fields"] = inherited_fields
|
|
289
|
+
namespace["_fields"] = inherited_fields | own_fields
|
|
290
|
+
namespace["_js_fields"] = {
|
|
291
|
+
key: value
|
|
292
|
+
for key, value in own_fields.items()
|
|
293
|
+
if value.is_javascript is True
|
|
294
|
+
}
|
|
295
|
+
return super().__new__(cls, name, bases, namespace)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
class BaseComponent(metaclass=BaseComponentMeta):
|
|
66
299
|
"""The base class for all Reflex components.
|
|
67
300
|
|
|
68
301
|
This is something that can be rendered as a Component via the Reflex compiler.
|
|
69
302
|
"""
|
|
70
303
|
|
|
71
304
|
# The children nested within the component.
|
|
72
|
-
children: list[BaseComponent] =
|
|
305
|
+
children: list[BaseComponent] = field(
|
|
306
|
+
default_factory=list, is_javascript_property=False
|
|
307
|
+
)
|
|
73
308
|
|
|
74
309
|
# The library that the component is based on.
|
|
75
|
-
library: str | None =
|
|
310
|
+
library: str | None = field(default=None, is_javascript_property=False)
|
|
76
311
|
|
|
77
312
|
# List here the non-react dependency needed by `library`
|
|
78
|
-
lib_dependencies: list[str] =
|
|
313
|
+
lib_dependencies: list[str] = field(
|
|
314
|
+
default_factory=list, is_javascript_property=False
|
|
315
|
+
)
|
|
79
316
|
|
|
80
317
|
# List here the dependencies that need to be transpiled by Next.js
|
|
81
|
-
transpile_packages: list[str] =
|
|
318
|
+
transpile_packages: list[str] = field(
|
|
319
|
+
default_factory=list, is_javascript_property=False
|
|
320
|
+
)
|
|
82
321
|
|
|
83
322
|
# The tag to use when rendering the component.
|
|
84
|
-
tag: str | None =
|
|
323
|
+
tag: str | None = field(default=None, is_javascript_property=False)
|
|
324
|
+
|
|
325
|
+
def __init__(
|
|
326
|
+
self,
|
|
327
|
+
**kwargs,
|
|
328
|
+
):
|
|
329
|
+
"""Initialize the component.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
**kwargs: The kwargs to pass to the component.
|
|
333
|
+
"""
|
|
334
|
+
for key, value in kwargs.items():
|
|
335
|
+
setattr(self, key, value)
|
|
336
|
+
for name, value in self.get_fields().items():
|
|
337
|
+
if name not in kwargs:
|
|
338
|
+
setattr(self, name, value.default_value())
|
|
339
|
+
|
|
340
|
+
def set(self, **kwargs):
|
|
341
|
+
"""Set the component props.
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
**kwargs: The kwargs to set.
|
|
345
|
+
|
|
346
|
+
Returns:
|
|
347
|
+
The component with the updated props.
|
|
348
|
+
"""
|
|
349
|
+
for key, value in kwargs.items():
|
|
350
|
+
setattr(self, key, value)
|
|
351
|
+
return self
|
|
352
|
+
|
|
353
|
+
def __eq__(self, value: Any) -> bool:
|
|
354
|
+
"""Check if the component is equal to another value.
|
|
355
|
+
|
|
356
|
+
Args:
|
|
357
|
+
value: The value to compare to.
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
Whether the component is equal to the value.
|
|
361
|
+
"""
|
|
362
|
+
return type(self) is type(value) and bool(
|
|
363
|
+
getattr(self, key) == getattr(value, key) for key in self.get_fields()
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
@classmethod
|
|
367
|
+
def get_fields(cls) -> Mapping[str, ComponentField]:
|
|
368
|
+
"""Get the fields of the component.
|
|
369
|
+
|
|
370
|
+
Returns:
|
|
371
|
+
The fields of the component.
|
|
372
|
+
"""
|
|
373
|
+
return cls._fields
|
|
374
|
+
|
|
375
|
+
@classmethod
|
|
376
|
+
def get_js_fields(cls) -> Mapping[str, ComponentField]:
|
|
377
|
+
"""Get the javascript fields of the component.
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
The javascript fields of the component.
|
|
381
|
+
"""
|
|
382
|
+
return cls._js_fields
|
|
85
383
|
|
|
86
384
|
@abstractmethod
|
|
87
385
|
def render(self) -> dict:
|
|
@@ -258,39 +556,39 @@ class Component(BaseComponent, ABC):
|
|
|
258
556
|
"""A component with style, event trigger and other props."""
|
|
259
557
|
|
|
260
558
|
# The style of the component.
|
|
261
|
-
style: Style =
|
|
559
|
+
style: Style = field(default_factory=Style, is_javascript_property=False)
|
|
262
560
|
|
|
263
561
|
# A mapping from event triggers to event chains.
|
|
264
|
-
event_triggers: dict[str, EventChain | Var] =
|
|
265
|
-
default_factory=dict
|
|
562
|
+
event_triggers: dict[str, EventChain | Var] = field(
|
|
563
|
+
default_factory=dict, is_javascript_property=False
|
|
266
564
|
)
|
|
267
565
|
|
|
268
566
|
# The alias for the tag.
|
|
269
|
-
alias: str | None =
|
|
567
|
+
alias: str | None = field(default=None, is_javascript_property=False)
|
|
270
568
|
|
|
271
569
|
# Whether the component is a global scope tag. True for tags like `html`, `head`, `body`.
|
|
272
570
|
_is_tag_in_global_scope: ClassVar[bool] = False
|
|
273
571
|
|
|
274
572
|
# Whether the import is default or named.
|
|
275
|
-
is_default: bool | None =
|
|
573
|
+
is_default: bool | None = field(default=False, is_javascript_property=False)
|
|
276
574
|
|
|
277
575
|
# A unique key for the component.
|
|
278
|
-
key: Any =
|
|
576
|
+
key: Any = field(default=None, is_javascript_property=False)
|
|
279
577
|
|
|
280
578
|
# The id for the component.
|
|
281
|
-
id: Any =
|
|
579
|
+
id: Any = field(default=None, is_javascript_property=False)
|
|
282
580
|
|
|
283
581
|
# The Var to pass as the ref to the component.
|
|
284
|
-
ref: Var | None =
|
|
582
|
+
ref: Var | None = field(default=None, is_javascript_property=False)
|
|
285
583
|
|
|
286
584
|
# The class name for the component.
|
|
287
|
-
class_name: Any =
|
|
585
|
+
class_name: Any = field(default=None, is_javascript_property=False)
|
|
288
586
|
|
|
289
587
|
# Special component props.
|
|
290
|
-
special_props: list[Var] =
|
|
588
|
+
special_props: list[Var] = field(default_factory=list, is_javascript_property=False)
|
|
291
589
|
|
|
292
590
|
# Whether the component should take the focus once the page is loaded
|
|
293
|
-
autofocus: bool =
|
|
591
|
+
autofocus: bool = field(default=False, is_javascript_property=False)
|
|
294
592
|
|
|
295
593
|
# components that cannot be children
|
|
296
594
|
_invalid_children: ClassVar[list[str]] = []
|
|
@@ -305,14 +603,18 @@ class Component(BaseComponent, ABC):
|
|
|
305
603
|
_rename_props: ClassVar[dict[str, str]] = {}
|
|
306
604
|
|
|
307
605
|
# custom attribute
|
|
308
|
-
custom_attrs: dict[str, Var | Any] =
|
|
606
|
+
custom_attrs: dict[str, Var | Any] = field(
|
|
607
|
+
default_factory=dict, is_javascript_property=False
|
|
608
|
+
)
|
|
309
609
|
|
|
310
610
|
# When to memoize this component and its children.
|
|
311
|
-
_memoization_mode: MemoizationMode =
|
|
611
|
+
_memoization_mode: MemoizationMode = field(
|
|
612
|
+
default_factory=MemoizationMode, is_javascript_property=False
|
|
613
|
+
)
|
|
312
614
|
|
|
313
615
|
# State class associated with this component instance
|
|
314
|
-
State: type[reflex.state.State] | None =
|
|
315
|
-
|
|
616
|
+
State: type[reflex.state.State] | None = field(
|
|
617
|
+
default=None, is_javascript_property=False
|
|
316
618
|
)
|
|
317
619
|
|
|
318
620
|
def add_imports(self) -> ImportDict | list[ImportDict]:
|
|
@@ -409,25 +711,6 @@ class Component(BaseComponent, ABC):
|
|
|
409
711
|
"""
|
|
410
712
|
super().__init_subclass__(**kwargs)
|
|
411
713
|
|
|
412
|
-
# Get all the props for the component.
|
|
413
|
-
props = cls.get_props()
|
|
414
|
-
|
|
415
|
-
# Convert fields to props, setting default values.
|
|
416
|
-
for field in cls.get_fields().values():
|
|
417
|
-
# If the field is not a component prop, skip it.
|
|
418
|
-
if field.name not in props:
|
|
419
|
-
continue
|
|
420
|
-
|
|
421
|
-
# Set default values for any props.
|
|
422
|
-
if field.type_ is Var:
|
|
423
|
-
field.required = False
|
|
424
|
-
if field.default is not None:
|
|
425
|
-
field.default_factory = functools.partial(
|
|
426
|
-
LiteralVar.create, field.default
|
|
427
|
-
)
|
|
428
|
-
elif field.type_ is EventHandler:
|
|
429
|
-
field.required = False
|
|
430
|
-
|
|
431
714
|
# Ensure renamed props from parent classes are applied to the subclass.
|
|
432
715
|
if cls._rename_props:
|
|
433
716
|
inherited_rename_props = {}
|
|
@@ -442,15 +725,15 @@ class Component(BaseComponent, ABC):
|
|
|
442
725
|
Args:
|
|
443
726
|
**kwargs: The kwargs to pass to the component.
|
|
444
727
|
"""
|
|
728
|
+
super().__init__(
|
|
729
|
+
children=kwargs.get("children", []),
|
|
730
|
+
)
|
|
445
731
|
console.deprecate(
|
|
446
732
|
"component-direct-instantiation",
|
|
447
733
|
reason="Use the `create` method instead.",
|
|
448
734
|
deprecation_version="0.7.2",
|
|
449
735
|
removal_version="0.8.0",
|
|
450
736
|
)
|
|
451
|
-
super().__init__(
|
|
452
|
-
children=kwargs.get("children", []),
|
|
453
|
-
)
|
|
454
737
|
self._post_init(**kwargs)
|
|
455
738
|
|
|
456
739
|
def _post_init(self, *args, **kwargs):
|
|
@@ -496,7 +779,9 @@ class Component(BaseComponent, ABC):
|
|
|
496
779
|
is_var = False
|
|
497
780
|
elif key in props:
|
|
498
781
|
# Set the field type.
|
|
499
|
-
is_var =
|
|
782
|
+
is_var = (
|
|
783
|
+
field.type_origin is Var if (field := fields.get(key)) else False
|
|
784
|
+
)
|
|
500
785
|
else:
|
|
501
786
|
continue
|
|
502
787
|
|
|
@@ -577,11 +862,7 @@ class Component(BaseComponent, ABC):
|
|
|
577
862
|
|
|
578
863
|
kwargs["style"] = Style(
|
|
579
864
|
{
|
|
580
|
-
**(
|
|
581
|
-
fields_style.default_factory()
|
|
582
|
-
if fields_style.default_factory
|
|
583
|
-
else fields_style.default
|
|
584
|
-
),
|
|
865
|
+
**fields_style.default_value(),
|
|
585
866
|
**style,
|
|
586
867
|
**{attr: value for attr, value in kwargs.items() if attr not in fields},
|
|
587
868
|
}
|
|
@@ -632,17 +913,20 @@ class Component(BaseComponent, ABC):
|
|
|
632
913
|
Returns:
|
|
633
914
|
The event triggers.
|
|
634
915
|
"""
|
|
635
|
-
triggers = DEFAULT_TRIGGERS.copy()
|
|
636
916
|
# Look for component specific triggers,
|
|
637
917
|
# e.g. variable declared as EventHandler types.
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
918
|
+
return DEFAULT_TRIGGERS | {
|
|
919
|
+
name: (
|
|
920
|
+
metadata[0]
|
|
921
|
+
if (
|
|
922
|
+
(metadata := getattr(field.annotated_type, "__metadata__", None))
|
|
923
|
+
is not None
|
|
924
|
+
)
|
|
925
|
+
else no_args_event_spec
|
|
926
|
+
)
|
|
927
|
+
for name, field in self.get_fields().items()
|
|
928
|
+
if field.type_origin is EventHandler
|
|
929
|
+
}
|
|
646
930
|
|
|
647
931
|
def __repr__(self) -> str:
|
|
648
932
|
"""Represent the component in React.
|
|
@@ -848,7 +1132,8 @@ class Component(BaseComponent, ABC):
|
|
|
848
1132
|
Returns:
|
|
849
1133
|
The component.
|
|
850
1134
|
"""
|
|
851
|
-
comp = cls.
|
|
1135
|
+
comp = cls.__new__(cls)
|
|
1136
|
+
super(Component, comp).__init__(id=props.get("id"), children=list(children))
|
|
852
1137
|
comp._post_init(children=list(children), **props)
|
|
853
1138
|
return comp
|
|
854
1139
|
|
|
@@ -865,7 +1150,8 @@ class Component(BaseComponent, ABC):
|
|
|
865
1150
|
Returns:
|
|
866
1151
|
The component.
|
|
867
1152
|
"""
|
|
868
|
-
comp = cls.
|
|
1153
|
+
comp = cls.__new__(cls)
|
|
1154
|
+
super(Component, comp).__init__(id=props.get("id"), children=list(children))
|
|
869
1155
|
for prop, value in props.items():
|
|
870
1156
|
setattr(comp, prop, value)
|
|
871
1157
|
return comp
|
|
@@ -1724,10 +2010,10 @@ class CustomComponent(Component):
|
|
|
1724
2010
|
library = f"$/{Dirs.COMPONENTS_PATH}"
|
|
1725
2011
|
|
|
1726
2012
|
# The function that creates the component.
|
|
1727
|
-
component_fn: Callable[..., Component] = Component.create
|
|
2013
|
+
component_fn: Callable[..., Component] = field(default=Component.create)
|
|
1728
2014
|
|
|
1729
2015
|
# The props of the component.
|
|
1730
|
-
props: dict[str, Any] =
|
|
2016
|
+
props: dict[str, Any] = field(default_factory=dict)
|
|
1731
2017
|
|
|
1732
2018
|
def _post_init(self, **kwargs):
|
|
1733
2019
|
"""Initialize the custom component.
|
|
@@ -2261,7 +2547,9 @@ class StatefulComponent(BaseComponent):
|
|
|
2261
2547
|
return [var_name]
|
|
2262
2548
|
|
|
2263
2549
|
@staticmethod
|
|
2264
|
-
def _get_deps_from_event_trigger(
|
|
2550
|
+
def _get_deps_from_event_trigger(
|
|
2551
|
+
event: EventChain | EventSpec | Var,
|
|
2552
|
+
) -> dict[str, None]:
|
|
2265
2553
|
"""Get the dependencies accessed by event triggers.
|
|
2266
2554
|
|
|
2267
2555
|
Args:
|
|
@@ -2271,7 +2559,7 @@ class StatefulComponent(BaseComponent):
|
|
|
2271
2559
|
The dependencies accessed by the event triggers.
|
|
2272
2560
|
"""
|
|
2273
2561
|
events: list = [event]
|
|
2274
|
-
deps =
|
|
2562
|
+
deps = {}
|
|
2275
2563
|
|
|
2276
2564
|
if isinstance(event, EventChain):
|
|
2277
2565
|
events.extend(event.events)
|
|
@@ -2282,7 +2570,7 @@ class StatefulComponent(BaseComponent):
|
|
|
2282
2570
|
for a in arg:
|
|
2283
2571
|
var_datas = VarData.merge(a._get_all_var_data())
|
|
2284
2572
|
if var_datas and var_datas.deps is not None:
|
|
2285
|
-
deps |= {str(dep) for dep in var_datas.deps}
|
|
2573
|
+
deps |= {str(dep): None for dep in var_datas.deps}
|
|
2286
2574
|
return deps
|
|
2287
2575
|
|
|
2288
2576
|
@classmethod
|
|
@@ -2499,27 +2787,23 @@ def empty_component() -> Component:
|
|
|
2499
2787
|
return Bare.create("")
|
|
2500
2788
|
|
|
2501
2789
|
|
|
2502
|
-
def render_dict_to_var(tag: dict | Component | str
|
|
2790
|
+
def render_dict_to_var(tag: dict | Component | str) -> Var:
|
|
2503
2791
|
"""Convert a render dict to a Var.
|
|
2504
2792
|
|
|
2505
2793
|
Args:
|
|
2506
2794
|
tag: The render dict.
|
|
2507
|
-
imported_names: The names of the imported components.
|
|
2508
2795
|
|
|
2509
2796
|
Returns:
|
|
2510
2797
|
The Var.
|
|
2511
2798
|
"""
|
|
2512
2799
|
if not isinstance(tag, dict):
|
|
2513
2800
|
if isinstance(tag, Component):
|
|
2514
|
-
return render_dict_to_var(tag.render()
|
|
2801
|
+
return render_dict_to_var(tag.render())
|
|
2515
2802
|
return Var.create(tag)
|
|
2516
2803
|
|
|
2517
2804
|
if "iterable" in tag:
|
|
2518
2805
|
function_return = LiteralArrayVar.create(
|
|
2519
|
-
[
|
|
2520
|
-
render_dict_to_var(child.render(), imported_names)
|
|
2521
|
-
for child in tag["children"]
|
|
2522
|
-
]
|
|
2806
|
+
[render_dict_to_var(child.render()) for child in tag["children"]]
|
|
2523
2807
|
)
|
|
2524
2808
|
|
|
2525
2809
|
func = ArgsFunctionOperation.create(
|
|
@@ -2537,7 +2821,7 @@ def render_dict_to_var(tag: dict | Component | str, imported_names: set[str]) ->
|
|
|
2537
2821
|
if tag["name"] == "match":
|
|
2538
2822
|
element = tag["cond"]
|
|
2539
2823
|
|
|
2540
|
-
conditionals = render_dict_to_var(tag["default"]
|
|
2824
|
+
conditionals = render_dict_to_var(tag["default"])
|
|
2541
2825
|
|
|
2542
2826
|
for case in tag["match_cases"][::-1]:
|
|
2543
2827
|
condition = case[0].to_string() == element.to_string()
|
|
@@ -2546,7 +2830,7 @@ def render_dict_to_var(tag: dict | Component | str, imported_names: set[str]) ->
|
|
|
2546
2830
|
|
|
2547
2831
|
conditionals = ternary_operation(
|
|
2548
2832
|
condition,
|
|
2549
|
-
render_dict_to_var(case[-1]
|
|
2833
|
+
render_dict_to_var(case[-1]),
|
|
2550
2834
|
conditionals,
|
|
2551
2835
|
)
|
|
2552
2836
|
|
|
@@ -2555,8 +2839,8 @@ def render_dict_to_var(tag: dict | Component | str, imported_names: set[str]) ->
|
|
|
2555
2839
|
if "cond" in tag:
|
|
2556
2840
|
return ternary_operation(
|
|
2557
2841
|
tag["cond"],
|
|
2558
|
-
render_dict_to_var(tag["true_value"]
|
|
2559
|
-
render_dict_to_var(tag["false_value"]
|
|
2842
|
+
render_dict_to_var(tag["true_value"]),
|
|
2843
|
+
render_dict_to_var(tag["false_value"])
|
|
2560
2844
|
if tag["false_value"] is not None
|
|
2561
2845
|
else LiteralNoneVar.create(),
|
|
2562
2846
|
)
|
|
@@ -2574,7 +2858,7 @@ def render_dict_to_var(tag: dict | Component | str, imported_names: set[str]) ->
|
|
|
2574
2858
|
tag_name,
|
|
2575
2859
|
props,
|
|
2576
2860
|
*([Var(contents)] if contents is not None else []),
|
|
2577
|
-
*[render_dict_to_var(child
|
|
2861
|
+
*[render_dict_to_var(child) for child in tag["children"]],
|
|
2578
2862
|
)
|
|
2579
2863
|
|
|
2580
2864
|
|
|
@@ -2595,13 +2879,7 @@ class LiteralComponentVar(CachedVarOperation, LiteralVar, ComponentVar):
|
|
|
2595
2879
|
Returns:
|
|
2596
2880
|
The name of the var.
|
|
2597
2881
|
"""
|
|
2598
|
-
|
|
2599
|
-
if var_data is not None:
|
|
2600
|
-
# flatten imports
|
|
2601
|
-
imported_names = {j.alias or j.name for i in var_data.imports for j in i[1]}
|
|
2602
|
-
else:
|
|
2603
|
-
imported_names = set()
|
|
2604
|
-
return str(render_dict_to_var(self._var_value.render(), imported_names))
|
|
2882
|
+
return str(render_dict_to_var(self._var_value.render()))
|
|
2605
2883
|
|
|
2606
2884
|
@cached_property_no_lock
|
|
2607
2885
|
def _cached_get_all_var_data(self) -> VarData | None:
|