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.utils import console, format, imports, types
from reflex.utils.serializers import serializer
from reflex.vars import BaseVar, ImportVar, Var
@ -400,6 +401,20 @@ class Component(Base, ABC):
"""
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
def create(cls, *children, **props) -> Component:
"""Create the component.
@ -596,19 +611,48 @@ class Component(Base, ABC):
# Return the dynamic imports
return dynamic_imports
def _get_dependencies_imports(self):
return {
dep: {ImportVar(tag=None, render=False)} for dep in self.lib_dependencies
}
def _get_props_imports(self) -> imports.ImportDict:
"""Get the imports needed for components props.
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:
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:
imports[self.library] = {self.import_var}
return {**self._get_dependencies_imports(), **imports}
_imports[self.library] = {self.import_var}
return imports.merge_imports(
self._get_props_imports(),
self._get_dependencies_imports(),
_imports,
)
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:
The import dict with the required imports.
@ -988,3 +1032,16 @@ class NoSSRComponent(Component):
else ""
)
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."""
from typing import Optional
from reflex.components.component import Component
from reflex.components.typography.text import Text
from reflex.vars import Var
@ -16,7 +19,7 @@ class IconButton(Text):
aria_label: Var[str]
# 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.
is_active: Var[bool]