Factor out responsive helpers (#624)

This commit is contained in:
Nikhil Rao 2023-03-03 13:29:17 -08:00 committed by GitHub
parent b751260276
commit 8ba22ed92d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 128 additions and 123 deletions

View File

@ -1,10 +1,6 @@
"""Import all the components."""
from __future__ import annotations
from typing import TYPE_CHECKING
from pynecone import utils
from .component import Component
from .datadisplay import *
from .disclosure import *
@ -17,9 +13,6 @@ from .navigation import *
from .overlay import *
from .typography import *
if TYPE_CHECKING:
from typing import Any
# Add the convenience methods for all the components.
# locals().update(
# {
@ -29,6 +22,8 @@ if TYPE_CHECKING:
# }
# )
# Add the convenience methods for all the components manually.
# This is necessary for static type checking to work.
component = Component.create
badge = Badge.create
code = Code.create
@ -205,116 +200,3 @@ heading = Heading.create
markdown = Markdown.create
span = Span.create
text = Text.create
# Add responsive styles shortcuts.
def mobile_only(*children, **props):
"""Create a component that is only visible on mobile.
Args:
*children: The children to pass to the component.
**props: The props to pass to the component.
Returns:
The component.
"""
return Box.create(*children, **props, display=["block", "none", "none", "none"])
def tablet_only(*children, **props):
"""Create a component that is only visible on tablet.
Args:
*children: The children to pass to the component.
**props: The props to pass to the component.
Returns:
The component.
"""
return Box.create(*children, **props, display=["none", "block", "block", "none"])
def desktop_only(*children, **props):
"""Create a component that is only visible on desktop.
Args:
*children: The children to pass to the component.
**props: The props to pass to the component.
Returns:
The component.
"""
return Box.create(*children, **props, display=["none", "none", "none", "block"])
def tablet_and_desktop(*children, **props):
"""Create a component that is only visible on tablet and desktop.
Args:
*children: The children to pass to the component.
**props: The props to pass to the component.
Returns:
The component.
"""
return Box.create(*children, **props, display=["none", "block", "block", "block"])
def mobile_and_tablet(*children, **props):
"""Create a component that is only visible on mobile and tablet.
Args:
*children: The children to pass to the component.
**props: The props to pass to the component.
Returns:
The component.
"""
return Box.create(*children, **props, display=["block", "block", "block", "none"])
def cond(condition: Any, c1: Any, c2: Any = None):
"""Create a conditional component or Prop.
Args:
condition: The cond to determine which component to render.
c1: The component or prop to render if the cond_var is true.
c2: The component or prop to render if the cond_var is false.
Returns:
The conditional component.
Raises:
ValueError: If the arguments are invalid.
"""
# Import here to avoid circular imports.
from pynecone.var import BaseVar, Var
# Convert the condition to a Var.
cond_var = Var.create(condition)
assert cond_var is not None, "The condition must be set."
# If the first component is a component, create a Cond component.
if isinstance(c1, Component):
assert c2 is None or isinstance(
c2, Component
), "Both arguments must be components."
return Cond.create(cond_var, c1, c2)
# Otherwise, create a conditionl Var.
# Check that the second argument is valid.
if isinstance(c2, Component):
raise ValueError("Both arguments must be props.")
if c2 is None:
raise ValueError("For conditional vars, the second argument must be set.")
# Create the conditional var.
return BaseVar(
name=utils.format_cond(
cond=cond_var.full_name,
true_value=c1,
false_value=c2,
is_prop=True,
),
type_=c1.type_ if isinstance(c1, BaseVar) else type(c1),
)

View File

@ -2,13 +2,20 @@
from .box import Box
from .center import Center, Circle, Square
from .cond import Cond
from .cond import Cond, cond
from .container import Container
from .flex import Flex
from .foreach import Foreach
from .fragment import Fragment
from .grid import Grid, GridItem, ResponsiveGrid
from .html import Html
from .responsive import (
desktop_only,
mobile_and_tablet,
mobile_only,
tablet_and_desktop,
tablet_only,
)
from .spacer import Spacer
from .stack import Hstack, Stack, Vstack
from .wrap import Wrap, WrapItem

View File

@ -3,6 +3,7 @@ from __future__ import annotations
from typing import Any, Optional
from pynecone import utils
from pynecone.components.component import Component
from pynecone.components.layout.fragment import Fragment
from pynecone.components.tags import CondTag, Tag
@ -64,3 +65,50 @@ class Cond(Component):
false_value=self.comp2.render(),
is_nested=self.is_nested,
)
def cond(condition: Any, c1: Any, c2: Any = None):
"""Create a conditional component or Prop.
Args:
condition: The cond to determine which component to render.
c1: The component or prop to render if the cond_var is true.
c2: The component or prop to render if the cond_var is false.
Returns:
The conditional component.
Raises:
ValueError: If the arguments are invalid.
"""
# Import here to avoid circular imports.
from pynecone.var import BaseVar, Var
# Convert the condition to a Var.
cond_var = Var.create(condition)
assert cond_var is not None, "The condition must be set."
# If the first component is a component, create a Cond component.
if isinstance(c1, Component):
assert c2 is None or isinstance(
c2, Component
), "Both arguments must be components."
return Cond.create(cond_var, c1, c2)
# Otherwise, create a conditionl Var.
# Check that the second argument is valid.
if isinstance(c2, Component):
raise ValueError("Both arguments must be props.")
if c2 is None:
raise ValueError("For conditional vars, the second argument must be set.")
# Create the conditional var.
return BaseVar(
name=utils.format_cond(
cond=cond_var.full_name,
true_value=c1,
false_value=c2,
is_prop=True,
),
type_=c1.type_ if isinstance(c1, BaseVar) else type(c1),
)

View File

@ -0,0 +1,69 @@
"""Responsive components."""
from pynecone.components.layout.box import Box
# Add responsive styles shortcuts.
def mobile_only(*children, **props):
"""Create a component that is only visible on mobile.
Args:
*children: The children to pass to the component.
**props: The props to pass to the component.
Returns:
The component.
"""
return Box.create(*children, **props, display=["block", "none", "none", "none"])
def tablet_only(*children, **props):
"""Create a component that is only visible on tablet.
Args:
*children: The children to pass to the component.
**props: The props to pass to the component.
Returns:
The component.
"""
return Box.create(*children, **props, display=["none", "block", "block", "none"])
def desktop_only(*children, **props):
"""Create a component that is only visible on desktop.
Args:
*children: The children to pass to the component.
**props: The props to pass to the component.
Returns:
The component.
"""
return Box.create(*children, **props, display=["none", "none", "none", "block"])
def tablet_and_desktop(*children, **props):
"""Create a component that is only visible on tablet and desktop.
Args:
*children: The children to pass to the component.
**props: The props to pass to the component.
Returns:
The component.
"""
return Box.create(*children, **props, display=["none", "block", "block", "block"])
def mobile_and_tablet(*children, **props):
"""Create a component that is only visible on mobile and tablet.
Args:
*children: The children to pass to the component.
**props: The props to pass to the component.
Returns:
The component.
"""
return Box.create(*children, **props, display=["block", "block", "block", "none"])

View File

@ -4,8 +4,7 @@ from typing import Any
import pytest
import pynecone as pc
from pynecone.components import cond
from pynecone.components.layout.cond import Cond
from pynecone.components.layout.cond import Cond, cond
from pynecone.components.layout.fragment import Fragment
from pynecone.components.typography.text import Text
from pynecone.var import Var