reflex/reflex/components/radix/primitives/drawer.py
Alek Petuskey eadbf1d3db
Fix comments on drawer (#2604)
* Fix comments on drawer

* Fix precommit

* Fix pyi

* Fix table invalid children

---------

Co-authored-by: Alek Petuskey <alekpetuskey@aleks-mbp.lan>
2024-02-13 22:10:18 -08:00

258 lines
7.4 KiB
Python

"""Drawer components based on Radix primitives."""
# Based on Vaul: https://github.com/emilkowalski/vaul
# Style based on https://ui.shadcn.com/docs/components/drawer
from __future__ import annotations
from types import SimpleNamespace
from typing import Any, Dict, List, Literal, Optional, Union
from reflex.components.radix.primitives.base import RadixPrimitiveComponent
from reflex.constants import EventTriggers
from reflex.vars import Var
class DrawerComponent(RadixPrimitiveComponent):
"""A Drawer component."""
library = "vaul"
lib_dependencies: List[str] = ["@radix-ui/react-dialog@^1.0.5"]
LiteralDirectionType = Literal[
"top",
"bottom",
"left",
"right",
]
class DrawerRoot(DrawerComponent):
"""The Root component of a Drawer, contains all parts of a drawer."""
tag = "Drawer.Root"
alias = "Vaul" + tag
# Whether the drawer is open or not.
open: Var[bool]
# Enable background scaling, it requires an element with [vaul-drawer-wrapper] data attribute to scale its background.
should_scale_background: Var[bool]
# Number between 0 and 1 that determines when the drawer should be closed.
close_threshold: Var[float]
# Array of numbers from 0 to 100 that corresponds to % of the screen a given snap point should take up. Should go from least visible. Also Accept px values, which doesn't take screen height into account.
snap_points: Optional[List[Union[str, float]]]
# Index of a snapPoint from which the overlay fade should be applied. Defaults to the last snap point.
fade_from_index: Var[int]
# Duration for which the drawer is not draggable after scrolling content inside of the drawer. Defaults to 500ms
scroll_lock_timeout: Var[int]
# When `False`, it allows to interact with elements outside of the drawer without closing it. Defaults to `True`.
modal: Var[bool]
# Direction of the drawer. Defaults to `"bottom"`
direction: Var[LiteralDirectionType]
# When `True`, it prevents scroll restoration. Defaults to `True`.
preventScrollRestoration: Var[bool]
def get_event_triggers(self) -> Dict[str, Any]:
"""Get the event triggers that pass the component's value to the handler.
Returns:
A dict mapping the event trigger to the var that is passed to the handler.
"""
return {
**super().get_event_triggers(),
EventTriggers.ON_OPEN_CHANGE: lambda e0: [e0.target.value],
}
class DrawerTrigger(DrawerComponent):
"""The button that opens the dialog."""
tag = "Drawer.Trigger"
alias = "Vaul" + tag
# Defaults to true, if the first child acts as the trigger.
as_child: Var[bool] = True # type: ignore
class DrawerPortal(DrawerComponent):
"""Portals your drawer into the body."""
tag = "Drawer.Portal"
alias = "Vaul" + tag
# Based on https://www.radix-ui.com/primitives/docs/components/dialog#content
class DrawerContent(DrawerComponent):
"""Content that should be rendered in the drawer."""
tag = "Drawer.Content"
alias = "Vaul" + tag
# Style set partially based on the source code at https://ui.shadcn.com/docs/components/drawer
def _get_style(self) -> dict:
"""Get the style for the component.
Returns:
The dictionary of the component style as value and the style notation as key.
"""
base_style = {
"left": "0",
"right": "0",
"bottom": "0",
"top": "0",
"position": "fixed",
"z_index": 50,
"display": "flex",
}
style = self.style or {}
base_style.update(style)
self.style.update(
{
"css": base_style,
}
)
return self.style
def get_event_triggers(self) -> Dict[str, Any]:
"""Get the events triggers signatures for the component.
Returns:
The signatures of the event triggers.
"""
return {
**super().get_event_triggers(),
# DrawerContent is based on Radix DialogContent
# These are the same triggers as DialogContent
EventTriggers.ON_OPEN_AUTO_FOCUS: lambda e0: [e0.target.value],
EventTriggers.ON_CLOSE_AUTO_FOCUS: lambda e0: [e0.target.value],
EventTriggers.ON_ESCAPE_KEY_DOWN: lambda e0: [e0.target.value],
EventTriggers.ON_POINTER_DOWN_OUTSIDE: lambda e0: [e0.target.value],
EventTriggers.ON_INTERACT_OUTSIDE: lambda e0: [e0.target.value],
}
class DrawerOverlay(DrawerComponent):
"""A layer that covers the inert portion of the view when the dialog is open."""
tag = "Drawer.Overlay"
alias = "Vaul" + tag
# Style set based on the source code at https://ui.shadcn.com/docs/components/drawer
def _get_style(self) -> dict:
"""Get the style for the component.
Returns:
The dictionary of the component style as value and the style notation as key.
"""
base_style = {
"position": "fixed",
"left": "0",
"right": "0",
"bottom": "0",
"top": "0",
"z_index": 50,
"background": "rgba(0, 0, 0, 0.5)",
}
style = self.style or {}
base_style.update(style)
self.style.update(
{
"css": base_style,
}
)
return self.style
class DrawerClose(DrawerComponent):
"""A button that closes the drawer."""
tag = "Drawer.Close"
alias = "Vaul" + tag
class DrawerTitle(DrawerComponent):
"""A title for the drawer."""
tag = "Drawer.Title"
alias = "Vaul" + tag
# Style set based on the source code at https://ui.shadcn.com/docs/components/drawer
def _get_style(self) -> dict:
"""Get the style for the component.
Returns:
The dictionary of the component style as value and the style notation as key.
"""
base_style = {
"font-size": "1.125rem",
"font-weight": "600",
"line-weight": "1",
"letter-spacing": "-0.05em",
}
style = self.style or {}
base_style.update(style)
self.style.update(
{
"css": base_style,
}
)
return self.style
class DrawerDescription(DrawerComponent):
"""A description for the drawer."""
tag = "Drawer.Description"
alias = "Vaul" + tag
# Style set based on the source code at https://ui.shadcn.com/docs/components/drawer
def _get_style(self) -> dict:
"""Get the style for the component.
Returns:
The dictionary of the component style as value and the style notation as key.
"""
base_style = {
"font-size": "0.875rem",
}
style = self.style or {}
base_style.update(style)
self.style.update(
{
"css": base_style,
}
)
return self.style
class Drawer(SimpleNamespace):
"""A namespace for Drawer components."""
root = __call__ = staticmethod(DrawerRoot.create)
trigger = staticmethod(DrawerTrigger.create)
portal = staticmethod(DrawerPortal.create)
content = staticmethod(DrawerContent.create)
overlay = staticmethod(DrawerOverlay.create)
close = staticmethod(DrawerClose.create)
title = staticmethod(DrawerTitle.create)
description = staticmethod(DrawerDescription.create)
drawer = Drawer()