Merge remote-tracking branch 'origin/main' into reflex-0.4.0
This commit is contained in:
commit
c124650082
@ -460,7 +460,12 @@ def remove_tailwind_from_postcss() -> tuple[str, str]:
|
||||
|
||||
|
||||
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"])
|
||||
|
||||
|
||||
|
@ -15,7 +15,6 @@ class ChakraComponent(Component):
|
||||
library = "@chakra-ui/react@2.6.1"
|
||||
lib_dependencies: List[str] = [
|
||||
"@chakra-ui/system@2.5.7",
|
||||
"focus-visible@5.2.0",
|
||||
"framer-motion@10.16.4",
|
||||
]
|
||||
|
||||
@ -26,25 +25,6 @@ class ChakraComponent(Component):
|
||||
(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:
|
||||
"""Get the style for the component.
|
||||
|
||||
@ -65,25 +45,11 @@ class ChakraComponent(Component):
|
||||
dep: [imports.ImportVar(tag=None, render=False)]
|
||||
for dep in [
|
||||
"@chakra-ui/system@2.5.7",
|
||||
"focus-visible@5.2.0",
|
||||
"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):
|
||||
"""Top level Chakra provider must be included in any app using chakra components."""
|
||||
|
||||
@ -99,7 +65,6 @@ class ChakraProvider(ChakraComponent):
|
||||
A new ChakraProvider component.
|
||||
"""
|
||||
return super().create(
|
||||
Global.create(styles=Var.create("GlobalStyles", _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.ImportVar(tag="theme", is_default=True),
|
||||
)
|
||||
_imports.setdefault(Global.__fields__["library"].default, []).append(
|
||||
imports.ImportVar(tag="css", is_default=False),
|
||||
)
|
||||
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
|
||||
@lru_cache(maxsize=None)
|
||||
def _get_app_wrap_components() -> dict[tuple[int, str], Component]:
|
||||
|
@ -14,7 +14,6 @@ from reflex.utils import imports
|
||||
from reflex.vars import Var
|
||||
|
||||
class ChakraComponent(Component):
|
||||
def get_imports(self) -> imports.ImportDict: ...
|
||||
@overload
|
||||
@classmethod
|
||||
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):
|
||||
@overload
|
||||
@classmethod
|
||||
|
@ -91,15 +91,9 @@ class Input(ChakraComponent):
|
||||
Returns:
|
||||
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
|
||||
return DebounceInput.create(
|
||||
super().create(*children, **props), debounce_timeout=debounce_timeout
|
||||
)
|
||||
return DebounceInput.create(super().create(*children, **props))
|
||||
return super().create(*children, **props)
|
||||
|
||||
|
||||
|
@ -74,13 +74,7 @@ class TextArea(ChakraComponent):
|
||||
Returns:
|
||||
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
|
||||
return DebounceInput.create(
|
||||
super().create(*children, **props), debounce_timeout=debounce_timeout
|
||||
)
|
||||
return DebounceInput.create(super().create(*children, **props))
|
||||
return super().create(*children, **props)
|
||||
|
@ -7,6 +7,8 @@ from reflex.components.component import Component
|
||||
from reflex.constants import EventTriggers
|
||||
from reflex.vars import Var, VarData
|
||||
|
||||
DEFAULT_DEBOUNCE_TIMEOUT = 300
|
||||
|
||||
|
||||
class DebounceInput(Component):
|
||||
"""The DebounceInput component is used to buffer input events on the client side.
|
||||
@ -23,7 +25,7 @@ class DebounceInput(Component):
|
||||
min_length: Var[int]
|
||||
|
||||
# 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
|
||||
force_notify_by_enter: Var[bool]
|
||||
|
@ -12,6 +12,8 @@ from reflex.components.component import Component
|
||||
from reflex.constants import EventTriggers
|
||||
from reflex.vars import Var, VarData
|
||||
|
||||
DEFAULT_DEBOUNCE_TIMEOUT = 300
|
||||
|
||||
class DebounceInput(Component):
|
||||
@overload
|
||||
@classmethod
|
||||
|
@ -3,7 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
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.core import match
|
||||
@ -344,6 +344,8 @@ class AccordionRoot(AccordionComponent):
|
||||
# The var_data associated with the component.
|
||||
_var_data: VarData = VarData() # type: ignore
|
||||
|
||||
_valid_children: List[str] = ["AccordionItem"]
|
||||
|
||||
@classmethod
|
||||
def create(cls, *children, **props) -> Component:
|
||||
"""Create the Accordion root component.
|
||||
@ -451,6 +453,14 @@ class AccordionItem(AccordionComponent):
|
||||
# When true, prevents the user from interacting with the item.
|
||||
disabled: Var[bool]
|
||||
|
||||
_valid_children: List[str] = [
|
||||
"AccordionHeader",
|
||||
"AccordionTrigger",
|
||||
"AccordionContent",
|
||||
]
|
||||
|
||||
_valid_parents: List[str] = ["AccordionRoot"]
|
||||
|
||||
def _apply_theme(self, theme: Component):
|
||||
self.style = Style(
|
||||
{
|
||||
|
@ -8,7 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
|
||||
from reflex.event import EventChain, EventHandler, EventSpec
|
||||
from reflex.style import Style
|
||||
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.core import match
|
||||
from reflex.components.lucide.icon import Icon
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Interactive components provided by @radix-ui/themes."""
|
||||
from types import SimpleNamespace
|
||||
from typing import Any, Dict, Literal
|
||||
from typing import Any, Dict, List, Literal
|
||||
|
||||
from reflex.constants import EventTriggers
|
||||
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.
|
||||
modal: Var[bool]
|
||||
|
||||
_invalid_children: List[str] = ["ContextMenuItem"]
|
||||
|
||||
def get_event_triggers(self) -> Dict[str, Any]:
|
||||
"""Get the events triggers signatures for the component.
|
||||
|
||||
@ -39,6 +41,10 @@ class ContextMenuTrigger(RadixThemesComponent):
|
||||
# Whether the trigger is disabled
|
||||
disabled: Var[bool]
|
||||
|
||||
_valid_parents: List[str] = ["ContextMenuRoot"]
|
||||
|
||||
_invalid_children: List[str] = ["ContextMenuContent"]
|
||||
|
||||
|
||||
class ContextMenuContent(RadixThemesComponent):
|
||||
"""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.
|
||||
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]
|
||||
|
||||
def get_event_triggers(self) -> Dict[str, Any]:
|
||||
@ -93,6 +99,8 @@ class ContextMenuSubTrigger(RadixThemesComponent):
|
||||
# Whether the trigger is disabled
|
||||
disabled: Var[bool]
|
||||
|
||||
_valid_parents: List[str] = ["ContextMenuContent", "ContextMenuSub"]
|
||||
|
||||
|
||||
class ContextMenuSubContent(RadixThemesComponent):
|
||||
"""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.
|
||||
loop: Var[bool]
|
||||
|
||||
_valid_parents: List[str] = ["ContextMenuSub"]
|
||||
|
||||
def get_event_triggers(self) -> Dict[str, Any]:
|
||||
"""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: Var[str]
|
||||
|
||||
_valid_parents: List[str] = ["ContextMenuContent", "ContextMenuSubContent"]
|
||||
|
||||
|
||||
class ContextMenuSeparator(RadixThemesComponent):
|
||||
"""Trigger an action or event, such as submitting a form or displaying a dialog."""
|
||||
|
@ -8,7 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
|
||||
from reflex.event import EventChain, EventHandler, EventSpec
|
||||
from reflex.style import Style
|
||||
from types import SimpleNamespace
|
||||
from typing import Any, Dict, Literal
|
||||
from typing import Any, Dict, List, Literal
|
||||
from reflex.constants import EventTriggers
|
||||
from reflex.vars import Var
|
||||
from ..base import LiteralAccentColor, RadixThemesComponent
|
||||
@ -472,7 +472,7 @@ class ContextMenuContent(RadixThemesComponent):
|
||||
variant: Variant of button: "solid" | "soft" | "outline" | "ghost"
|
||||
high_contrast: Whether to render the button with higher contrast color against background
|
||||
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.
|
||||
key: A unique key for the component.
|
||||
id: The id for the component.
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Interactive components provided by @radix-ui/themes."""
|
||||
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.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.
|
||||
dir: Var[LiteralDirType]
|
||||
|
||||
_invalid_children: List[str] = ["DropdownMenuItem"]
|
||||
|
||||
def get_event_triggers(self) -> Dict[str, Any]:
|
||||
"""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.
|
||||
as_child: Var[bool]
|
||||
|
||||
_valid_parents: List[str] = ["DropdownMenuRoot"]
|
||||
|
||||
_invalid_children: List[str] = ["DropdownMenuContent"]
|
||||
|
||||
|
||||
class DropdownMenuContent(RadixThemesComponent):
|
||||
"""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.
|
||||
text_value: Var[str]
|
||||
|
||||
_valid_parents: List[str] = ["DropdownMenuContent", "DropdownMenuSub"]
|
||||
|
||||
|
||||
class DropdownMenuSub(RadixThemesComponent):
|
||||
"""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.
|
||||
hide_when_detached: Var[bool]
|
||||
|
||||
_valid_parents: List[str] = ["DropdownMenuSub"]
|
||||
|
||||
def get_event_triggers(self) -> Dict[str, Any]:
|
||||
"""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.
|
||||
text_value: Var[str]
|
||||
|
||||
_valid_parents: List[str] = ["DropdownMenuContent", "DropdownMenuSubContent"]
|
||||
|
||||
def get_event_triggers(self) -> Dict[str, Any]:
|
||||
"""Get the events triggers signatures for the component.
|
||||
|
||||
|
@ -8,7 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
|
||||
from reflex.event import EventChain, EventHandler, EventSpec
|
||||
from reflex.style import Style
|
||||
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.vars import Var
|
||||
from ..base import LiteralAccentColor, RadixThemesComponent
|
||||
|
@ -78,6 +78,8 @@ class SelectTrigger(RadixThemesComponent):
|
||||
# The placeholder of the select trigger
|
||||
placeholder: Var[str]
|
||||
|
||||
_valid_parents: List[str] = ["SelectRoot"]
|
||||
|
||||
|
||||
class SelectContent(RadixThemesComponent):
|
||||
"""The component that pops out when the select is open."""
|
||||
@ -127,6 +129,8 @@ class SelectGroup(RadixThemesComponent):
|
||||
|
||||
tag = "Select.Group"
|
||||
|
||||
_valid_parents: List[str] = ["SelectContent"]
|
||||
|
||||
|
||||
class SelectItem(RadixThemesComponent):
|
||||
"""The component that contains the select items."""
|
||||
@ -139,12 +143,16 @@ class SelectItem(RadixThemesComponent):
|
||||
# Whether the select item is disabled
|
||||
disabled: Var[bool]
|
||||
|
||||
_valid_parents: List[str] = ["SelectGroup", "SelectContent"]
|
||||
|
||||
|
||||
class SelectLabel(RadixThemesComponent):
|
||||
"""Used to render the label of a group, it isn't focusable using arrow keys."""
|
||||
|
||||
tag = "Select.Label"
|
||||
|
||||
_valid_parents: List[str] = ["SelectGroup"]
|
||||
|
||||
|
||||
class SelectSeparator(RadixThemesComponent):
|
||||
"""Used to visually separate items in the Select."""
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""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.vars import Var
|
||||
|
||||
@ -35,7 +36,7 @@ class Slider(RadixThemesComponent):
|
||||
radius: Var[LiteralRadius]
|
||||
|
||||
# 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.
|
||||
value: Var[List[Union[float, int]]]
|
||||
@ -73,5 +74,39 @@ class Slider(RadixThemesComponent):
|
||||
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
|
@ -7,7 +7,8 @@ from typing import Any, Dict, Literal, Optional, Union, overload
|
||||
from reflex.vars import Var, BaseVar, ComputedVar
|
||||
from reflex.event import EventChain, EventHandler, EventSpec
|
||||
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.vars import Var
|
||||
from ..base import LiteralAccentColor, LiteralRadius, RadixThemesComponent
|
||||
@ -19,7 +20,17 @@ class Slider(RadixThemesComponent):
|
||||
def create( # type: ignore
|
||||
cls,
|
||||
*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[
|
||||
Union[
|
||||
Var[
|
||||
@ -82,16 +93,6 @@ class Slider(RadixThemesComponent):
|
||||
],
|
||||
]
|
||||
] = 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,
|
||||
radius: Optional[
|
||||
Union[
|
||||
@ -100,7 +101,10 @@ class Slider(RadixThemesComponent):
|
||||
]
|
||||
] = None,
|
||||
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,
|
||||
value: Optional[
|
||||
Union[Var[List[Union[float, int]]], List[Union[float, int]]]
|
||||
@ -176,18 +180,15 @@ class Slider(RadixThemesComponent):
|
||||
] = None,
|
||||
**props
|
||||
) -> "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:
|
||||
*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.
|
||||
size: Button size "1" - "3"
|
||||
variant: Variant of button
|
||||
color_scheme: Override theme color for button
|
||||
high_contrast: Whether to render the button with higher contrast color against background
|
||||
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.
|
||||
@ -205,10 +206,10 @@ class Slider(RadixThemesComponent):
|
||||
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: Component properties.
|
||||
**props: The properties of the component.
|
||||
|
||||
Returns:
|
||||
A new component instance.
|
||||
The component.
|
||||
"""
|
||||
...
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Interactive components provided by @radix-ui/themes."""
|
||||
from types import SimpleNamespace
|
||||
from typing import Literal, Union
|
||||
from typing import List, Literal, Union
|
||||
|
||||
from reflex import el
|
||||
from reflex.vars import Var
|
||||
@ -27,6 +27,10 @@ class TableHeader(el.Thead, RadixThemesComponent):
|
||||
|
||||
tag = "Table.Header"
|
||||
|
||||
_invalid_children: List[str] = ["TableBody"]
|
||||
|
||||
_valid_parents: List[str] = ["TableRoot"]
|
||||
|
||||
|
||||
class TableRow(el.Tr, RadixThemesComponent):
|
||||
"""A row containing table cells."""
|
||||
@ -36,6 +40,8 @@ class TableRow(el.Tr, RadixThemesComponent):
|
||||
# The alignment of the row
|
||||
align: Var[Literal["start", "center", "end", "baseline"]]
|
||||
|
||||
_invalid_children: List[str] = ["TableBody", "TableHeader", "TableRow"]
|
||||
|
||||
|
||||
class TableColumnHeaderCell(el.Th, RadixThemesComponent):
|
||||
"""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: Var[Union[str, int]]
|
||||
|
||||
_invalid_children: List[str] = [
|
||||
"TableBody",
|
||||
"TableHeader",
|
||||
"TableRow",
|
||||
"TableCell",
|
||||
"TableColumnHeaderCell",
|
||||
"TableRowHeaderCell",
|
||||
]
|
||||
|
||||
|
||||
class TableBody(el.Tbody, RadixThemesComponent):
|
||||
"""The body of the table contains the data rows."""
|
||||
|
||||
tag = "Table.Body"
|
||||
|
||||
_invalid_children: List[str] = [
|
||||
"TableHeader",
|
||||
"TableRowHeaderCell",
|
||||
"TableColumnHeaderCell",
|
||||
"TableCell",
|
||||
]
|
||||
|
||||
_valid_parents: List[str] = ["TableRoot"]
|
||||
|
||||
|
||||
class TableCell(el.Td, RadixThemesComponent):
|
||||
"""A cell containing data."""
|
||||
@ -66,6 +90,14 @@ class TableCell(el.Td, RadixThemesComponent):
|
||||
# width of the column
|
||||
width: Var[Union[str, int]]
|
||||
|
||||
_invalid_children: List[str] = [
|
||||
"TableBody",
|
||||
"TableHeader",
|
||||
"TableRowHeaderCell",
|
||||
"TableColumnHeaderCell",
|
||||
"TableCell",
|
||||
]
|
||||
|
||||
|
||||
class TableRowHeaderCell(el.Th, RadixThemesComponent):
|
||||
"""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: Var[Union[str, int]]
|
||||
|
||||
_invalid_children: List[str] = [
|
||||
"TableBody",
|
||||
"TableHeader",
|
||||
"TableRow",
|
||||
"TableCell",
|
||||
"TableColumnHeaderCell",
|
||||
"TableRowHeaderCell",
|
||||
]
|
||||
|
||||
|
||||
class Table(SimpleNamespace):
|
||||
"""Table components namespace."""
|
||||
|
@ -8,7 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
|
||||
from reflex.event import EventChain, EventHandler, EventSpec
|
||||
from reflex.style import Style
|
||||
from types import SimpleNamespace
|
||||
from typing import Literal, Union
|
||||
from typing import List, Literal, Union
|
||||
from reflex import el
|
||||
from reflex.vars import Var
|
||||
from ..base import RadixThemesComponent
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Interactive components provided by @radix-ui/themes."""
|
||||
from types import SimpleNamespace
|
||||
from typing import Any, Dict, Literal
|
||||
from typing import Any, Dict, List, Literal
|
||||
|
||||
from reflex.constants import EventTriggers
|
||||
from reflex.vars import Var
|
||||
@ -59,6 +59,8 @@ class TabsTrigger(RadixThemesComponent):
|
||||
# Whether the tab is disabled
|
||||
disabled: Var[bool]
|
||||
|
||||
_valid_parents: List[str] = ["TabsList"]
|
||||
|
||||
|
||||
class TabsContent(RadixThemesComponent):
|
||||
"""Trigger an action or event, such as submitting a form or displaying a dialog."""
|
||||
|
@ -8,7 +8,7 @@ from reflex.vars import Var, BaseVar, ComputedVar
|
||||
from reflex.event import EventChain, EventHandler, EventSpec
|
||||
from reflex.style import Style
|
||||
from types import SimpleNamespace
|
||||
from typing import Any, Dict, Literal
|
||||
from typing import Any, Dict, List, Literal
|
||||
from reflex.constants import EventTriggers
|
||||
from reflex.vars import Var
|
||||
from ..base import RadixThemesComponent
|
||||
|
@ -40,15 +40,9 @@ class TextArea(RadixThemesComponent, el.Textarea):
|
||||
Returns:
|
||||
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
|
||||
return DebounceInput.create(
|
||||
super().create(*children, **props), debounce_timeout=debounce_timeout
|
||||
)
|
||||
return DebounceInput.create(super().create(*children, **props))
|
||||
return super().create(*children, **props)
|
||||
|
||||
def get_event_triggers(self) -> Dict[str, Any]:
|
||||
|
@ -56,15 +56,9 @@ class TextFieldInput(el.Input, TextFieldRoot):
|
||||
Returns:
|
||||
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
|
||||
return DebounceInput.create(
|
||||
super().create(*children, **props), debounce_timeout=debounce_timeout
|
||||
)
|
||||
return DebounceInput.create(super().create(*children, **props))
|
||||
return super().create(*children, **props)
|
||||
|
||||
def get_event_triggers(self) -> Dict[str, Any]:
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, Tuple
|
||||
|
||||
from reflex import constants
|
||||
from reflex.event import EventChain
|
||||
@ -40,6 +40,15 @@ toggle_color_mode = BaseVar(
|
||||
|
||||
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):
|
||||
"""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.
|
||||
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():
|
||||
key = format.to_camel_case(key, allow_hyphens=True)
|
||||
keys = format_style_key(key)
|
||||
if isinstance(value, dict):
|
||||
# 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):
|
||||
# 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:
|
||||
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.
|
||||
var_data = VarData.merge(var_data, new_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):
|
||||
"""A style dictionary."""
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
import pytest
|
||||
|
||||
import reflex as rx
|
||||
from reflex.components.core.debounce import DEFAULT_DEBOUNCE_TIMEOUT
|
||||
from reflex.state import BaseState
|
||||
from reflex.vars import BaseVar
|
||||
|
||||
@ -107,7 +108,7 @@ def test_full_control_implicit_debounce():
|
||||
value=S.value,
|
||||
on_change=S.on_change,
|
||||
)._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 tag.props["onChange"].events[0].handler == S.on_change
|
||||
assert tag.contents == ""
|
||||
@ -119,7 +120,7 @@ def test_full_control_implicit_debounce_text_area():
|
||||
value=S.value,
|
||||
on_change=S.on_change,
|
||||
)._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 tag.props["onChange"].events[0].handler == S.on_change
|
||||
assert tag.contents == ""
|
||||
|
@ -56,4 +56,8 @@ def test_pass_custom_styles():
|
||||
md = Markdown.create("# Hello", custom_styles={"h1": {"color": "red"}})
|
||||
|
||||
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",
|
||||
}
|
||||
|
@ -1274,7 +1274,6 @@ def test_app_wrap_priority(compilable_app):
|
||||
"return ("
|
||||
"<Box>"
|
||||
"<ChakraProvider theme={extendTheme(theme)}>"
|
||||
"<Global styles={GlobalStyles}/>"
|
||||
"<ChakraColorModeProvider>"
|
||||
"<Text>"
|
||||
"<Fragment2>"
|
||||
|
@ -20,6 +20,19 @@ test_style = [
|
||||
{"::-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"],
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user