"""API for helpers, layout components, UI components, and style modifiers."""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.

# %% auto 0
__all__ = ['bc_link', 'tw_scr', 'fh_swiftui_hdrs', 'IncludeColors', 'mk_previewer', 'Color', 'Font', 'Text', 'TextField',
           'HStack', 'VStack', 'Spacer', 'HDivider', 'VDivider']

# %% ../nbs/00_core.ipynb 2
from fastcore.utils import *
from fasthtml.common import *
import fasthtml.components as fh
from fasthtml.jupyter import *
from enum import Enum
from fastcore.basics import store_attr

# %% ../nbs/00_core.ipynb 3
def _def_colors():
    base = ["primary","secondary","accent","muted","card","popover"]
    return base+[f"{o}-foreground" for o in base]+["background","foreground","destructive","ring","input","border"]
    

# %% ../nbs/00_core.ipynb 5
def IncludeColors(
    colors:list=None,  # Additional Tailwind color names to include (e.g., ['red-500', 'blue-300'])
    append:bool=True,  # Append to default theme colors; set `False` to replace all defaults
): # Hidden div with color classes to ensure they're included in Tailwind's build
    "Include additional colors that will be available via Tailwind utility classes on the page"
    from itertools import product
    if not colors: colors = []
    pr = [f"border-{o}" for o in "lrtb"] + ["bg", "text", "border"]
    return Div(cls=f"hidden {' '.join(f'{p}-{c}' for p,c in product(pr, _def_colors() + colors if append else colors))}")

# %% ../nbs/00_core.ipynb 6
# enable basecoat and tailwind; add useful default colors
bc_link = Link(rel='stylesheet', href='https://cdn.jsdelivr.net/npm/basecoat-css@latest/dist/basecoat.cdn.min.css')
tw_scr = Script(src='https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4')

fh_swiftui_hdrs = (bc_link,tw_scr,IncludeColors())


# %% ../nbs/00_core.ipynb 8
def mk_previewer(
    app=None,  # FastHTML app instance; defaults to app with fh_swiftui_hdrs
    hdrs=None, # Custom headers (unused, kept for API compatibility)
    cls:str='max-w-lg', # Tailwind max-width class (e.g., 'max-w-sm', 'max-w-xl', 'max-w-2xl')
): # Returns a previewer function `p(*c, cls='', **kw)` for rendering components in an iframe
    "Create a previewer function for rendering FastHTML components in iframes"
    xcls = cls
    if not app: app=FastHTML(hdrs=fh_swiftui_hdrs)
    def p(*c, cls='', **kw):
        return HTMX(Div(cls=f'{xcls} {cls}')(*c), app=app, host=None, port=None, **kw)
    return p

# %% ../nbs/00_core.ipynb 14
@patch
def append_classes(
    self:FT, # FastTag element to modify
    *c       # CSS class names to append
): # Modified FastTag element with classes appended
    "Append css classes to the FastTag element"
    self.attrs["class"] = " ".join(f"{self.attrs.get('class','')} {' '.join(c)}".split())
    return self

# %% ../nbs/00_core.ipynb 16
@patch
def padding(
    self:FT,        # FastTag element to modify
    all=None,       # equal padding on all sides 
    **kw,           # values for 4 edges: 'top', 'bottom', 'left', 'right'. Use Tailwind spacing (0-96, px, or '[<custom>]')
): # Modified FastTag with padding classes appended
    "Add padding around the content within the element's bounds. Defaults to p-4 if no arguments provided."
    if all is not None: return self.append_classes(f"p-{all}")
    edge = {"top":'t', "bottom":'b', "left":'l', "right":'r'}

    c = [f"p{edge[k]}-{kw[k]}" for k in set(kw) & edge.keys()]
    return self.append_classes(*c if c else ["p-4"])


# %% ../nbs/00_core.ipynb 22
@patch
def margin(
    self:FT,    # FastTag element to modify
    all=None,   # equal margins on all sides
    **kw,       # values for 4 edges: 'top', 'bottom', 'left', 'right'. Use Tailwind spacing (0-96, px, or '[<custom>]')
): # Modified FastTag with margin classes appended
    "Add margin (space outside) to the element. Defaults to m-4 if no arguments provided."
    if all is not None: return self.append_classes(f"m-{all}")
    edge = {"top":'t', "bottom":'b', "left":'l', "right":'r'}
    c = [f"m{edge[k]}-{kw[k]}" for k in set(kw) & edge.keys()]
    return self.append_classes(*c if c else ["m-4"])


