components as props (#2124)

This commit is contained in:
Thomas Brandého 2023-11-03 21:29:18 +01:00 committed by GitHub
parent 4c97b4c4c0
commit eb52edb067
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 9 deletions

View File

@ -20,6 +20,7 @@ from reflex.event import (
) )
from reflex.style import Style from reflex.style import Style
from reflex.utils import console, format, imports, types from reflex.utils import console, format, imports, types
from reflex.utils.serializers import serializer
from reflex.vars import BaseVar, ImportVar, Var from reflex.vars import BaseVar, ImportVar, Var
@ -400,6 +401,20 @@ class Component(Base, ABC):
""" """
return set() return set()
@classmethod
def get_component_props(cls) -> set[str]:
"""Get the props that expected a component as value.
Returns:
The components props.
"""
return {
name
for name, field in cls.get_fields().items()
if name in cls.get_props()
and types._issubclass(field.outer_type_, Component)
}
@classmethod @classmethod
def create(cls, *children, **props) -> Component: def create(cls, *children, **props) -> Component:
"""Create the component. """Create the component.
@ -596,19 +611,48 @@ class Component(Base, ABC):
# Return the dynamic imports # Return the dynamic imports
return dynamic_imports return dynamic_imports
def _get_dependencies_imports(self): def _get_props_imports(self) -> imports.ImportDict:
return { """Get the imports needed for components props.
dep: {ImportVar(tag=None, render=False)} for dep in self.lib_dependencies
} Returns:
The imports for the components props of the component.
"""
return imports.merge_imports(
*[
getattr(self, prop).get_imports()
for prop in self.get_component_props()
if getattr(self, prop) is not None
]
)
def _get_dependencies_imports(self) -> imports.ImportDict:
"""Get the imports from lib_dependencies for installing.
Returns:
The dependencies imports of the component.
"""
return imports.merge_imports(
{dep: {ImportVar(tag=None, render=False)} for dep in self.lib_dependencies}
)
def _get_imports(self) -> imports.ImportDict: def _get_imports(self) -> imports.ImportDict:
imports = {} """Get all the libraries and fields that are used by the component.
Returns:
The imports needed by the component.
"""
_imports = {}
if self.library is not None and self.tag is not None: if self.library is not None and self.tag is not None:
imports[self.library] = {self.import_var} _imports[self.library] = {self.import_var}
return {**self._get_dependencies_imports(), **imports}
return imports.merge_imports(
self._get_props_imports(),
self._get_dependencies_imports(),
_imports,
)
def get_imports(self) -> imports.ImportDict: def get_imports(self) -> imports.ImportDict:
"""Get all the libraries and fields that are used by the component. """Get all the libraries and fields that are used by the component and its children.
Returns: Returns:
The import dict with the required imports. The import dict with the required imports.
@ -988,3 +1032,16 @@ class NoSSRComponent(Component):
else "" else ""
) )
return "".join((library_import, mod_import, opts_fragment)) return "".join((library_import, mod_import, opts_fragment))
@serializer
def serialize_component(comp: Component):
"""Serialize a component.
Args:
comp: The component to serialize.
Returns:
The serialized component.
"""
return str(comp)

View File

@ -1,5 +1,8 @@
"""An icon button component.""" """An icon button component."""
from typing import Optional
from reflex.components.component import Component
from reflex.components.typography.text import Text from reflex.components.typography.text import Text
from reflex.vars import Var from reflex.vars import Var
@ -16,7 +19,7 @@ class IconButton(Text):
aria_label: Var[str] aria_label: Var[str]
# The icon to be used in the button. # The icon to be used in the button.
icon: Var[str] icon: Optional[Component]
# If true, the button will be styled in its active state. # If true, the button will be styled in its active state.
is_active: Var[bool] is_active: Var[bool]