from typing import Any, Optional, Union from fasthtml.common import H1, Div, Li from monsterui.daisy import ( Alert, AlertT, ) from monsterui.foundations import stringify from monsterui.franken import ( H3, Button, ButtonT, Card, Container, ContainerT, Details, DivLAligned, DivRAligned, Form, Grid, Input, P, Summary, TabContainer, UkIcon, ) scrollbar_viewport_styles = ( "scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch;" ) scrollbar_cls = "flex touch-none select-none transition-colors p-[1px]" def ScrollArea( *c: Any, cls: Optional[Union[str, tuple]] = None, orientation: str = "vertical", **kwargs: Any ) -> Div: """Creates a styled scroll area. Args: orientation (str): The orientation of the scroll area. Defaults to vertical. """ new_cls = "relative overflow-hidden" if cls: new_cls += f" {stringify(cls)}" kwargs["cls"] = new_cls content = Div( Div(*c, style="min-width:100%;display:table;"), style=f"overflow: {'hidden scroll' if orientation == 'vertical' else 'scroll'}; {scrollbar_viewport_styles}", cls="w-full h-full rounded-[inherit]", data_ref="viewport", ) scrollbar = Div( Div(cls="bg-border rounded-full hidden relative flex-1", data_ref="thumb"), cls=f"{scrollbar_cls} flex-col h-2.5 w-full border-t border-t-transparent" if orientation == "horizontal" else f"{scrollbar_cls} w-2.5 h-full border-l border-l-transparent", data_ref="scrollbar", style=f"position: absolute;{'right:0; top:0;' if orientation == 'vertical' else 'bottom:0; left:0;'}", ) return Div( content, scrollbar, role="region", tabindex="0", data_orientation=orientation, data_ref_scrollarea=True, aria_label="Scrollable content", **kwargs, ) def Success(*c: Any) -> Alert: return Alert( DivLAligned( UkIcon("check"), P(*c), ), cls=AlertT.success, ) def Error(*c: Any) -> Alert: return Alert( DivLAligned( UkIcon("triangle-alert"), P(*c), ), cls=AlertT.error, ) def ConfigCard( config_name: str, config_type: str, read_only: str, value: str, default: str, description: str, deprecated: Optional[Union[str, bool]], update_error: Optional[str], update_value: Optional[str], update_open: Optional[bool], ) -> Card: """Creates a styled configuration card for displaying configuration details. This function generates a configuration card that is displayed in the UI with various sections such as configuration name, type, description, default value, current value, and error details. It supports both read-only and editable modes. Args: config_name (str): The name of the configuration. config_type (str): The type of the configuration. read_only (str): Indicates if the configuration is read-only ("rw" for read-write, any other value indicates read-only). value (str): The current value of the configuration. default (str): The default value of the configuration. description (str): A description of the configuration. deprecated (Optional[Union[str, bool]]): The deprecated marker of the configuration. update_error (Optional[str]): The error message, if any, during the update process. update_value (Optional[str]): The value to be updated, if different from the current value. update_open (Optional[bool]): A flag indicating whether the update section of the card should be initially expanded. Returns: Card: A styled Card component containing the configuration details. """ config_id = config_name.replace(".", "-") if not update_value: update_value = value if not update_open: update_open = False if deprecated: if isinstance(deprecated, bool): deprecated = "Deprecated" return Card( Details( Summary( Grid( Grid( DivLAligned( UkIcon(icon="play"), P(config_name), ), DivRAligned( P(read_only), ), ), P(value), ), cls="list-none", ), Grid( P(description), P(config_type), ) if not deprecated else None, Grid( P(deprecated), P("DEPRECATED!"), ) if deprecated else None, # Default Grid( DivRAligned(P("default")), P(default), ) if read_only == "rw" and not deprecated else None, # Set value Grid( DivRAligned(P("update")), Grid( Form( Input(value=config_name, type="hidden", id="key"), Input(value=update_value, type="text", id="value"), hx_put="/eosdash/configuration", hx_target="#page-content", hx_swap="innerHTML", ), ), ) if read_only == "rw" and not deprecated else None, # Last error Grid( DivRAligned(P("update error")), P(update_error), ) if update_error else None, cls="space-y-4 gap-4", open=update_open, ), cls="w-full", ) def DashboardHeader(title: Optional[str]) -> Div: """Creates a styled header with a title. Args: title (Optional[str]): The title text for the header. Returns: Div: A styled `Div` element containing the header. """ if title is None: return Div("", cls="header") return Div(H1(title, cls="text-2xl font-bold mb-4"), cls="header") def DashboardFooter(*c: Any, path: str) -> Card: """Creates a styled footer with the provided information. The footer content is reloaded every 5 seconds from path. Args: path (str): Path to reload footer content from Returns: Card: A styled `Card` element containing the footer. """ return Card( Container(*c, id="footer-content"), hx_get=f"{path}", hx_trigger="every 5s", hx_target="#footer-content", hx_swap="innerHTML", ) def DashboardTrigger(*c: Any, cls: Optional[Union[str, tuple]] = None, **kwargs: Any) -> Button: """Creates a styled button for the dashboard trigger. Args: *c: Positional arguments to pass to the button. cls (Optional[str]): Additional CSS classes for styling. Defaults to None. **kwargs: Additional keyword arguments for the button. Returns: Button: A styled `Button` component. """ new_cls = f"{ButtonT.primary}" if cls: new_cls += f" {stringify(cls)}" kwargs["cls"] = new_cls return Button(*c, submit=False, **kwargs) def DashboardTabs(dashboard_items: dict[str, str]) -> Card: """Creates a dashboard tab with dynamic dashboard items. Args: dashboard_items (dict[str, str]): A dictionary of dashboard items where keys are item names and values are paths for navigation. Returns: Card: A styled `Card` component containing the dashboard tabs. """ dash_items = [ Li( DashboardTrigger( H3(menu), hx_get=f"{path}", hx_target="#page-content", hx_swap="innerHTML", ), ) for menu, path in dashboard_items.items() ] return Card(TabContainer(*dash_items, cls="gap-4"), alt=True) def DashboardContent(content: Any) -> Card: """Creates a content section within a styled card. Args: content (Any): The content to display. Returns: Card: A styled `Card` element containing the content. """ return Card(ScrollArea(Container(content, id="page-content"), cls="h-[75vh] w-full rounded-md")) def Page( title: Optional[str], dashboard_items: dict[str, str], content: Any, footer_content: Any, footer_path: str, ) -> Div: """Generates a full-page layout with a header, dashboard items, content, and footer. Args: title (Optional[str]): The page title. dashboard_items (dict[str, str]): A dictionary of dashboard items. content (Any): The main content for the page. footer_content (Any): Footer content. footer_path (Any): Path to reload footer content from. Returns: Div: A `Div` element representing the entire page layout. """ return Container( DashboardHeader(title), DashboardTabs(dashboard_items), DashboardContent(content), DashboardFooter(footer_content, path=footer_path), cls=("bg-background text-foreground w-screen p-4 space-y-4", ContainerT.xl), )