# %% ../nbs/00_core.ipynb 27
@patch
def border(
    self:FT,        # FastTag element to modify
    width:int=None, # Border width as integer (0, 2, 4, 8, etc.) producing border-<width> class
    color:str=None, # Border color without 'border-' prefix (e.g., 'primary', 'muted', 'gray-300')
): # Modified FastTag with border classes appended
    "Add a border around the element with optional width and color customization"
    c = ["border"]
    if width: c.append(f"border-{width}")
    if color: c.append(f"border-{color}")
    return self.append_classes(*c)

# %% ../nbs/00_core.ipynb 33
@patch
def corner_radius(
    self:FT,       # FastTag element to modify
    size:str=None, # Tailwind size suffix: 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl', 'none', 'full', or '[<custom>]'
): # Modified FastTag with rounded corner class appended
    "Round the corners of this element. Defaults to 'rounded' (base radius) if no size provided."
    return self.append_classes(f"rounded-{size}" if size else "rounded")

# %% ../nbs/00_core.ipynb 40
from fastcore.basics import *

class Color:
    def __init__(self,hue,weight=None): store_attr()

    def __str__(self): return f"{self.hue}{f'-{self.weight}' if self.weight else ''}".lower()

    
_default_color_palette = dict(
    # Text hierarchy
    primary=["gray","900"],secondary=["gray","500"],muted=["gray","300"],
    background=["white",None],surface=["gray","50"],accent=["blue","600"],
    success=["green","600"],warning=["amber","500"],danger=["red","600"],info=["blue","500"],
    blue=["blue","500"],green=["green","500"],red=["red","500"],yellow=["yellow","500"],
    orange=["orange","500"],purple=["purple","500"],pink=["pink","500"],indigo=["indigo","500"],gray=["gray","500"],
)

def _init_color_palette(palette=None):
    if palette is None: palette = _default_color_palette
    for f,a in palette.items(): setattr(Color,f.capitalize(),Color(*a))

_init_color_palette()



# %% ../nbs/00_core.ipynb 42
@patch
def fg(
    self:FT,        # The FT tag this applies to
    c               # A color object or a tailwind color (e.g. red-500)
):
    "Set foreground/text color"
    return self.append_classes(f"text-{c}")

@patch
def bg(
    self:FT,        # The FT tag this applies to
    c               # A color object or a tailwind color (e.g. red-500)
):
    "Set background color"
    return self.append_classes(f"bg-{c}")

# %% ../nbs/00_core.ipynb 51
@patch
def shadow(
    self:FT, # FastTag element to modify
    **kw,    # Shadow options: 'size' (2xs/xs/sm/md/lg/xl/2xl/none), 'color' (CSS color), 'x'/'y'/'blur'/'spread' (int px offsets)
): # Modified FastTag with shadow class appended
    "Add shadow to element. Use 'size' for presets, or 'x'/'y'/'blur'/'spread'/'color' for custom shadows."
    if "color" not in kw: kw["color"] = "rgba(0,0,0,0.1)"
    if len(kw) == 1 and "color" in kw: return self.append_classes("shadow")
    if "size" in kw: return self.append_classes(f"shadow-{kw['size']}")
    def enc(color, x=0, y=1, blur=3, spread=0, **k2): return f"shadow-[{x}px_{y}px_{blur}px_{spread}px_{color}]"
    return self.append_classes(enc(**kw))

# %% ../nbs/00_core.ipynb 57
@patch
def opacity(
    self:FT,    # FastTag element to modify
    pct:int=100, # Opacity percentage (0, 5, 10, 15, 20, 25, 30, ..., 95, 100, or '[<custom>]' as string)
): # Modified FastTag with opacity class appended
    "Set element opacity using Tailwind opacity-<pct> utility class"
    return self.append_classes(f"opacity-{pct}")

