Przeglądaj źródła

Merge remote-tracking branch 'origin/main' into reflex-0.4.0

Masen Furer 1 rok temu
rodzic
commit
c124650082

+ 6 - 1
reflex/compiler/compiler.py

@@ -460,7 +460,12 @@ def remove_tailwind_from_postcss() -> tuple[str, str]:
 
 
 
 
 def purge_web_pages_dir():
 def purge_web_pages_dir():
-    """Empty out .web directory."""
+    """Empty out .web/pages directory."""
+    if _is_dev_mode() and os.environ.get("REFLEX_PERSIST_WEB_DIR"):
+        # Skip purging the web directory in dev mode if REFLEX_PERSIST_WEB_DIR is set.
+        return
+
+    # Empty out the web pages directory.
     utils.empty_dir(constants.Dirs.WEB_PAGES, keep_files=["_app.js"])
     utils.empty_dir(constants.Dirs.WEB_PAGES, keep_files=["_app.js"])
 
 
 
 

+ 0 - 49
reflex/components/chakra/base.py

@@ -15,7 +15,6 @@ class ChakraComponent(Component):
     library = "@chakra-ui/react@2.6.1"
     library = "@chakra-ui/react@2.6.1"
     lib_dependencies: List[str] = [
     lib_dependencies: List[str] = [
         "@chakra-ui/system@2.5.7",
         "@chakra-ui/system@2.5.7",
-        "focus-visible@5.2.0",
         "framer-motion@10.16.4",
         "framer-motion@10.16.4",
     ]
     ]
 
 
@@ -26,25 +25,6 @@ class ChakraComponent(Component):
             (60, "ChakraProvider"): chakra_provider,
             (60, "ChakraProvider"): chakra_provider,
         }
         }
 
 
-    def get_imports(self) -> imports.ImportDict:
-        """Chakra requires focus-visible and imported into each page.
-
-        This allows the GlobalStyle defined by the ChakraProvider to hide the blue border.
-
-        Returns:
-            The imports for the component.
-        """
-        return imports.merge_imports(
-            super().get_imports(),
-            {
-                "": {
-                    imports.ImportVar(
-                        tag="focus-visible/dist/focus-visible", install=False
-                    )
-                }
-            },
-        )
-
     def _get_style(self) -> dict:
     def _get_style(self) -> dict:
         """Get the style for the component.
         """Get the style for the component.
 
 
@@ -65,25 +45,11 @@ class ChakraComponent(Component):
             dep: [imports.ImportVar(tag=None, render=False)]
             dep: [imports.ImportVar(tag=None, render=False)]
             for dep in [
             for dep in [
                 "@chakra-ui/system@2.5.7",
                 "@chakra-ui/system@2.5.7",
-                "focus-visible@5.2.0",
                 "framer-motion@10.16.4",
                 "framer-motion@10.16.4",
             ]
             ]
         }
         }
 
 
 
 
-class Global(Component):
-    """The emotion/react Global styling component."""
-
-    library = "@emotion/react@^11.11.0"
-    lib_dependencies: List[str] = [
-        "@emotion/styled@^11.11.0",
-    ]
-
-    tag = "Global"
-
-    styles: Var[str]
-
-
 class ChakraProvider(ChakraComponent):
 class ChakraProvider(ChakraComponent):
     """Top level Chakra provider must be included in any app using chakra components."""
     """Top level Chakra provider must be included in any app using chakra components."""
 
 
@@ -99,7 +65,6 @@ class ChakraProvider(ChakraComponent):
             A new ChakraProvider component.
             A new ChakraProvider component.
         """
         """
         return super().create(
         return super().create(
-            Global.create(styles=Var.create("GlobalStyles", _var_is_local=False)),
             theme=Var.create("extendTheme(theme)", _var_is_local=False),
             theme=Var.create("extendTheme(theme)", _var_is_local=False),
         )
         )
 
 
@@ -111,22 +76,8 @@ class ChakraProvider(ChakraComponent):
         _imports.setdefault("/utils/theme.js", []).append(
         _imports.setdefault("/utils/theme.js", []).append(
             imports.ImportVar(tag="theme", is_default=True),
             imports.ImportVar(tag="theme", is_default=True),
         )
         )
-        _imports.setdefault(Global.__fields__["library"].default, []).append(
-            imports.ImportVar(tag="css", is_default=False),
-        )
         return _imports
         return _imports
 
 
-    def _get_custom_code(self) -> str | None:
-        return """
-const GlobalStyles = css`
-  /* Hide the blue border around Chakra components. */
-  .js-focus-visible :focus:not([data-focus-visible-added]) {
-    outline: none;
-    box-shadow: none;
-  }
-`;
-"""
-
     @staticmethod
     @staticmethod
     @lru_cache(maxsize=None)
     @lru_cache(maxsize=None)
     def _get_app_wrap_components() -> dict[tuple[int, str], Component]:
     def _get_app_wrap_components() -> dict[tuple[int, str], Component]:

+ 0 - 83
reflex/components/chakra/base.pyi

@@ -14,7 +14,6 @@ from reflex.utils import imports
 from reflex.vars import Var
 from reflex.vars import Var
 
 
 class ChakraComponent(Component):
 class ChakraComponent(Component):
