diff --git a/reflex/components/core/debounce.py b/reflex/components/core/debounce.py index e24a6563d..5fabd4486 100644 --- a/reflex/components/core/debounce.py +++ b/reflex/components/core/debounce.py @@ -121,6 +121,8 @@ class DebounceInput(Component): component = super().create(**props) component._get_style = child._get_style component.event_triggers.update(child.event_triggers) + component.children = child.children + component._rename_props = child._rename_props return component def get_event_triggers(self) -> dict[str, Any]: diff --git a/reflex/components/radix/themes/components/text_field.py b/reflex/components/radix/themes/components/text_field.py index 148bddcff..970b950e3 100644 --- a/reflex/components/radix/themes/components/text_field.py +++ b/reflex/components/radix/themes/components/text_field.py @@ -1,11 +1,15 @@ """Interactive components provided by @radix-ui/themes.""" +from __future__ import annotations from typing import Any, Dict, Literal, Union from reflex.components import el +from reflex.components.base.fragment import Fragment from reflex.components.component import Component, ComponentNamespace from reflex.components.core.debounce import DebounceInput from reflex.constants import EventTriggers +from reflex.style import Style, format_as_emotion +from reflex.utils import console from reflex.vars import Var from ..base import ( @@ -79,10 +83,85 @@ class TextFieldRoot(el.Div, RadixThemesComponent): Returns: The component. """ + component = super().create(*children, **props) if props.get("value") is not None and props.get("on_change"): # create a debounced input if the user requests full control to avoid typing jank - return DebounceInput.create(super().create(*children, **props)) - return super().create(*children, **props) + return DebounceInput.create(component) + return component + + @classmethod + def create_root_deprecated(cls, *children, **props) -> Component: + """Create a Fragment component (wrapper for deprecated name). + + Copy the attributes that were previously defined on TextFieldRoot in 0.4.9 to + any child input elements (via custom_attrs). + + Args: + *children: The children of the component. + **props: The properties of the component. + + Returns: + The component. + """ + console.deprecate( + feature_name="rx.input.root", + reason="use rx.input without the .root suffix", + deprecation_version="0.5.0", + removal_version="0.6.0", + ) + inputs = [ + child + for child in children + if isinstance(child, (TextFieldRoot, DebounceInput)) + ] + if not inputs: + # Old-style where no explicit child input was provided + return cls.create(*children, **props) + slots = [child for child in children if isinstance(child, TextFieldSlot)] + carry_props = { + prop: props.pop(prop) + for prop in ["size", "variant", "color_scheme", "radius"] + if prop in props + } + template = cls.create(**props) + for child in inputs: + child.children.extend(slots) + custom_attrs = child.custom_attrs + custom_attrs.update( + { + prop: value + for prop, value in carry_props.items() + if prop not in custom_attrs and getattr(child, prop) is None + } + ) + style = Style(template.style) + style.update(child.style) + child._get_style = lambda style=style: { + "css": Var.create(format_as_emotion(style)) + } + for trigger in template.event_triggers: + if trigger not in child.event_triggers: + child.event_triggers[trigger] = template.event_triggers[trigger] + return Fragment.create(*inputs) + + @classmethod + def create_input_deprecated(cls, *children, **props) -> Component: + """Create a TextFieldRoot component (wrapper for deprecated name). + + Args: + *children: The children of the component. + **props: The properties of the component. + + Returns: + The component. + """ + console.deprecate( + feature_name="rx.input.input", + reason="use rx.input without the .input suffix", + deprecation_version="0.5.0", + removal_version="0.6.0", + ) + return cls.create(*children, **props) def get_event_triggers(self) -> Dict[str, Any]: """Get the event triggers that pass the component's value to the handler. @@ -112,7 +191,8 @@ class TextFieldSlot(RadixThemesComponent): class TextField(ComponentNamespace): """TextField components namespace.""" - root = staticmethod(TextFieldRoot.create) + root = staticmethod(TextFieldRoot.create_root_deprecated) + input = staticmethod(TextFieldRoot.create_input_deprecated) slot = staticmethod(TextFieldSlot.create) __call__ = staticmethod(TextFieldRoot.create) diff --git a/reflex/components/radix/themes/components/text_field.pyi b/reflex/components/radix/themes/components/text_field.pyi index 7811d2bba..c14fb031a 100644 --- a/reflex/components/radix/themes/components/text_field.pyi +++ b/reflex/components/radix/themes/components/text_field.pyi @@ -9,9 +9,12 @@ from reflex.event import EventChain, EventHandler, EventSpec from reflex.style import Style from typing import Any, Dict, Literal, Union from reflex.components import el +from reflex.components.base.fragment import Fragment from reflex.components.component import Component, ComponentNamespace from reflex.components.core.debounce import DebounceInput from reflex.constants import EventTriggers +from reflex.style import Style, format_as_emotion +from reflex.utils import console from reflex.vars import Var from ..base import LiteralAccentColor, LiteralRadius, RadixThemesComponent @@ -263,6 +266,10 @@ class TextFieldRoot(el.Div, RadixThemesComponent): The component. """ ... + @classmethod + def create_root_deprecated(cls, *children, **props) -> Component: ... + @classmethod + def create_input_deprecated(cls, *children, **props) -> Component: ... def get_event_triggers(self) -> Dict[str, Any]: ... class TextFieldSlot(RadixThemesComponent): @@ -408,7 +415,8 @@ class TextFieldSlot(RadixThemesComponent): ... class TextField(ComponentNamespace): - root = staticmethod(TextFieldRoot.create) + root = staticmethod(TextFieldRoot.create_root_deprecated) + input = staticmethod(TextFieldRoot.create_input_deprecated) slot = staticmethod(TextFieldSlot.create) @staticmethod