# %% ../nbs/00_core.ipynb 64
@patch
def frame(
    self:FT,           # FastTag element to wrap in a frame
    w=None,            # Frame width: number (0-96), container size (xs-7xl), 'full', 'screen', 'auto', fraction, or '[<custom>]'
    h=None,            # Frame height: number (0-96), container size (xs-7xl), 'full', 'screen', 'auto', fraction, or '[<custom>]'
    halign:str="center", # Horizontal alignment: 'leading', 'center', 'trailing'
    valign:str="center", # Vertical alignment: 'top', 'center', 'bottom'
): # Div wrapping self with flex alignment and optional size classes
    "Position this element within a flex frame with optional sizing and alignment"
    h_map = {"leading": "justify-start", "center": "justify-center", "trailing": "justify-end"}
    v_map = {"top": "items-start", "center": "items-center", "bottom": "items-end"}
    c = ["flex", h_map[halign], v_map[valign]]
    if w: c.append(f"w-{w}")
    if h: c.append(f"h-{h}")
    return Div(self).append_classes(*c)

# %% ../nbs/00_core.ipynb 72
class Font(Enum):
    def __init__(self,size,weight="normal"): store_attr()

    @property
    def twcls(self): return f"text-{self.size}", f"font-{self.weight}"

    Title = ("2xl", "bold")
    Headline = ("xl", "semibold")
    Body = ("base", "normal")
    Caption = ("sm", "normal")
    Footnote = ("xs", "normal")



# %% ../nbs/00_core.ipynb 73
@patch
def font(
    self:FT,            # FastTag element to modify
    f:Font              # Font to use for this element
):
    "Set the font default font for this element"
    return self.append_classes(*f.twcls)

# %% ../nbs/00_core.ipynb 81
def Text(
    s: str          # the text string to display
):
    "this draws a string in your app’s user interface using a body font"
    return Span(s)

# %% ../nbs/00_core.ipynb 83
def TextField(
    name:str,                       # the name of the input field
    placeholder:str=None,           # placeholder for this
    **kw
):
    "displays an editable text field"
    return Input(name=name,placeholder=placeholder,**kw)

# %% ../nbs/00_core.ipynb 89
def _axial(alignment, spacing, axis): 
    def fn(*c): return Div(cls=f"flex flex-{axis} items-{alignment} gap-{spacing}")(*c)
    return fn

# %% ../nbs/00_core.ipynb 91
def HStack(
    *c,                # Child elements to arrange horizontally
    spacing=2,         # Gap between items (Tailwind spacing: 0, 0.5, 1, ..., 96, px, or '[<custom>]')
    alignment="start", # Vertical alignment: 'start', 'end', 'center', 'baseline', 'stretch'
): # Div with horizontal flex layout; partial function if no children provided
    "Arrange child elements horizontally in a row with configurable spacing and vertical alignment"
    fn = _axial(alignment, spacing, "row")
    return fn(*c) if c else fn

# %% ../nbs/00_core.ipynb 96
def VStack(
    *c,                # Child elements to arrange vertically
    spacing=2,         # Gap between items (Tailwind spacing: 0, 0.5, 1, 1.5, 2, ..., 96, px, or '[<custom>]')
    alignment="start", # Cross-axis alignment: 'start', 'end', 'center', 'baseline', 'stretch'
): # Div with vertical flex layout; partial function if no children provided
    "Arrange child elements vertically in a column with configurable spacing and horizontal alignment"
    fn = _axial(alignment, spacing, "col")
    return fn(*c) if c else fn

# %% ../nbs/00_core.ipynb 101
def Spacer():
    "A flexible space that expands along the major axis of its containing stack layout"
    return Div(cls="flex-grow")

# %% ../nbs/00_core.ipynb 106
def HDivider(
): # Div element styled as a horizontal divider with top border and vertical margin
    "A horizontal line that visually separates content within a vertical stack layout"
    return Div(cls="border-t w-full my-2")

# %% ../nbs/00_core.ipynb 110
def VDivider(
    color:str="muted", # Border color without 'border-l-' prefix (e.g., 'muted', 'gray-300', 'blue-500')
): # Div element styled as a vertical divider with left border and horizontal margin
    "A vertical line that visually separates content within a horizontal stack layout"
    return Div(cls=f"border-l-2 self-stretch mx-2 border-l-{color}")