-    def get_imports(self) -> imports.ImportDict: ...
     @overload
     @overload
     @classmethod
     @classmethod
     def create(  # type: ignore
     def create(  # type: ignore
@@ -95,88 +94,6 @@ class ChakraComponent(Component):
         """
         """
         ...
         ...
 
 
-class Global(Component):
-    @overload
-    @classmethod
-    def create(  # type: ignore
-        cls,
-        *children,
-        styles: Optional[Union[Var[str], str]] = None,
-        style: Optional[Style] = None,
-        key: Optional[Any] = None,
-        id: Optional[Any] = None,
-        class_name: Optional[Any] = None,
-        autofocus: Optional[bool] = None,
-        _rename_props: Optional[Dict[str, str]] = None,
-        custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
-        on_blur: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_click: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_context_menu: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_double_click: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_focus: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mount: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_down: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_enter: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_leave: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_move: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_out: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_over: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_mouse_up: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_scroll: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        on_unmount: Optional[
-            Union[EventHandler, EventSpec, list, function, BaseVar]
-        ] = None,
-        **props
-    ) -> "Global":
-        """Create the component.
-
-        Args:
-            *children: The children of the component.
-            style: The style of the component.
-            key: A unique key for the component.
-            id: The id for the component.
-            class_name: The class name for the component.
-            autofocus: Whether the component should take the focus once the page is loaded
-            _rename_props: props to change the name of
-            custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
-
-        Raises:
-            TypeError: If an invalid child is passed.
-        """
-        ...
-
 class ChakraProvider(ChakraComponent):
 class ChakraProvider(ChakraComponent):
     @overload
     @overload
     @classmethod
     @classmethod

+ 2 - 8
reflex/components/chakra/forms/input.py

@@ -91,15 +91,9 @@ class Input(ChakraComponent):
         Returns:
         Returns:
             The component.
             The component.
         """
         """
-        if (
-            isinstance(props.get("value"), Var) and props.get("on_change")
-        ) or "debounce_timeout" in props:
-            # Currently default to 50ms, which appears to be a good balance
-            debounce_timeout = props.pop("debounce_timeout", 50)
+        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
             # create a debounced input if the user requests full control to avoid typing jank
-            return DebounceInput.create(
-                super().create(*children, **props), debounce_timeout=debounce_timeout
-            )
+            return DebounceInput.create(super().create(*children, **props))
         return super().create(*children, **props)
         return super().create(*children, **props)
 
 
 
 

+ 2 - 8
reflex/components/chakra/forms/textarea.py

@@ -74,13 +74,7 @@ class TextArea(ChakraComponent):
         Returns:
         Returns:
             The component.
             The component.
         """
         """
-        if (
-            isinstance(props.get("value"), Var) and props.get("on_change")
-        ) or "debounce_timeout" in props:
-            # Currently default to 50ms, which appears to be a good balance
-            debounce_timeout = props.pop("debounce_timeout", 50)
+        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
             # create a debounced input if the user requests full control to avoid typing jank
-            return DebounceInput.create(
-                super().create(*children, **props), debounce_timeout=debounce_timeout
-            )
+            return DebounceInput.create(super().create(*children, **props))
         return super().create(*children, **props)
         return super().create(*children, **props)

+ 3 - 1
reflex/components/core/debounce.py

@@ -7,6 +7,8 @@ from reflex.components.component import Component
 from reflex.constants import EventTriggers
 from reflex.constants import EventTriggers
 from reflex.vars import Var, VarData
 from reflex.vars import Var, VarData
 
 
+DEFAULT_DEBOUNCE_TIMEOUT = 300
+
 
 
 class DebounceInput(Component):
 class DebounceInput(Component):
     """The DebounceInput component is used to buffer input events on the client side.
     """The DebounceInput component is used to buffer input events on the client side.
@@ -23,7 +25,7 @@ class DebounceInput(Component):
     min_length: Var[int]
     min_length: Var[int]
 
 
     # Time to wait between end of input and triggering on_change
     # Time to wait between end of input and triggering on_change
-    debounce_timeout: Var[int]
+    debounce_timeout: Var[int] = DEFAULT_DEBOUNCE_TIMEOUT  # type: ignore
 
 
     # If true, notify when Enter key is pressed
     # If true, notify when Enter key is pressed
     force_notify_by_enter: Var[bool]
     force_notify_by_enter: Var[bool]

+ 2 - 0
reflex/components/core/debounce.pyi

@@ -12,6 +12,8 @@ from reflex.components.component import Component
 from reflex.constants import EventTriggers
 from reflex.constants import EventTriggers
 from reflex.vars import Var, VarData
 from reflex.vars import Var, VarData
 
 
+DEFAULT_DEBOUNCE_TIMEOUT = 300
+
 class DebounceInput(Component):
 class DebounceInput(Component):
     @overload
     @overload
     @classmethod
     @classmethod

+ 11 - 1
reflex/components/radix/primitives/accordion.py

@@ -3,7 +3,7 @@
 from __future__ import annotations
 from __future__ import annotations
 
 
 from types import SimpleNamespace
 from types import SimpleNamespace
-from typing import Any, Dict, Literal
+from typing import Any, Dict, List, Literal
 
 
 from reflex.components.component import Component
 from reflex.components.component import Component
 from reflex.components.core import match
 from reflex.components.core import match
@@ -344,6 +344,8 @@ class AccordionRoot(AccordionComponent):
     # The var_data associated with the component.
     # The var_data associated with the component.
     _var_data: VarData = VarData()  # type: ignore
     _var_data: VarData = VarData()  # type: ignore
 
 
+    _valid_children: List[str] = ["AccordionItem"]
+
     @classmethod
     @classmethod
     def create(cls, *children, **props) -> Component:
     def create(cls, *children, **props) -> Component:
         """Create the Accordion root component.
         """Create the Accordion root component.
@@ -451,6 +453,14 @@ class AccordionItem(AccordionComponent):
     # When true, prevents the user from interacting with the item.
     # When true, prevents the user from interacting with the item.
     disabled: Var[bool]
     disabled: Var[bool]
 
 
+    _valid_children: List[str] = [
+        "AccordionHeader",
+        "AccordionTrigger",
+        "AccordionContent",
+    ]
+
+    _valid_parents: List[str] = ["AccordionRoot"]
+
     def _apply_theme(self, theme: Component):
     def _apply_theme(self, theme: Component):
         self.style = Style(
         self.style = Style(
             {
             {

+ 1 - 1
reflex/components/radix/primitives/accordion.pyi

@@ -8,7 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
 from reflex.style import Style
 from types import SimpleNamespace
 from types import SimpleNamespace
-from typing import Any, Dict, Literal
+from typing import Any, Dict, List, Literal
 from reflex.components.component import Component
 from reflex.components.component import Component
 from reflex.components.core import match
 from reflex.components.core import match
 from reflex.components.lucide.icon import Icon
 from reflex.components.lucide.icon import Icon

+ 14 - 2
reflex/components/radix/themes/components/contextmenu.py

@@ -1,6 +1,6 @@
 """Interactive components provided by @radix-ui/themes."""
 """Interactive components provided by @radix-ui/themes."""
 from types import SimpleNamespace
 from types import SimpleNamespace
-from typing import Any, Dict, Literal
+from typing import Any, Dict, List, Literal
 
 
 from reflex.constants import EventTriggers
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from reflex.vars import Var
@@ -19,6 +19,8 @@ class ContextMenuRoot(RadixThemesComponent):
     # The modality of the context menu. When set to true, interaction with outside elements will be disabled and only menu content will be visible to screen readers.
     # The modality of the context menu. When set to true, interaction with outside elements will be disabled and only menu content will be visible to screen readers.
     modal: Var[bool]
     modal: Var[bool]
 
 
+    _invalid_children: List[str] = ["ContextMenuItem"]
+
     def get_event_triggers(self) -> Dict[str, Any]:
     def get_event_triggers(self) -> Dict[str, Any]:
         """Get the events triggers signatures for the component.
         """Get the events triggers signatures for the component.
 
 
@@ -39,6 +41,10 @@ class ContextMenuTrigger(RadixThemesComponent):
     # Whether the trigger is disabled
     # Whether the trigger is disabled
     disabled: Var[bool]
     disabled: Var[bool]
 
 
+    _valid_parents: List[str] = ["ContextMenuRoot"]
+
+    _invalid_children: List[str] = ["ContextMenuContent"]
+
 
 
 class ContextMenuContent(RadixThemesComponent):
 class ContextMenuContent(RadixThemesComponent):
     """Trigger an action or event, such as submitting a form or displaying a dialog."""
     """Trigger an action or event, such as submitting a form or displaying a dialog."""
@@ -60,7 +66,7 @@ class ContextMenuContent(RadixThemesComponent):
     # The vertical distance in pixels from the anchor.
     # The vertical distance in pixels from the anchor.
     align_offset: Var[int]
     align_offset: Var[int]
 
 
-    # When true, overrides the side andalign preferences to prevent collisions with boundary edges.
+    # When true, overrides the side and aligns preferences to prevent collisions with boundary edges.
     avoid_collisions: Var[bool]
     avoid_collisions: Var[bool]
 
 
     def get_event_triggers(self) -> Dict[str, Any]:
     def get_event_triggers(self) -> Dict[str, Any]:
@@ -93,6 +99,8 @@ class ContextMenuSubTrigger(RadixThemesComponent):
     # Whether the trigger is disabled
     # Whether the trigger is disabled
     disabled: Var[bool]
     disabled: Var[bool]
 
 
+    _valid_parents: List[str] = ["ContextMenuContent", "ContextMenuSub"]
+
 
 
 class ContextMenuSubContent(RadixThemesComponent):
 class ContextMenuSubContent(RadixThemesComponent):
     """Trigger an action or event, such as submitting a form or displaying a dialog."""
     """Trigger an action or event, such as submitting a form or displaying a dialog."""
@@ -102,6 +110,8 @@ class ContextMenuSubContent(RadixThemesComponent):
     # When true, keyboard navigation will loop from last item to first, and vice versa.
     # When true, keyboard navigation will loop from last item to first, and vice versa.
     loop: Var[bool]
     loop: Var[bool]
 
 
+    _valid_parents: List[str] = ["ContextMenuSub"]
+
     def get_event_triggers(self) -> Dict[str, Any]:
     def get_event_triggers(self) -> Dict[str, Any]:
         """Get the events triggers signatures for the component.
         """Get the events triggers signatures for the component.
 
 
@@ -128,6 +138,8 @@ class ContextMenuItem(RadixThemesComponent):
     # Shortcut to render a menu item as a link
     # Shortcut to render a menu item as a link
     shortcut: Var[str]
     shortcut: Var[str]
 
 
+    _valid_parents: List[str] = ["ContextMenuContent", "ContextMenuSubContent"]
+
 
 
 class ContextMenuSeparator(RadixThemesComponent):
 class ContextMenuSeparator(RadixThemesComponent):
     """Trigger an action or event, such as submitting a form or displaying a dialog."""
     """Trigger an action or event, such as submitting a form or displaying a dialog."""

+ 2 - 2
reflex/components/radix/themes/components/contextmenu.pyi

@@ -8,7 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
 from reflex.style import Style
 from types import SimpleNamespace
 from types import SimpleNamespace
-from typing import Any, Dict, Literal
+from typing import Any, Dict, List, Literal
 from reflex.constants import EventTriggers
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from reflex.vars import Var
 from ..base import LiteralAccentColor, RadixThemesComponent
 from ..base import LiteralAccentColor, RadixThemesComponent
@@ -472,7 +472,7 @@ class ContextMenuContent(RadixThemesComponent):
             variant: Variant of button: "solid" | "soft" | "outline" | "ghost"
             variant: Variant of button: "solid" | "soft" | "outline" | "ghost"
             high_contrast: Whether to render the button with higher contrast color against background
             high_contrast: Whether to render the button with higher contrast color against background
             align_offset: The vertical distance in pixels from the anchor.
             align_offset: The vertical distance in pixels from the anchor.
-            avoid_collisions: When true, overrides the side andalign preferences to prevent collisions with boundary edges.
+            avoid_collisions: When true, overrides the side and aligns preferences to prevent collisions with boundary edges.
             style: The style of the component.
             style: The style of the component.
             key: A unique key for the component.
             key: A unique key for the component.
             id: The id for the component.
             id: The id for the component.

+ 13 - 1
reflex/components/radix/themes/components/dropdownmenu.py

@@ -1,6 +1,6 @@
 """Interactive components provided by @radix-ui/themes."""
 """Interactive components provided by @radix-ui/themes."""
 from types import SimpleNamespace
 from types import SimpleNamespace
-from typing import Any, Dict, Literal, Union
+from typing import Any, Dict, List, Literal, Union
 
 
 from reflex.constants import EventTriggers
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from reflex.vars import Var
@@ -44,6 +44,8 @@ class DropdownMenuRoot(RadixThemesComponent):
     # The reading direction of submenus when applicable. If omitted, inherits globally from DirectionProvider or assumes LTR (left-to-right) reading mode.
     # The reading direction of submenus when applicable. If omitted, inherits globally from DirectionProvider or assumes LTR (left-to-right) reading mode.
     dir: Var[LiteralDirType]
     dir: Var[LiteralDirType]
 
 
+    _invalid_children: List[str] = ["DropdownMenuItem"]
+
     def get_event_triggers(self) -> Dict[str, Any]:
     def get_event_triggers(self) -> Dict[str, Any]:
         """Get the events triggers signatures for the component.
         """Get the events triggers signatures for the component.
 
 
@@ -64,6 +66,10 @@ class DropdownMenuTrigger(RadixThemesComponent):
     # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.
     # Change the default rendered element for the one passed as a child, merging their props and behavior. Defaults to False.
     as_child: Var[bool]
     as_child: Var[bool]
 
 
+    _valid_parents: List[str] = ["DropdownMenuRoot"]
+
+    _invalid_children: List[str] = ["DropdownMenuContent"]
+
 
 
 class DropdownMenuContent(RadixThemesComponent):
 class DropdownMenuContent(RadixThemesComponent):
     """The Dropdown Menu Content component that pops out when the dropdown menu is open."""
     """The Dropdown Menu Content component that pops out when the dropdown menu is open."""
@@ -148,6 +154,8 @@ class DropdownMenuSubTrigger(RadixThemesComponent):
     # Optional text used for typeahead purposes. By default the typeahead behavior will use the .textContent of the item. Use this when the content is complex, or you have non-textual content inside.
     # Optional text used for typeahead purposes. By default the typeahead behavior will use the .textContent of the item. Use this when the content is complex, or you have non-textual content inside.
     text_value: Var[str]
     text_value: Var[str]
 
 
+    _valid_parents: List[str] = ["DropdownMenuContent", "DropdownMenuSub"]
+
 
 
 class DropdownMenuSub(RadixThemesComponent):
 class DropdownMenuSub(RadixThemesComponent):
     """Contains all the parts of a submenu."""
     """Contains all the parts of a submenu."""
@@ -219,6 +227,8 @@ class DropdownMenuSubContent(RadixThemesComponent):
     # Whether to hide the content when the trigger becomes fully occluded. Defaults to False.
     # Whether to hide the content when the trigger becomes fully occluded. Defaults to False.
     hide_when_detached: Var[bool]
     hide_when_detached: Var[bool]
 
 
+    _valid_parents: List[str] = ["DropdownMenuSub"]
+
     def get_event_triggers(self) -> Dict[str, Any]:
     def get_event_triggers(self) -> Dict[str, Any]:
         """Get the events triggers signatures for the component.
         """Get the events triggers signatures for the component.
 
 
@@ -254,6 +264,8 @@ class DropdownMenuItem(RadixThemesComponent):
     # Optional text used for typeahead purposes. By default the typeahead behavior will use the .textContent of the item. Use this when the content is complex, or you have non-textual content inside.
     # Optional text used for typeahead purposes. By default the typeahead behavior will use the .textContent of the item. Use this when the content is complex, or you have non-textual content inside.
     text_value: Var[str]
     text_value: Var[str]
 
 
+    _valid_parents: List[str] = ["DropdownMenuContent", "DropdownMenuSubContent"]
+
     def get_event_triggers(self) -> Dict[str, Any]:
     def get_event_triggers(self) -> Dict[str, Any]:
         """Get the events triggers signatures for the component.
         """Get the events triggers signatures for the component.
 
 

+ 1 - 1
reflex/components/radix/themes/components/dropdownmenu.pyi

@@ -8,7 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
 from reflex.style import Style
 from types import SimpleNamespace
 from types import SimpleNamespace
-from typing import Any, Dict, Literal, Union
+from typing import Any, Dict, List, Literal, Union
 from reflex.constants import EventTriggers
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from reflex.vars import Var
 from ..base import LiteralAccentColor, RadixThemesComponent
 from ..base import LiteralAccentColor, RadixThemesComponent

+ 8 - 0
reflex/components/radix/themes/components/select.py

@@ -78,6 +78,8 @@ class SelectTrigger(RadixThemesComponent):
     # The placeholder of the select trigger
     # The placeholder of the select trigger
     placeholder: Var[str]
     placeholder: Var[str]
 
 
+    _valid_parents: List[str] = ["SelectRoot"]
+
 
 
 class SelectContent(RadixThemesComponent):
 class SelectContent(RadixThemesComponent):
     """The component that pops out when the select is open."""
     """The component that pops out when the select is open."""
@@ -127,6 +129,8 @@ class SelectGroup(RadixThemesComponent):
 
 
     tag = "Select.Group"
     tag = "Select.Group"
 
 
+    _valid_parents: List[str] = ["SelectContent"]
+
 
 
 class SelectItem(RadixThemesComponent):
 class SelectItem(RadixThemesComponent):
     """The component that contains the select items."""
     """The component that contains the select items."""
@@ -139,12 +143,16 @@ class SelectItem(RadixThemesComponent):
     # Whether the select item is disabled
     # Whether the select item is disabled
     disabled: Var[bool]
     disabled: Var[bool]
 
 
+    _valid_parents: List[str] = ["SelectGroup", "SelectContent"]
+
 
 
 class SelectLabel(RadixThemesComponent):
 class SelectLabel(RadixThemesComponent):
     """Used to render the label of a group, it isn't focusable using arrow keys."""
     """Used to render the label of a group, it isn't focusable using arrow keys."""
 
 
     tag = "Select.Label"
     tag = "Select.Label"
 
 
+    _valid_parents: List[str] = ["SelectGroup"]
+
 
 
 class SelectSeparator(RadixThemesComponent):
 class SelectSeparator(RadixThemesComponent):
     """Used to visually separate items in the Select."""
     """Used to visually separate items in the Select."""

+ 38 - 3
reflex/components/radix/themes/components/slider.py

@@ -1,6 +1,7 @@
 """Interactive components provided by @radix-ui/themes."""
 """Interactive components provided by @radix-ui/themes."""
-from typing import Any, Dict, List, Literal, Union
+from typing import Any, Dict, List, Literal, Optional, Union
 
 
+from reflex.components.component import Component
 from reflex.constants import EventTriggers
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from reflex.vars import Var
 
 
@@ -35,7 +36,7 @@ class Slider(RadixThemesComponent):
     radius: Var[LiteralRadius]
     radius: Var[LiteralRadius]
 
 
     # The value of the slider when initially rendered. Use when you do not need to control the state of the slider.
     # The value of the slider when initially rendered. Use when you do not need to control the state of the slider.
-    default_value: Var[List[Union[float, int]]]
+    default_value: Var[Union[List[Union[float, int]], float, int]]
 
 
     # The controlled value of the slider. Must be used in conjunction with onValueChange.
     # The controlled value of the slider. Must be used in conjunction with onValueChange.
     value: Var[List[Union[float, int]]]
     value: Var[List[Union[float, int]]]
@@ -73,5 +74,39 @@ class Slider(RadixThemesComponent):
             EventTriggers.ON_VALUE_COMMIT: lambda e0: [e0],
             EventTriggers.ON_VALUE_COMMIT: lambda e0: [e0],
         }
         }
 
 
+    @classmethod
+    def create(
+        cls,
+        *children,
+        width: Optional[str] = "100%",
+        **props,
+    ) -> Component:
+        """Create a Slider component.
 
 
-slider = Slider.create
+        Args:
+            *children: The children of the component.
+            width: The width of the slider.
+            **props: The properties of the component.
+
+        Returns:
+            The component.
+        """
+        default_value = props.pop("default_value", [50])
+
+        if isinstance(default_value, Var):
+            if issubclass(default_value._var_type, (int, float)):
+                default_value = [default_value]
+
+        elif isinstance(default_value, (int, float)):
+            default_value = [default_value]
+
+        style = props.setdefault("style", {})
+        style.update(
+            {
+                "width": width,
+            }
+        )
+        return super().create(*children, default_value=default_value, **props)
+
+
+slider = Slider.create

+ 23 - 22
reflex/components/radix/themes/components/slider.pyi

@@ -7,7 +7,8 @@ from typing import Any, Dict, Literal, Optional, Union, overload
 from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
 from reflex.style import Style
-from typing import Any, Dict, List, Literal, Union
+from typing import Any, Dict, List, Literal, Optional, Union
+from reflex.components.component import Component
 from reflex.constants import EventTriggers
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from reflex.vars import Var
 from ..base import LiteralAccentColor, LiteralRadius, RadixThemesComponent
 from ..base import LiteralAccentColor, LiteralRadius, RadixThemesComponent
@@ -19,7 +20,17 @@ class Slider(RadixThemesComponent):
     def create(  # type: ignore
     def create(  # type: ignore
         cls,
         cls,
         *children,
         *children,
-        color: Optional[Union[Var[str], str]] = None,
+        width: Optional[str] = "100%",
+        as_child: Optional[Union[Var[bool], bool]] = None,
+        size: Optional[
+            Union[Var[Literal["1", "2", "3"]], Literal["1", "2", "3"]]
+        ] = None,
+        variant: Optional[
+            Union[
+                Var[Literal["classic", "surface", "soft"]],
+                Literal["classic", "surface", "soft"],
+            ]
+        ] = None,
         color_scheme: Optional[
         color_scheme: Optional[
             Union[
             Union[
                 Var[
                 Var[
@@ -82,16 +93,6 @@ class Slider(RadixThemesComponent):
                 ],
                 ],
             ]
             ]
         ] = None,
         ] = None,
-        as_child: Optional[Union[Var[bool], bool]] = None,
-        size: Optional[
-            Union[Var[Literal["1", "2", "3"]], Literal["1", "2", "3"]]
-        ] = None,
-        variant: Optional[
-            Union[
-                Var[Literal["classic", "surface", "soft"]],
-                Literal["classic", "surface", "soft"],
-            ]
-        ] = None,
         high_contrast: Optional[Union[Var[bool], bool]] = None,
         high_contrast: Optional[Union[Var[bool], bool]] = None,
         radius: Optional[
         radius: Optional[
             Union[
             Union[
@@ -100,7 +101,10 @@ class Slider(RadixThemesComponent):
             ]
             ]
         ] = None,
         ] = None,
         default_value: Optional[
         default_value: Optional[
-            Union[Var[List[Union[float, int]]], List[Union[float, int]]]
+            Union[
+                Var[Union[List[Union[float, int]], float, int]],
+                Union[List[Union[float, int]], float, int],
+            ]
         ] = None,
         ] = None,
         value: Optional[
         value: Optional[
             Union[Var[List[Union[float, int]]], List[Union[float, int]]]
             Union[Var[List[Union[float, int]]], List[Union[float, int]]]
@@ -176,18 +180,15 @@ class Slider(RadixThemesComponent):
         ] = None,
         ] = None,
         **props
         **props
     ) -> "Slider":
     ) -> "Slider":
-        """Create a new component instance.
-
-        Will prepend "RadixThemes" to the component tag to avoid conflicts with
-        other UI libraries for common names, like Text and Button.
+        """Create a Slider component.
 
 
         Args:
         Args:
-            *children: Child components.
-            color: map to CSS default color property.
-            color_scheme: map to radix color property.
+            *children: The children of the component.
+            width: The width of the slider.
             as_child: Change the default rendered element for the one passed as a child, merging their props and behavior.
             as_child: Change the default rendered element for the one passed as a child, merging their props and behavior.
             size: Button size "1" - "3"
             size: Button size "1" - "3"
             variant: Variant of button
             variant: Variant of button
+            color_scheme: Override theme color for button
             high_contrast: Whether to render the button with higher contrast color against background
             high_contrast: Whether to render the button with higher contrast color against background
             radius: Override theme radius for button: "none" | "small" | "medium" | "large" | "full"
             radius: Override theme radius for button: "none" | "small" | "medium" | "large" | "full"
             default_value: The value of the slider when initially rendered. Use when you do not need to control the state of the slider.
             default_value: The value of the slider when initially rendered. Use when you do not need to control the state of the slider.
@@ -205,10 +206,10 @@ class Slider(RadixThemesComponent):
             autofocus: Whether the component should take the focus once the page is loaded
             autofocus: Whether the component should take the focus once the page is loaded
             _rename_props: props to change the name of
             _rename_props: props to change the name of
             custom_attrs: custom attribute
             custom_attrs: custom attribute
-            **props: Component properties.
+            **props: The properties of the component.
 
 
         Returns:
         Returns:
-            A new component instance.
+            The component.
         """
         """
         ...
         ...
 
 

+ 42 - 1
reflex/components/radix/themes/components/table.py

@@ -1,6 +1,6 @@
 """Interactive components provided by @radix-ui/themes."""
 """Interactive components provided by @radix-ui/themes."""
 from types import SimpleNamespace
 from types import SimpleNamespace
-from typing import Literal, Union
+from typing import List, Literal, Union
 
 
 from reflex import el
 from reflex import el
 from reflex.vars import Var
 from reflex.vars import Var
@@ -27,6 +27,10 @@ class TableHeader(el.Thead, RadixThemesComponent):
 
 
     tag = "Table.Header"
     tag = "Table.Header"
 
 
+    _invalid_children: List[str] = ["TableBody"]
+
+    _valid_parents: List[str] = ["TableRoot"]
+
 
 
 class TableRow(el.Tr, RadixThemesComponent):
 class TableRow(el.Tr, RadixThemesComponent):
     """A row containing table cells."""
     """A row containing table cells."""
@@ -36,6 +40,8 @@ class TableRow(el.Tr, RadixThemesComponent):
     # The alignment of the row
     # The alignment of the row
     align: Var[Literal["start", "center", "end", "baseline"]]
     align: Var[Literal["start", "center", "end", "baseline"]]
 
 
+    _invalid_children: List[str] = ["TableBody", "TableHeader", "TableRow"]
+
 
 
 class TableColumnHeaderCell(el.Th, RadixThemesComponent):
 class TableColumnHeaderCell(el.Th, RadixThemesComponent):
     """A table cell that is semantically treated as a column header."""
     """A table cell that is semantically treated as a column header."""
@@ -48,12 +54,30 @@ class TableColumnHeaderCell(el.Th, RadixThemesComponent):
     # width of the column
     # width of the column
     width: Var[Union[str, int]]
     width: Var[Union[str, int]]
 
 
+    _invalid_children: List[str] = [
+        "TableBody",
+        "TableHeader",
+        "TableRow",
+        "TableCell",
+        "TableColumnHeaderCell",
+        "TableRowHeaderCell",
+    ]
+
 
 
 class TableBody(el.Tbody, RadixThemesComponent):
 class TableBody(el.Tbody, RadixThemesComponent):
     """The body of the table contains the data rows."""
     """The body of the table contains the data rows."""
 
 
     tag = "Table.Body"
     tag = "Table.Body"
 
 
+    _invalid_children: List[str] = [
+        "TableHeader",
+        "TableRowHeaderCell",
+        "TableColumnHeaderCell",
+        "TableCell",
+    ]
+
+    _valid_parents: List[str] = ["TableRoot"]
+
 
 
 class TableCell(el.Td, RadixThemesComponent):
 class TableCell(el.Td, RadixThemesComponent):
     """A cell containing data."""
     """A cell containing data."""
@@ -66,6 +90,14 @@ class TableCell(el.Td, RadixThemesComponent):
     # width of the column
     # width of the column
     width: Var[Union[str, int]]
     width: Var[Union[str, int]]
 
 
+    _invalid_children: List[str] = [
+        "TableBody",
+        "TableHeader",
+        "TableRowHeaderCell",
+        "TableColumnHeaderCell",
+        "TableCell",
+    ]
+
 
 
 class TableRowHeaderCell(el.Th, RadixThemesComponent):
 class TableRowHeaderCell(el.Th, RadixThemesComponent):
     """A table cell that is semantically treated as a row header."""
     """A table cell that is semantically treated as a row header."""
@@ -78,6 +110,15 @@ class TableRowHeaderCell(el.Th, RadixThemesComponent):
     # width of the column
     # width of the column
     width: Var[Union[str, int]]
     width: Var[Union[str, int]]
 
 
+    _invalid_children: List[str] = [
+        "TableBody",
+        "TableHeader",
+        "TableRow",
+        "TableCell",
+        "TableColumnHeaderCell",
+        "TableRowHeaderCell",
+    ]
+
 
 
 class Table(SimpleNamespace):
 class Table(SimpleNamespace):
     """Table components namespace."""
     """Table components namespace."""

+ 1 - 1
reflex/components/radix/themes/components/table.pyi

@@ -8,7 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
 from reflex.style import Style
 from types import SimpleNamespace
 from types import SimpleNamespace
-from typing import Literal, Union
+from typing import List, Literal, Union
 from reflex import el
 from reflex import el
 from reflex.vars import Var
 from reflex.vars import Var
 from ..base import RadixThemesComponent
 from ..base import RadixThemesComponent

+ 3 - 1
reflex/components/radix/themes/components/tabs.py

@@ -1,6 +1,6 @@
 """Interactive components provided by @radix-ui/themes."""
 """Interactive components provided by @radix-ui/themes."""
 from types import SimpleNamespace
 from types import SimpleNamespace
-from typing import Any, Dict, Literal
+from typing import Any, Dict, List, Literal
 
 
 from reflex.constants import EventTriggers
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from reflex.vars import Var
@@ -59,6 +59,8 @@ class TabsTrigger(RadixThemesComponent):
     # Whether the tab is disabled
     # Whether the tab is disabled
     disabled: Var[bool]
     disabled: Var[bool]
 
 
+    _valid_parents: List[str] = ["TabsList"]
+
 
 
 class TabsContent(RadixThemesComponent):
 class TabsContent(RadixThemesComponent):
     """Trigger an action or event, such as submitting a form or displaying a dialog."""
     """Trigger an action or event, such as submitting a form or displaying a dialog."""

+ 1 - 1
reflex/components/radix/themes/components/tabs.pyi

@@ -8,7 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.event import EventChain, EventHandler, EventSpec
 from reflex.style import Style
 from reflex.style import Style
 from types import SimpleNamespace
 from types import SimpleNamespace
-from typing import Any, Dict, Literal
+from typing import Any, Dict, List, Literal
 from reflex.constants import EventTriggers
 from reflex.constants import EventTriggers
 from reflex.vars import Var
 from reflex.vars import Var
 from ..base import RadixThemesComponent
 from ..base import RadixThemesComponent

+ 2 - 8
reflex/components/radix/themes/components/textarea.py

@@ -40,15 +40,9 @@ class TextArea(RadixThemesComponent, el.Textarea):
         Returns:
         Returns:
             The component.
             The component.
         """
         """
-        if (
-            isinstance(props.get("value"), Var) and props.get("on_change")
-        ) or "debounce_timeout" in props:
-            # Currently default to 50ms, which appears to be a good balance
-            debounce_timeout = props.pop("debounce_timeout", 50)
+        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
             # create a debounced input if the user requests full control to avoid typing jank
-            return DebounceInput.create(
-                super().create(*children, **props), debounce_timeout=debounce_timeout
-            )
+            return DebounceInput.create(super().create(*children, **props))
         return super().create(*children, **props)
         return super().create(*children, **props)
 
 
     def get_event_triggers(self) -> Dict[str, Any]:
     def get_event_triggers(self) -> Dict[str, Any]:

+ 2 - 8
reflex/components/radix/themes/components/textfield.py

@@ -56,15 +56,9 @@ class TextFieldInput(el.Input, TextFieldRoot):
         Returns:
         Returns:
             The component.
             The component.
         """
         """
-        if (
-            isinstance(props.get("value"), Var) and props.get("on_change")
-        ) or "debounce_timeout" in props:
-            # Currently default to 50ms, which appears to be a good balance
-            debounce_timeout = props.pop("debounce_timeout", 50)
+        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
             # create a debounced input if the user requests full control to avoid typing jank
-            return DebounceInput.create(
-                super().create(*children, **props), debounce_timeout=debounce_timeout
-            )
+            return DebounceInput.create(super().create(*children, **props))
         return super().create(*children, **props)
         return super().create(*children, **props)
 
 
     def get_event_triggers(self) -> Dict[str, Any]:
     def get_event_triggers(self) -> Dict[str, Any]:

+ 36 - 5
reflex/style.py

@@ -2,7 +2,7 @@
 
 
 from __future__ import annotations
 from __future__ import annotations
 
 
-from typing import Any
+from typing import Any, Tuple
 
 
 from reflex import constants
 from reflex import constants
 from reflex.event import EventChain
 from reflex.event import EventChain
@@ -40,6 +40,15 @@ toggle_color_mode = BaseVar(
 
 
 breakpoints = ["0", "30em", "48em", "62em", "80em", "96em"]
 breakpoints = ["0", "30em", "48em", "62em", "80em", "96em"]
 
 
+STYLE_PROP_SHORTHAND_MAPPING = {
+    "paddingX": ("padding-inline-start", "padding-inline-end"),
+    "paddingY": ("padding-top", "padding-bottom"),
+    "marginX": ("margin-inline-start", "margin-inline-end"),
+    "marginY": ("margin-top", "margin-bottom"),
+    "bg": ("background",),
+    "bgColor": ("background-color",),
+}
+
 
 
 def media_query(breakpoint_index: int):
 def media_query(breakpoint_index: int):
     """Create a media query selector.
     """Create a media query selector.
@@ -110,21 +119,43 @@ def convert(style_dict):
     """
     """
     var_data = None  # Track import/hook data from any Vars in the style dict.
     var_data = None  # Track import/hook data from any Vars in the style dict.
     out = {}
     out = {}
+
+    def update_out_dict(return_value, keys_to_update):
+        for k in keys_to_update:
+            out[k] = return_value
+
     for key, value in style_dict.items():
     for key, value in style_dict.items():
-        key = format.to_camel_case(key, allow_hyphens=True)
+        keys = format_style_key(key)
         if isinstance(value, dict):
         if isinstance(value, dict):
             # Recursively format nested style dictionaries.
             # Recursively format nested style dictionaries.
-            out[key], new_var_data = convert(value)
+            return_val, new_var_data = convert(value)
+            update_out_dict(return_val, keys)
         elif isinstance(value, list):
         elif isinstance(value, list):
             # Responsive value is a list of dict or value
             # Responsive value is a list of dict or value
-            out[key], new_var_data = convert_list(value)
+            return_val, new_var_data = convert_list(value)
+            update_out_dict(return_val, keys)
         else:
         else:
-            out[key], new_var_data = convert_item(value)
+            return_val, new_var_data = convert_item(value)
+            update_out_dict(return_val, keys)
         # Combine all the collected VarData instances.
         # Combine all the collected VarData instances.
         var_data = VarData.merge(var_data, new_var_data)
         var_data = VarData.merge(var_data, new_var_data)
     return out, var_data
     return out, var_data
 
 
 
 
+def format_style_key(key: str) -> Tuple[str, ...]:
+    """Convert style keys to camel case and convert shorthand
+    styles names to their corresponding css names.
+
+    Args:
+        key: The style key to convert.
+
+    Returns:
+        Tuple of css style names corresponding to the key provided.
+    """
+    key = format.to_camel_case(key, allow_hyphens=True)
+    return STYLE_PROP_SHORTHAND_MAPPING.get(key, (key,))
+
+
 class Style(dict):
 class Style(dict):
     """A style dictionary."""
     """A style dictionary."""
 
 

+ 3 - 2
tests/components/forms/test_debounce.py

@@ -3,6 +3,7 @@
 import pytest
 import pytest
 
 
 import reflex as rx
 import reflex as rx
+from reflex.components.core.debounce import DEFAULT_DEBOUNCE_TIMEOUT
 from reflex.state import BaseState
 from reflex.state import BaseState
 from reflex.vars import BaseVar
 from reflex.vars import BaseVar
 
 
@@ -107,7 +108,7 @@ def test_full_control_implicit_debounce():
         value=S.value,
         value=S.value,
         on_change=S.on_change,
         on_change=S.on_change,
     )._render()
     )._render()
-    assert tag.props["debounceTimeout"]._var_name == "50"
+    assert tag.props["debounceTimeout"]._var_name == str(DEFAULT_DEBOUNCE_TIMEOUT)
     assert len(tag.props["onChange"].events) == 1
     assert len(tag.props["onChange"].events) == 1
     assert tag.props["onChange"].events[0].handler == S.on_change
     assert tag.props["onChange"].events[0].handler == S.on_change
     assert tag.contents == ""
     assert tag.contents == ""
@@ -119,7 +120,7 @@ def test_full_control_implicit_debounce_text_area():
         value=S.value,
         value=S.value,
         on_change=S.on_change,
         on_change=S.on_change,
     )._render()
     )._render()
-    assert tag.props["debounceTimeout"]._var_name == "50"
+    assert tag.props["debounceTimeout"]._var_name == str(DEFAULT_DEBOUNCE_TIMEOUT)
     assert len(tag.props["onChange"].events) == 1
     assert len(tag.props["onChange"].events) == 1
     assert tag.props["onChange"].events[0].handler == S.on_change
     assert tag.props["onChange"].events[0].handler == S.on_change
     assert tag.contents == ""
     assert tag.contents == ""

+ 5 - 1
tests/components/typography/test_markdown.py

@@ -56,4 +56,8 @@ def test_pass_custom_styles():
     md = Markdown.create("# Hello", custom_styles={"h1": {"color": "red"}})
     md = Markdown.create("# Hello", custom_styles={"h1": {"color": "red"}})
 
 
     comp = md.get_component("h1")  # type: ignore
     comp = md.get_component("h1")  # type: ignore
-    assert comp.style == {"color": "red", "marginY": "0.5em"}
+    assert comp.style == {
+        "color": "red",
+        "margin-bottom": "0.5em",
+        "margin-top": "0.5em",
+    }

+ 0 - 1
tests/test_app.py

@@ -1274,7 +1274,6 @@ def test_app_wrap_priority(compilable_app):
         "return ("
         "return ("
         "<Box>"
         "<Box>"
         "<ChakraProvider theme={extendTheme(theme)}>"
         "<ChakraProvider theme={extendTheme(theme)}>"
-        "<Global styles={GlobalStyles}/>"
         "<ChakraColorModeProvider>"
         "<ChakraColorModeProvider>"
         "<Text>"
         "<Text>"
         "<Fragment2>"
         "<Fragment2>"

+ 13 - 0
tests/test_style.py

@@ -20,6 +20,19 @@ test_style = [
         {"::-webkit-scrollbar": {"display": "none"}},
         {"::-webkit-scrollbar": {"display": "none"}},
         {"::-webkit-scrollbar": {"display": "none"}},
         {"::-webkit-scrollbar": {"display": "none"}},
     ),
     ),
+    ({"margin_y": "2rem"}, {"margin-bottom": "2rem", "margin-top": "2rem"}),
+    ({"marginY": "2rem"}, {"margin-bottom": "2rem", "margin-top": "2rem"}),
+    (
+        {"::-webkit-scrollbar": {"bgColor": "red"}},
+        {"::-webkit-scrollbar": {"background-color": "red"}},
+    ),
+    (
+        {"paddingX": ["2rem", "3rem"]},
+        {
+            "padding-inline-start": ["2rem", "3rem"],
+            "padding-inline-end": ["2rem", "3rem"],
+        },
+    ),
 ]
 ]