reflex 0.4.5a2__py3-none-any.whl → 0.4.6a1__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 +5 -15
- reflex/.templates/jinja/web/pages/index.js.jinja2 +4 -0
- reflex/.templates/jinja/web/pages/stateful_component.js.jinja2 +4 -0
- reflex/.templates/web/utils/state.js +3 -0
- reflex/__init__.py +12 -2
- reflex/__init__.pyi +4 -0
- reflex/app.py +21 -1
- reflex/base.py +16 -4
- reflex/compiler/compiler.py +1 -0
- reflex/compiler/utils.py +11 -2
- reflex/components/base/app_wrap.pyi +1 -1
- reflex/components/base/bare.py +3 -4
- reflex/components/base/body.pyi +1 -1
- reflex/components/base/document.pyi +1 -1
- reflex/components/base/fragment.pyi +1 -1
- reflex/components/base/head.pyi +1 -1
- reflex/components/base/link.pyi +1 -1
- reflex/components/base/meta.pyi +1 -1
- reflex/components/base/script.pyi +1 -1
- reflex/components/chakra/base.pyi +1 -1
- reflex/components/chakra/datadisplay/badge.pyi +1 -1
- reflex/components/chakra/datadisplay/code.pyi +1 -1
- reflex/components/chakra/datadisplay/divider.pyi +1 -1
- reflex/components/chakra/datadisplay/keyboard_key.pyi +1 -1
- reflex/components/chakra/datadisplay/list.pyi +1 -1
- reflex/components/chakra/datadisplay/stat.pyi +1 -1
- reflex/components/chakra/datadisplay/table.pyi +1 -1
- reflex/components/chakra/datadisplay/tag.pyi +1 -1
- reflex/components/chakra/disclosure/accordion.pyi +1 -1
- reflex/components/chakra/disclosure/tabs.pyi +1 -1
- reflex/components/chakra/disclosure/transition.pyi +1 -1
- reflex/components/chakra/disclosure/visuallyhidden.pyi +1 -1
- reflex/components/chakra/feedback/alert.pyi +1 -1
- reflex/components/chakra/feedback/circularprogress.pyi +1 -1
- reflex/components/chakra/feedback/progress.pyi +1 -1
- reflex/components/chakra/feedback/skeleton.pyi +1 -1
- reflex/components/chakra/feedback/spinner.pyi +1 -1
- reflex/components/chakra/forms/button.pyi +1 -1
- reflex/components/chakra/forms/checkbox.pyi +1 -1
- reflex/components/chakra/forms/colormodeswitch.pyi +1 -1
- reflex/components/chakra/forms/date_picker.pyi +1 -1
- reflex/components/chakra/forms/date_time_picker.pyi +1 -1
- reflex/components/chakra/forms/editable.pyi +1 -1
- reflex/components/chakra/forms/email.pyi +1 -1
- reflex/components/chakra/forms/form.pyi +1 -1
- reflex/components/chakra/forms/iconbutton.pyi +1 -1
- reflex/components/chakra/forms/input.pyi +1 -1
- reflex/components/chakra/forms/numberinput.pyi +1 -1
- reflex/components/chakra/forms/password.pyi +1 -1
- reflex/components/chakra/forms/pininput.pyi +1 -1
- reflex/components/chakra/forms/radio.pyi +1 -1
- reflex/components/chakra/forms/rangeslider.pyi +1 -1
- reflex/components/chakra/forms/select.pyi +1 -1
- reflex/components/chakra/forms/slider.pyi +1 -1
- reflex/components/chakra/forms/switch.pyi +1 -1
- reflex/components/chakra/forms/textarea.pyi +1 -1
- reflex/components/chakra/forms/time_picker.pyi +1 -1
- reflex/components/chakra/layout/aspect_ratio.pyi +1 -1
- reflex/components/chakra/layout/box.pyi +1 -1
- reflex/components/chakra/layout/card.pyi +1 -1
- reflex/components/chakra/layout/center.pyi +1 -1
- reflex/components/chakra/layout/container.pyi +1 -1
- reflex/components/chakra/layout/flex.pyi +1 -1
- reflex/components/chakra/layout/grid.pyi +1 -1
- reflex/components/chakra/layout/spacer.pyi +1 -1
- reflex/components/chakra/layout/stack.pyi +1 -1
- reflex/components/chakra/layout/wrap.pyi +1 -1
- reflex/components/chakra/media/avatar.pyi +1 -1
- reflex/components/chakra/media/icon.pyi +1 -1
- reflex/components/chakra/media/image.pyi +1 -1
- reflex/components/chakra/navigation/breadcrumb.pyi +1 -1
- reflex/components/chakra/navigation/link.pyi +1 -1
- reflex/components/chakra/navigation/linkoverlay.pyi +1 -1
- reflex/components/chakra/navigation/stepper.pyi +1 -1
- reflex/components/chakra/overlay/alertdialog.pyi +1 -1
- reflex/components/chakra/overlay/drawer.pyi +1 -1
- reflex/components/chakra/overlay/menu.pyi +1 -1
- reflex/components/chakra/overlay/modal.pyi +1 -1
- reflex/components/chakra/overlay/popover.pyi +1 -1
- reflex/components/chakra/overlay/tooltip.pyi +1 -1
- reflex/components/chakra/typography/heading.pyi +1 -1
- reflex/components/chakra/typography/highlight.pyi +1 -1
- reflex/components/chakra/typography/span.pyi +1 -1
- reflex/components/chakra/typography/text.pyi +1 -1
- reflex/components/component.py +109 -30
- reflex/components/core/banner.py +1 -2
- reflex/components/core/banner.pyi +1 -2
- reflex/components/core/client_side_routing.pyi +1 -1
- reflex/components/core/cond.py +1 -1
- reflex/components/core/debounce.pyi +1 -1
- reflex/components/core/html.pyi +1 -1
- reflex/components/core/responsive.py +1 -1
- reflex/components/core/upload.pyi +1 -1
- reflex/components/datadisplay/code.py +17 -9
- reflex/components/datadisplay/code.pyi +3 -1
- reflex/components/datadisplay/dataeditor.pyi +1 -1
- reflex/components/el/element.pyi +1 -1
- reflex/components/el/elements/base.pyi +1 -1
- reflex/components/el/elements/forms.py +78 -1
- reflex/components/el/elements/forms.pyi +10 -2
- reflex/components/el/elements/inline.pyi +1 -1
- reflex/components/el/elements/media.pyi +1 -1
- reflex/components/el/elements/metadata.pyi +1 -1
- reflex/components/el/elements/other.pyi +1 -1
- reflex/components/el/elements/scripts.pyi +1 -1
- reflex/components/el/elements/sectioning.pyi +1 -1
- reflex/components/el/elements/tables.pyi +1 -1
- reflex/components/el/elements/typography.pyi +1 -1
- reflex/components/gridjs/datatable.pyi +1 -1
- reflex/components/lucide/icon.py +275 -115
- reflex/components/lucide/icon.pyi +259 -114
- reflex/components/markdown/markdown.pyi +1 -1
- reflex/components/moment/moment.pyi +1 -1
- reflex/components/next/base.pyi +1 -1
- reflex/components/next/image.pyi +1 -1
- reflex/components/next/link.pyi +1 -1
- reflex/components/next/video.pyi +1 -1
- reflex/components/plotly/plotly.pyi +1 -1
- reflex/components/radix/primitives/accordion.pyi +1 -1
- reflex/components/radix/primitives/base.pyi +1 -1
- reflex/components/radix/primitives/drawer.pyi +1 -1
- reflex/components/radix/primitives/form.pyi +1 -1
- reflex/components/radix/primitives/progress.pyi +1 -1
- reflex/components/radix/primitives/slider.pyi +1 -1
- reflex/components/radix/themes/base.pyi +1 -1
- reflex/components/radix/themes/color_mode.pyi +1 -1
- reflex/components/radix/themes/components/alert_dialog.pyi +1 -1
- reflex/components/radix/themes/components/aspect_ratio.pyi +1 -1
- reflex/components/radix/themes/components/avatar.pyi +1 -1
- reflex/components/radix/themes/components/badge.pyi +1 -1
- reflex/components/radix/themes/components/button.pyi +1 -1
- reflex/components/radix/themes/components/callout.pyi +1 -1
- reflex/components/radix/themes/components/card.pyi +1 -1
- reflex/components/radix/themes/components/checkbox.pyi +1 -1
- reflex/components/radix/themes/components/context_menu.pyi +1 -1
- reflex/components/radix/themes/components/dialog.pyi +1 -1
- reflex/components/radix/themes/components/dropdown_menu.pyi +1 -1
- reflex/components/radix/themes/components/hover_card.pyi +1 -1
- reflex/components/radix/themes/components/icon_button.pyi +1 -1
- reflex/components/radix/themes/components/inset.pyi +1 -1
- reflex/components/radix/themes/components/popover.pyi +1 -1
- reflex/components/radix/themes/components/radio_group.pyi +1 -1
- reflex/components/radix/themes/components/scroll_area.pyi +1 -1
- reflex/components/radix/themes/components/select.pyi +1 -1
- reflex/components/radix/themes/components/separator.pyi +1 -1
- reflex/components/radix/themes/components/slider.pyi +1 -1
- reflex/components/radix/themes/components/switch.pyi +1 -1
- reflex/components/radix/themes/components/table.pyi +1 -1
- reflex/components/radix/themes/components/tabs.pyi +1 -1
- reflex/components/radix/themes/components/text_area.pyi +5 -1
- reflex/components/radix/themes/components/text_field.pyi +1 -1
- reflex/components/radix/themes/components/tooltip.pyi +1 -1
- reflex/components/radix/themes/layout/__init__.py +5 -4
- reflex/components/radix/themes/layout/base.pyi +1 -1
- reflex/components/radix/themes/layout/box.pyi +1 -1
- reflex/components/radix/themes/layout/center.pyi +1 -1
- reflex/components/radix/themes/layout/container.pyi +1 -1
- reflex/components/radix/themes/layout/flex.pyi +1 -1
- reflex/components/radix/themes/layout/grid.pyi +1 -1
- reflex/components/radix/themes/layout/list.py +21 -13
- reflex/components/radix/themes/layout/list.pyi +139 -481
- reflex/components/radix/themes/layout/section.pyi +1 -1
- reflex/components/radix/themes/layout/spacer.pyi +1 -1
- reflex/components/radix/themes/layout/stack.pyi +1 -1
- reflex/components/radix/themes/typography/blockquote.pyi +1 -1
- reflex/components/radix/themes/typography/code.pyi +1 -1
- reflex/components/radix/themes/typography/heading.pyi +1 -1
- reflex/components/radix/themes/typography/link.pyi +1 -1
- reflex/components/radix/themes/typography/text.pyi +1 -1
- reflex/components/react_player/audio.pyi +1 -1
- reflex/components/react_player/react_player.pyi +1 -1
- reflex/components/react_player/video.pyi +1 -1
- reflex/components/recharts/cartesian.pyi +1 -1
- reflex/components/recharts/charts.pyi +1 -1
- reflex/components/recharts/general.pyi +1 -1
- reflex/components/recharts/polar.pyi +1 -1
- reflex/components/recharts/recharts.pyi +1 -1
- reflex/components/suneditor/editor.pyi +1 -1
- reflex/config.py +12 -2
- reflex/custom_components/custom_components.py +313 -20
- reflex/event.py +36 -46
- reflex/reflex.py +19 -13
- reflex/state.py +184 -39
- reflex/testing.py +15 -11
- reflex/utils/console.py +15 -7
- reflex/utils/prerequisites.py +11 -0
- reflex/utils/processes.py +8 -25
- reflex/utils/pyi_generator.py +842 -0
- reflex/utils/types.py +14 -2
- reflex/vars.py +33 -3
- {reflex-0.4.5a2.dist-info → reflex-0.4.6a1.dist-info}/METADATA +33 -31
- {reflex-0.4.5a2.dist-info → reflex-0.4.6a1.dist-info}/RECORD +195 -195
- reflex/page.pyi +0 -17
- {reflex-0.4.5a2.dist-info → reflex-0.4.6a1.dist-info}/LICENSE +0 -0
- {reflex-0.4.5a2.dist-info → reflex-0.4.6a1.dist-info}/WHEEL +0 -0
- {reflex-0.4.5a2.dist-info → reflex-0.4.6a1.dist-info}/entry_points.txt +0 -0
reflex/components/component.py
CHANGED
|
@@ -21,6 +21,7 @@ from typing import (
|
|
|
21
21
|
Union,
|
|
22
22
|
)
|
|
23
23
|
|
|
24
|
+
import reflex.state
|
|
24
25
|
from reflex.base import Base
|
|
25
26
|
from reflex.compiler.templates import STATEFUL_COMPONENT
|
|
26
27
|
from reflex.components.tags import Tag
|
|
@@ -74,6 +75,14 @@ class BaseComponent(Base, ABC):
|
|
|
74
75
|
The dictionary for template of the component.
|
|
75
76
|
"""
|
|
76
77
|
|
|
78
|
+
@abstractmethod
|
|
79
|
+
def get_ref_hooks(self) -> set[str]:
|
|
80
|
+
"""Get the hooks required by refs in this component.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
The hooks for the refs.
|
|
84
|
+
"""
|
|
85
|
+
|
|
77
86
|
@abstractmethod
|
|
78
87
|
def get_hooks_internal(self) -> set[str]:
|
|
79
88
|
"""Get the reflex internal hooks for the component and its children.
|
|
@@ -206,6 +215,9 @@ class Component(BaseComponent, ABC):
|
|
|
206
215
|
# When to memoize this component and its children.
|
|
207
216
|
_memoization_mode: MemoizationMode = MemoizationMode()
|
|
208
217
|
|
|
218
|
+
# State class associated with this component instance
|
|
219
|
+
State: Optional[Type[reflex.state.State]] = None
|
|
220
|
+
|
|
209
221
|
@classmethod
|
|
210
222
|
def __init_subclass__(cls, **kwargs):
|
|
211
223
|
"""Set default properties.
|
|
@@ -228,6 +240,8 @@ class Component(BaseComponent, ABC):
|
|
|
228
240
|
if types._issubclass(field.type_, Var):
|
|
229
241
|
field.required = False
|
|
230
242
|
field.default = Var.create(field.default)
|
|
243
|
+
elif types._issubclass(field.type_, EventHandler):
|
|
244
|
+
field.required = False
|
|
231
245
|
|
|
232
246
|
# Ensure renamed props from parent classes are applied to the subclass.
|
|
233
247
|
if cls._rename_props:
|
|
@@ -264,7 +278,8 @@ class Component(BaseComponent, ABC):
|
|
|
264
278
|
|
|
265
279
|
# Get the component fields, triggers, and props.
|
|
266
280
|
fields = self.get_fields()
|
|
267
|
-
|
|
281
|
+
component_specific_triggers = self.get_event_triggers()
|
|
282
|
+
triggers = component_specific_triggers.keys()
|
|
268
283
|
props = self.get_props()
|
|
269
284
|
|
|
270
285
|
# Add any events triggers.
|
|
@@ -319,7 +334,9 @@ class Component(BaseComponent, ABC):
|
|
|
319
334
|
# Check if the key is an event trigger.
|
|
320
335
|
if key in triggers:
|
|
321
336
|
# Temporarily disable full control for event triggers.
|
|
322
|
-
kwargs["event_triggers"][key] = self._create_event_chain(
|
|
337
|
+
kwargs["event_triggers"][key] = self._create_event_chain(
|
|
338
|
+
value=value, args_spec=component_specific_triggers[key]
|
|
339
|
+
)
|
|
323
340
|
|
|
324
341
|
# Remove any keys that were added as events.
|
|
325
342
|
for key in kwargs["event_triggers"]:
|
|
@@ -351,7 +368,7 @@ class Component(BaseComponent, ABC):
|
|
|
351
368
|
|
|
352
369
|
def _create_event_chain(
|
|
353
370
|
self,
|
|
354
|
-
|
|
371
|
+
args_spec: Any,
|
|
355
372
|
value: Union[
|
|
356
373
|
Var, EventHandler, EventSpec, List[Union[EventHandler, EventSpec]], Callable
|
|
357
374
|
],
|
|
@@ -359,7 +376,7 @@ class Component(BaseComponent, ABC):
|
|
|
359
376
|
"""Create an event chain from a variety of input types.
|
|
360
377
|
|
|
361
378
|
Args:
|
|
362
|
-
|
|
379
|
+
args_spec: The args_spec of the the event trigger being bound.
|
|
363
380
|
value: The value to create the event chain from.
|
|
364
381
|
|
|
365
382
|
Returns:
|
|
@@ -368,9 +385,6 @@ class Component(BaseComponent, ABC):
|
|
|
368
385
|
Raises:
|
|
369
386
|
ValueError: If the value is not a valid event chain.
|
|
370
387
|
"""
|
|
371
|
-
# Check if the trigger is a controlled event.
|
|
372
|
-
triggers = self.get_event_triggers()
|
|
373
|
-
|
|
374
388
|
# If it's an event chain var, return it.
|
|
375
389
|
if isinstance(value, Var):
|
|
376
390
|
if value._var_type is not EventChain:
|
|
@@ -380,8 +394,6 @@ class Component(BaseComponent, ABC):
|
|
|
380
394
|
# Trust that the caller knows what they're doing passing an EventChain directly
|
|
381
395
|
return value
|
|
382
396
|
|
|
383
|
-
arg_spec = triggers.get(event_trigger, lambda: [])
|
|
384
|
-
|
|
385
397
|
# If the input is a single event handler, wrap it in a list.
|
|
386
398
|
if isinstance(value, (EventHandler, EventSpec)):
|
|
387
399
|
value = [value]
|
|
@@ -393,7 +405,7 @@ class Component(BaseComponent, ABC):
|
|
|
393
405
|
if isinstance(v, EventHandler):
|
|
394
406
|
# Call the event handler to get the event.
|
|
395
407
|
try:
|
|
396
|
-
event = call_event_handler(v,
|
|
408
|
+
event = call_event_handler(v, args_spec)
|
|
397
409
|
except ValueError as err:
|
|
398
410
|
raise ValueError(
|
|
399
411
|
f" {err} defined in the `{type(self).__name__}` component"
|
|
@@ -406,13 +418,13 @@ class Component(BaseComponent, ABC):
|
|
|
406
418
|
events.append(v)
|
|
407
419
|
elif isinstance(v, Callable):
|
|
408
420
|
# Call the lambda to get the event chain.
|
|
409
|
-
events.extend(call_event_fn(v,
|
|
421
|
+
events.extend(call_event_fn(v, args_spec))
|
|
410
422
|
else:
|
|
411
423
|
raise ValueError(f"Invalid event: {v}")
|
|
412
424
|
|
|
413
425
|
# If the input is a callable, create an event chain.
|
|
414
426
|
elif isinstance(value, Callable):
|
|
415
|
-
events = call_event_fn(value,
|
|
427
|
+
events = call_event_fn(value, args_spec)
|
|
416
428
|
|
|
417
429
|
# Otherwise, raise an error.
|
|
418
430
|
else:
|
|
@@ -427,7 +439,7 @@ class Component(BaseComponent, ABC):
|
|
|
427
439
|
event_actions.update(e.event_actions)
|
|
428
440
|
|
|
429
441
|
# Return the event chain.
|
|
430
|
-
if isinstance(
|
|
442
|
+
if isinstance(args_spec, Var):
|
|
431
443
|
return EventChain(
|
|
432
444
|
events=events,
|
|
433
445
|
args_spec=None,
|
|
@@ -436,7 +448,7 @@ class Component(BaseComponent, ABC):
|
|
|
436
448
|
else:
|
|
437
449
|
return EventChain(
|
|
438
450
|
events=events,
|
|
439
|
-
args_spec=
|
|
451
|
+
args_spec=args_spec,
|
|
440
452
|
event_actions=event_actions,
|
|
441
453
|
)
|
|
442
454
|
|
|
@@ -446,7 +458,7 @@ class Component(BaseComponent, ABC):
|
|
|
446
458
|
Returns:
|
|
447
459
|
The event triggers.
|
|
448
460
|
"""
|
|
449
|
-
|
|
461
|
+
default_triggers = {
|
|
450
462
|
EventTriggers.ON_FOCUS: lambda: [],
|
|
451
463
|
EventTriggers.ON_BLUR: lambda: [],
|
|
452
464
|
EventTriggers.ON_CLICK: lambda: [],
|
|
@@ -463,6 +475,14 @@ class Component(BaseComponent, ABC):
|
|
|
463
475
|
EventTriggers.ON_MOUNT: lambda: [],
|
|
464
476
|
EventTriggers.ON_UNMOUNT: lambda: [],
|
|
465
477
|
}
|
|
478
|
+
# Look for component specific triggers,
|
|
479
|
+
# e.g. variable declared as EventHandler types.
|
|
480
|
+
for field in self.get_fields().values():
|
|
481
|
+
if types._issubclass(field.type_, EventHandler):
|
|
482
|
+
default_triggers[field.name] = getattr(
|
|
483
|
+
field.type_, "args_spec", lambda: []
|
|
484
|
+
)
|
|
485
|
+
return default_triggers
|
|
466
486
|
|
|
467
487
|
def __repr__(self) -> str:
|
|
468
488
|
"""Represent the component in React.
|
|
@@ -621,6 +641,7 @@ class Component(BaseComponent, ABC):
|
|
|
621
641
|
reason=f"for consistency. Use `{prop}` instead.",
|
|
622
642
|
deprecation_version="0.4.0",
|
|
623
643
|
removal_version="0.5.0",
|
|
644
|
+
dedupe=False,
|
|
624
645
|
)
|
|
625
646
|
props[prop] = props.pop(under_prop)
|
|
626
647
|
|
|
@@ -635,9 +656,11 @@ class Component(BaseComponent, ABC):
|
|
|
635
656
|
)
|
|
636
657
|
|
|
637
658
|
children = [
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
659
|
+
(
|
|
660
|
+
child
|
|
661
|
+
if isinstance(child, Component)
|
|
662
|
+
else Bare.create(contents=Var.create(child, _var_is_string=True))
|
|
663
|
+
)
|
|
641
664
|
for child in children
|
|
642
665
|
]
|
|
643
666
|
|
|
@@ -1006,6 +1029,16 @@ class Component(BaseComponent, ABC):
|
|
|
1006
1029
|
)
|
|
1007
1030
|
return _imports
|
|
1008
1031
|
|
|
1032
|
+
def add_imports(
|
|
1033
|
+
self,
|
|
1034
|
+
) -> Dict[str, Union[str, ImportVar, List[str | ImportVar]]]:
|
|
1035
|
+
"""User defined imports for the component. Need to be overriden in subclass.
|
|
1036
|
+
|
|
1037
|
+
Returns:
|
|
1038
|
+
The user defined imports as a dict.
|
|
1039
|
+
"""
|
|
1040
|
+
return {}
|
|
1041
|
+
|
|
1009
1042
|
def _get_imports(self) -> imports.ImportDict:
|
|
1010
1043
|
"""Get all the libraries and fields that are used by the component.
|
|
1011
1044
|
|
|
@@ -1026,24 +1059,45 @@ class Component(BaseComponent, ABC):
|
|
|
1026
1059
|
var._var_data.imports for var in self._get_vars() if var._var_data
|
|
1027
1060
|
]
|
|
1028
1061
|
|
|
1062
|
+
# If the subclass implements add_imports, merge the imports.
|
|
1063
|
+
def _make_list(
|
|
1064
|
+
value: str | ImportVar | list[str | ImportVar],
|
|
1065
|
+
) -> list[str | ImportVar]:
|
|
1066
|
+
if isinstance(value, (str, ImportVar)):
|
|
1067
|
+
return [value]
|
|
1068
|
+
return value
|
|
1069
|
+
|
|
1070
|
+
added_imports = {
|
|
1071
|
+
package: [
|
|
1072
|
+
ImportVar(tag=tag) if not isinstance(tag, ImportVar) else tag
|
|
1073
|
+
for tag in _make_list(maybe_tags)
|
|
1074
|
+
]
|
|
1075
|
+
for package, maybe_tags in self.add_imports().items()
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1029
1078
|
return imports.merge_imports(
|
|
1030
1079
|
*self._get_props_imports(),
|
|
1031
1080
|
self._get_dependencies_imports(),
|
|
1032
1081
|
self._get_hooks_imports(),
|
|
1033
1082
|
_imports,
|
|
1034
1083
|
event_imports,
|
|
1084
|
+
added_imports,
|
|
1035
1085
|
*var_imports,
|
|
1036
1086
|
)
|
|
1037
1087
|
|
|
1038
|
-
def get_imports(self) -> imports.ImportDict:
|
|
1088
|
+
def get_imports(self, collapse: bool = False) -> imports.ImportDict:
|
|
1039
1089
|
"""Get all the libraries and fields that are used by the component and its children.
|
|
1040
1090
|
|
|
1091
|
+
Args:
|
|
1092
|
+
collapse: Whether to collapse the imports by removing duplicates.
|
|
1093
|
+
|
|
1041
1094
|
Returns:
|
|
1042
1095
|
The import dict with the required imports.
|
|
1043
1096
|
"""
|
|
1044
|
-
|
|
1097
|
+
_imports = imports.merge_imports(
|
|
1045
1098
|
self._get_imports(), *[child.get_imports() for child in self.children]
|
|
1046
1099
|
)
|
|
1100
|
+
return imports.collapse_imports(_imports) if collapse else _imports
|
|
1047
1101
|
|
|
1048
1102
|
def _get_mount_lifecycle_hook(self) -> str | None:
|
|
1049
1103
|
"""Generate the component lifecycle hook.
|
|
@@ -1129,14 +1183,10 @@ class Component(BaseComponent, ABC):
|
|
|
1129
1183
|
Set of internally managed hooks.
|
|
1130
1184
|
"""
|
|
1131
1185
|
return (
|
|
1132
|
-
|
|
1133
|
-
hook
|
|
1134
|
-
for hook in [self._get_mount_lifecycle_hook(), self._get_ref_hook()]
|
|
1135
|
-
if hook
|
|
1136
|
-
)
|
|
1137
|
-
| self._get_vars_hooks()
|
|
1186
|
+
self._get_vars_hooks()
|
|
1138
1187
|
| self._get_events_hooks()
|
|
1139
1188
|
| self._get_special_hooks()
|
|
1189
|
+
| set(hook for hook in [self._get_mount_lifecycle_hook()] if hook)
|
|
1140
1190
|
)
|
|
1141
1191
|
|
|
1142
1192
|
def _get_hooks(self) -> str | None:
|
|
@@ -1149,6 +1199,19 @@ class Component(BaseComponent, ABC):
|
|
|
1149
1199
|
"""
|
|
1150
1200
|
return
|
|
1151
1201
|
|
|
1202
|
+
def get_ref_hooks(self) -> Set[str]:
|
|
1203
|
+
"""Get the ref hooks for the component and its children.
|
|
1204
|
+
|
|
1205
|
+
Returns:
|
|
1206
|
+
The ref hooks.
|
|
1207
|
+
"""
|
|
1208
|
+
ref_hook = self._get_ref_hook()
|
|
1209
|
+
hooks = set() if ref_hook is None else {ref_hook}
|
|
1210
|
+
|
|
1211
|
+
for child in self.children:
|
|
1212
|
+
hooks |= child.get_ref_hooks()
|
|
1213
|
+
return hooks
|
|
1214
|
+
|
|
1152
1215
|
def get_hooks_internal(self) -> set[str]:
|
|
1153
1216
|
"""Get the reflex internal hooks for the component and its children.
|
|
1154
1217
|
|
|
@@ -1305,6 +1368,9 @@ class CustomComponent(Component):
|
|
|
1305
1368
|
# Set the tag to the name of the function.
|
|
1306
1369
|
self.tag = format.to_title_case(self.component_fn.__name__)
|
|
1307
1370
|
|
|
1371
|
+
# Get the event triggers defined in the component declaration.
|
|
1372
|
+
event_triggers_in_component_declaration = self.get_event_triggers()
|
|
1373
|
+
|
|
1308
1374
|
# Set the props.
|
|
1309
1375
|
props = typing.get_type_hints(self.component_fn)
|
|
1310
1376
|
for key, value in kwargs.items():
|
|
@@ -1317,7 +1383,12 @@ class CustomComponent(Component):
|
|
|
1317
1383
|
|
|
1318
1384
|
# Handle event chains.
|
|
1319
1385
|
if types._issubclass(type_, EventChain):
|
|
1320
|
-
value = self._create_event_chain(
|
|
1386
|
+
value = self._create_event_chain(
|
|
1387
|
+
value=value,
|
|
1388
|
+
args_spec=event_triggers_in_component_declaration.get(
|
|
1389
|
+
key, lambda: []
|
|
1390
|
+
),
|
|
1391
|
+
)
|
|
1321
1392
|
self.props[format.to_camel_case(key)] = value
|
|
1322
1393
|
continue
|
|
1323
1394
|
|
|
@@ -1423,9 +1494,9 @@ class CustomComponent(Component):
|
|
|
1423
1494
|
return [
|
|
1424
1495
|
BaseVar(
|
|
1425
1496
|
_var_name=name,
|
|
1426
|
-
_var_type=
|
|
1427
|
-
|
|
1428
|
-
|
|
1497
|
+
_var_type=(
|
|
1498
|
+
prop._var_type if types._isinstance(prop, Var) else type(prop)
|
|
1499
|
+
),
|
|
1429
1500
|
)
|
|
1430
1501
|
for name, prop in self.props.items()
|
|
1431
1502
|
]
|
|
@@ -1807,6 +1878,14 @@ class StatefulComponent(BaseComponent):
|
|
|
1807
1878
|
)
|
|
1808
1879
|
return trigger_memo
|
|
1809
1880
|
|
|
1881
|
+
def get_ref_hooks(self) -> set[str]:
|
|
1882
|
+
"""Get the ref hooks for the component and its children.
|
|
1883
|
+
|
|
1884
|
+
Returns:
|
|
1885
|
+
The ref hooks.
|
|
1886
|
+
"""
|
|
1887
|
+
return set()
|
|
1888
|
+
|
|
1810
1889
|
def get_hooks_internal(self) -> set[str]:
|
|
1811
1890
|
"""Get the reflex internal hooks for the component and its children.
|
|
1812
1891
|
|
reflex/components/core/banner.py
CHANGED
|
@@ -17,7 +17,6 @@ from reflex.components.radix.themes.components.dialog import (
|
|
|
17
17
|
from reflex.components.radix.themes.layout import Flex
|
|
18
18
|
from reflex.components.radix.themes.typography.text import Text
|
|
19
19
|
from reflex.constants import Dirs, Hooks, Imports
|
|
20
|
-
from reflex.state import State
|
|
21
20
|
from reflex.utils import imports
|
|
22
21
|
from reflex.vars import Var, VarData
|
|
23
22
|
|
|
@@ -199,7 +198,7 @@ class ConnectionPulser(Div):
|
|
|
199
198
|
"""
|
|
200
199
|
return super().create(
|
|
201
200
|
cond(
|
|
202
|
-
|
|
201
|
+
has_connection_errors,
|
|
203
202
|
WifiOffPulse.create(**props),
|
|
204
203
|
),
|
|
205
204
|
position="fixed",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Stub file for reflex/components/core/banner.py"""
|
|
2
2
|
# ------------------- DO NOT EDIT ----------------------
|
|
3
|
-
# This file was generated by `
|
|
3
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
4
|
# ------------------------------------------------------
|
|
5
5
|
|
|
6
6
|
from typing import Any, Dict, Literal, Optional, Union, overload
|
|
@@ -21,7 +21,6 @@ from reflex.components.radix.themes.components.dialog import (
|
|
|
21
21
|
from reflex.components.radix.themes.layout import Flex
|
|
22
22
|
from reflex.components.radix.themes.typography.text import Text
|
|
23
23
|
from reflex.constants import Dirs, Hooks, Imports
|
|
24
|
-
from reflex.state import State
|
|
25
24
|
from reflex.utils import imports
|
|
26
25
|
from reflex.vars import Var, VarData
|
|
27
26
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Stub file for reflex/components/core/client_side_routing.py"""
|
|
2
2
|
# ------------------- DO NOT EDIT ----------------------
|
|
3
|
-
# This file was generated by `
|
|
3
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
4
|
# ------------------------------------------------------
|
|
5
5
|
|
|
6
6
|
from typing import Any, Dict, Literal, Optional, Union, overload
|
reflex/components/core/cond.py
CHANGED
|
@@ -206,7 +206,7 @@ def color_mode_cond(light: Any, dark: Any = None) -> Var | Component:
|
|
|
206
206
|
The conditional component or prop.
|
|
207
207
|
"""
|
|
208
208
|
return cond(
|
|
209
|
-
color_mode == LIGHT_COLOR_MODE,
|
|
209
|
+
color_mode == Var.create(LIGHT_COLOR_MODE, _var_is_string=True),
|
|
210
210
|
light,
|
|
211
211
|
dark,
|
|
212
212
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Stub file for reflex/components/core/debounce.py"""
|
|
2
2
|
# ------------------- DO NOT EDIT ----------------------
|
|
3
|
-
# This file was generated by `
|
|
3
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
4
|
# ------------------------------------------------------
|
|
5
5
|
|
|
6
6
|
from typing import Any, Dict, Literal, Optional, Union, overload
|
reflex/components/core/html.pyi
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Stub file for reflex/components/core/html.py"""
|
|
2
2
|
# ------------------- DO NOT EDIT ----------------------
|
|
3
|
-
# This file was generated by `
|
|
3
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
4
|
# ------------------------------------------------------
|
|
5
5
|
|
|
6
6
|
from typing import Any, Dict, Literal, Optional, Union, overload
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Stub file for reflex/components/core/upload.py"""
|
|
2
2
|
# ------------------- DO NOT EDIT ----------------------
|
|
3
|
-
# This file was generated by `
|
|
3
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
4
|
# ------------------------------------------------------
|
|
5
5
|
|
|
6
6
|
from typing import Any, Dict, Literal, Optional, Union, overload
|
|
@@ -387,9 +387,9 @@ class CodeBlock(Component):
|
|
|
387
387
|
merged_imports = imports.merge_imports(
|
|
388
388
|
merged_imports,
|
|
389
389
|
{
|
|
390
|
-
f"react-syntax-highlighter/dist/cjs/styles/prism/{theme}": {
|
|
390
|
+
f"react-syntax-highlighter/dist/cjs/styles/prism/{self.convert_theme_name(theme)}": {
|
|
391
391
|
ImportVar(
|
|
392
|
-
tag=format.to_camel_case(theme),
|
|
392
|
+
tag=format.to_camel_case(self.convert_theme_name(theme)),
|
|
393
393
|
is_default=True,
|
|
394
394
|
install=False,
|
|
395
395
|
)
|
|
@@ -451,13 +451,7 @@ class CodeBlock(Component):
|
|
|
451
451
|
# react-syntax-highlighter doesnt have an explicit "light" or "dark" theme so we use one-light and one-dark
|
|
452
452
|
# themes respectively to ensure code compatibility.
|
|
453
453
|
if "theme" in props and not isinstance(props["theme"], Var):
|
|
454
|
-
props["theme"] = (
|
|
455
|
-
"one-light"
|
|
456
|
-
if props["theme"] == "light"
|
|
457
|
-
else "one-dark"
|
|
458
|
-
if props["theme"] == "dark"
|
|
459
|
-
else props["theme"]
|
|
460
|
-
)
|
|
454
|
+
props["theme"] = cls.convert_theme_name(props["theme"])
|
|
461
455
|
|
|
462
456
|
if can_copy:
|
|
463
457
|
code = children[0]
|
|
@@ -511,3 +505,17 @@ class CodeBlock(Component):
|
|
|
511
505
|
if self.code is not None:
|
|
512
506
|
out.special_props.add(Var.create_safe(f"children={str(self.code)}"))
|
|
513
507
|
return out
|
|
508
|
+
|
|
509
|
+
@staticmethod
|
|
510
|
+
def convert_theme_name(theme) -> str:
|
|
511
|
+
"""Convert theme names to appropriate names.
|
|
512
|
+
|
|
513
|
+
Args:
|
|
514
|
+
theme: The theme name.
|
|
515
|
+
|
|
516
|
+
Returns:
|
|
517
|
+
The right theme name.
|
|
518
|
+
"""
|
|
519
|
+
if theme in ["light", "dark"]:
|
|
520
|
+
return f"one-{theme}"
|
|
521
|
+
return theme
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Stub file for reflex/components/datadisplay/code.py"""
|
|
2
2
|
# ------------------- DO NOT EDIT ----------------------
|
|
3
|
-
# This file was generated by `
|
|
3
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
4
|
# ------------------------------------------------------
|
|
5
5
|
|
|
6
6
|
from typing import Any, Dict, Literal, Optional, Union, overload
|
|
@@ -1110,3 +1110,5 @@ class CodeBlock(Component):
|
|
|
1110
1110
|
The text component.
|
|
1111
1111
|
"""
|
|
1112
1112
|
...
|
|
1113
|
+
@staticmethod
|
|
1114
|
+
def convert_theme_name(theme) -> str: ...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Stub file for reflex/components/datadisplay/dataeditor.py"""
|
|
2
2
|
# ------------------- DO NOT EDIT ----------------------
|
|
3
|
-
# This file was generated by `
|
|
3
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
4
|
# ------------------------------------------------------
|
|
5
5
|
|
|
6
6
|
from typing import Any, Dict, Literal, Optional, Union, overload
|
reflex/components/el/element.pyi
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Stub file for reflex/components/el/element.py"""
|
|
2
2
|
# ------------------- DO NOT EDIT ----------------------
|
|
3
|
-
# This file was generated by `
|
|
3
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
4
|
# ------------------------------------------------------
|
|
5
5
|
|
|
6
6
|
from typing import Any, Dict, Literal, Optional, Union, overload
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Stub file for reflex/components/el/elements/base.py"""
|
|
2
2
|
# ------------------- DO NOT EDIT ----------------------
|
|
3
|
-
# This file was generated by `
|
|
3
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
4
|
# ------------------------------------------------------
|
|
5
5
|
|
|
6
6
|
from typing import Any, Dict, Literal, Optional, Union, overload
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
from hashlib import md5
|
|
5
|
-
from typing import Any, Dict, Iterator, Union
|
|
5
|
+
from typing import Any, Dict, Iterator, Set, Union
|
|
6
6
|
|
|
7
7
|
from jinja2 import Environment
|
|
8
8
|
|
|
@@ -500,6 +500,36 @@ class Select(BaseHTML):
|
|
|
500
500
|
}
|
|
501
501
|
|
|
502
502
|
|
|
503
|
+
AUTO_HEIGHT_JS = """
|
|
504
|
+
const autoHeightOnInput = (e, is_enabled) => {
|
|
505
|
+
if (is_enabled) {
|
|
506
|
+
const el = e.target;
|
|
507
|
+
el.style.overflowY = "hidden";
|
|
508
|
+
el.style.height = "auto";
|
|
509
|
+
el.style.height = (e.target.scrollHeight) + "px";
|
|
510
|
+
if (el.form && !el.form.data_resize_on_reset) {
|
|
511
|
+
el.form.addEventListener("reset", () => window.setTimeout(() => autoHeightOnInput(e, is_enabled), 0))
|
|
512
|
+
el.form.data_resize_on_reset = true;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
"""
|
|
517
|
+
|
|
518
|
+
|
|
519
|
+
ENTER_KEY_SUBMIT_JS = """
|
|
520
|
+
const enterKeySubmitOnKeyDown = (e, is_enabled) => {
|
|
521
|
+
if (is_enabled && e.which === 13 && !e.shiftKey) {
|
|
522
|
+
e.preventDefault();
|
|
523
|
+
if (!e.repeat) {
|
|
524
|
+
if (e.target.form) {
|
|
525
|
+
e.target.form.requestSubmit();
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
"""
|
|
531
|
+
|
|
532
|
+
|
|
503
533
|
class Textarea(BaseHTML):
|
|
504
534
|
"""Display the textarea element."""
|
|
505
535
|
|
|
@@ -511,6 +541,9 @@ class Textarea(BaseHTML):
|
|
|
511
541
|
# Automatically focuses the textarea when the page loads
|
|
512
542
|
auto_focus: Var[Union[str, int, bool]]
|
|
513
543
|
|
|
544
|
+
# Automatically fit the content height to the text (use min-height with this prop)
|
|
545
|
+
auto_height: Var[bool]
|
|
546
|
+
|
|
514
547
|
# Visible width of the text control, in average character widths
|
|
515
548
|
cols: Var[Union[str, int, bool]]
|
|
516
549
|
|
|
@@ -520,6 +553,9 @@ class Textarea(BaseHTML):
|
|
|
520
553
|
# Disables the textarea
|
|
521
554
|
disabled: Var[Union[str, int, bool]]
|
|
522
555
|
|
|
556
|
+
# Enter key submits form (shift-enter adds new line)
|
|
557
|
+
enter_key_submit: Var[bool]
|
|
558
|
+
|
|
523
559
|
# Associates the textarea with a form (by id)
|
|
524
560
|
form: Var[Union[str, int, bool]]
|
|
525
561
|
|
|
@@ -550,6 +586,47 @@ class Textarea(BaseHTML):
|
|
|
550
586
|
# How the text in the textarea is to be wrapped when submitting the form
|
|
551
587
|
wrap: Var[Union[str, int, bool]]
|
|
552
588
|
|
|
589
|
+
def _exclude_props(self) -> list[str]:
|
|
590
|
+
return super()._exclude_props() + [
|
|
591
|
+
"auto_height",
|
|
592
|
+
"enter_key_submit",
|
|
593
|
+
]
|
|
594
|
+
|
|
595
|
+
def get_custom_code(self) -> Set[str]:
|
|
596
|
+
"""Include the custom code for auto_height and enter_key_submit functionality.
|
|
597
|
+
|
|
598
|
+
Returns:
|
|
599
|
+
The custom code for the component.
|
|
600
|
+
"""
|
|
601
|
+
custom_code = super().get_custom_code()
|
|
602
|
+
if self.auto_height is not None:
|
|
603
|
+
custom_code.add(AUTO_HEIGHT_JS)
|
|
604
|
+
if self.enter_key_submit is not None:
|
|
605
|
+
custom_code.add(ENTER_KEY_SUBMIT_JS)
|
|
606
|
+
return custom_code
|
|
607
|
+
|
|
608
|
+
def _render(self) -> Tag:
|
|
609
|
+
tag = super()._render()
|
|
610
|
+
if self.enter_key_submit is not None:
|
|
611
|
+
if "on_key_down" in self.event_triggers:
|
|
612
|
+
raise ValueError(
|
|
613
|
+
"Cannot combine `enter_key_submit` with `on_key_down`.",
|
|
614
|
+
)
|
|
615
|
+
tag.add_props(
|
|
616
|
+
on_key_down=Var.create_safe(
|
|
617
|
+
f"(e) => enterKeySubmitOnKeyDown(e, {self.enter_key_submit._var_name_unwrapped})",
|
|
618
|
+
_var_is_local=False,
|
|
619
|
+
)._replace(merge_var_data=self.enter_key_submit._var_data),
|
|
620
|
+
)
|
|
621
|
+
if self.auto_height is not None:
|
|
622
|
+
tag.add_props(
|
|
623
|
+
on_input=Var.create_safe(
|
|
624
|
+
f"(e) => autoHeightOnInput(e, {self.auto_height._var_name_unwrapped})",
|
|
625
|
+
_var_is_local=False,
|
|
626
|
+
)._replace(merge_var_data=self.auto_height._var_data),
|
|
627
|
+
)
|
|
628
|
+
return tag
|
|
629
|
+
|
|
553
630
|
def get_event_triggers(self) -> Dict[str, Any]:
|
|
554
631
|
"""Get the event triggers that pass the component's value to the handler.
|
|
555
632
|
|