// Html Module - DSL for building HTML/DOM structures
//
// This module provides a type-safe way to describe HTML elements that can be
// compiled to efficient JavaScript for browser rendering.
//
// Example usage:
// let myView = div([class("container")], [
// h1([id("title")], [text("Hello!")]),
// button([onClick(Increment)], [text("+")])
// ])
// Html type represents a DOM structure
// Parameterized by Msg - the type of messages emitted by event handlers
type Html =
| Element(String, List>, List>)
| Text(String)
| Empty
// Attributes that can be applied to elements
type Attr =
| Class(String)
| Id(String)
| Style(String, String)
| Href(String)
| Src(String)
| Alt(String)
| Type(String)
| Value(String)
| Placeholder(String)
| Disabled(Bool)
| Checked(Bool)
| Name(String)
| OnClick(M)
| OnInput(fn(String): M)
| OnSubmit(M)
| OnChange(fn(String): M)
| OnMouseEnter(M)
| OnMouseLeave(M)
| OnFocus(M)
| OnBlur(M)
| OnKeyDown(fn(String): M)
| OnKeyUp(fn(String): M)
| DataAttr(String, String)
// ============================================================================
// Element builders - Container elements
// ============================================================================
fn div(attrs: List>, children: List>): Html =
Element("div", attrs, children)
fn span(attrs: List>, children: List>): Html =
Element("span", attrs, children)
fn section(attrs: List>, children: List>): Html =
Element("section", attrs, children)
fn article(attrs: List>, children: List>): Html =
Element("article", attrs, children)
fn header(attrs: List>, children: List>): Html =
Element("header", attrs, children)
fn footer(attrs: List>, children: List>): Html =
Element("footer", attrs, children)
fn nav(attrs: List>, children: List>): Html =
Element("nav", attrs, children)
fn main(attrs: List>, children: List>): Html =
Element("main", attrs, children)
fn aside(attrs: List>, children: List>): Html =
Element("aside", attrs, children)
// ============================================================================
// Element builders - Text elements
// ============================================================================
fn h1(attrs: List>, children: List>): Html =
Element("h1", attrs, children)
fn h2(attrs: List>, children: List>): Html =
Element("h2", attrs, children)
fn h3(attrs: List>, children: List>): Html =
Element("h3", attrs, children)
fn h4(attrs: List>, children: List>): Html =
Element("h4", attrs, children)
fn h5(attrs: List>, children: List>): Html =
Element("h5", attrs, children)
fn h6(attrs: List>, children: List>): Html =
Element("h6", attrs, children)
fn p(attrs: List>, children: List>): Html =
Element("p", attrs, children)
fn pre(attrs: List>, children: List>): Html =
Element("pre", attrs, children)
fn code(attrs: List>, children: List>): Html =
Element("code", attrs, children)
fn blockquote(attrs: List>, children: List>): Html =
Element("blockquote", attrs, children)
// ============================================================================
// Element builders - Inline elements
// ============================================================================
fn a(attrs: List>, children: List>): Html =
Element("a", attrs, children)
fn strong(attrs: List>, children: List>): Html =
Element("strong", attrs, children)
fn em(attrs: List>, children: List>): Html =
Element("em", attrs, children)
fn small(attrs: List>, children: List>): Html =
Element("small", attrs, children)
fn br(): Html =
Element("br", [], [])
fn hr(): Html =
Element("hr", [], [])
// ============================================================================
// Element builders - Lists
// ============================================================================
fn ul(attrs: List>, children: List>): Html =
Element("ul", attrs, children)
fn ol(attrs: List>, children: List>): Html =
Element("ol", attrs, children)
fn li(attrs: List>, children: List>): Html =
Element("li", attrs, children)
// ============================================================================
// Element builders - Forms
// ============================================================================
fn form(attrs: List>, children: List>): Html =
Element("form", attrs, children)
fn input(attrs: List>): Html =
Element("input", attrs, [])
fn textarea(attrs: List>, children: List>): Html =
Element("textarea", attrs, children)
fn button(attrs: List>, children: List>): Html =
Element("button", attrs, children)
fn label(attrs: List>, children: List>): Html =
Element("label", attrs, children)
fn select(attrs: List>, children: List>): Html =
Element("select", attrs, children)
fn option(attrs: List>, children: List>): Html =
Element("option", attrs, children)
// ============================================================================
// Element builders - Media
// ============================================================================
fn img(attrs: List>): Html =
Element("img", attrs, [])
fn video(attrs: List>, children: List>): Html =
Element("video", attrs, children)
fn audio(attrs: List>, children: List>): Html =
Element("audio", attrs, children)
// ============================================================================
// Element builders - Tables
// ============================================================================
fn table(attrs: List>, children: List>): Html =
Element("table", attrs, children)
fn thead(attrs: List>, children: List>): Html =
Element("thead", attrs, children)
fn tbody(attrs: List>, children: List>): Html =
Element("tbody", attrs, children)
fn tr(attrs: List>, children: List>): Html =
Element("tr", attrs, children)
fn th(attrs: List>, children: List>): Html =
Element("th", attrs, children)
fn td(attrs: List>, children: List>): Html =
Element("td", attrs, children)
// ============================================================================
// Text and empty nodes
// ============================================================================
fn text(content: String): Html =
Text(content)
fn empty(): Html =
Empty
// ============================================================================
// Attribute helpers
// ============================================================================
fn class(name: String): Attr =
Class(name)
fn id(name: String): Attr =
Id(name)
fn style(property: String, value: String): Attr =
Style(property, value)
fn href(url: String): Attr =
Href(url)
fn src(url: String): Attr =
Src(url)
fn alt(description: String): Attr =
Alt(description)
fn inputType(t: String): Attr =
Type(t)
fn value(v: String): Attr =
Value(v)
fn placeholder(p: String): Attr =
Placeholder(p)
fn disabled(d: Bool): Attr =
Disabled(d)
fn checked(c: Bool): Attr =
Checked(c)
fn name(n: String): Attr =
Name(n)
fn onClick(msg: M): Attr =
OnClick(msg)
fn onInput(h: fn(String): M): Attr =
OnInput(h)
fn onSubmit(msg: M): Attr =
OnSubmit(msg)
fn onChange(h: fn(String): M): Attr =
OnChange(h)
fn onMouseEnter(msg: M): Attr =
OnMouseEnter(msg)
fn onMouseLeave(msg: M): Attr =
OnMouseLeave(msg)
fn onFocus(msg: M): Attr =
OnFocus(msg)
fn onBlur(msg: M): Attr =
OnBlur(msg)
fn onKeyDown(h: fn(String): M): Attr =
OnKeyDown(h)
fn onKeyUp(h: fn(String): M): Attr =
OnKeyUp(h)
fn data(name: String, value: String): Attr =
DataAttr(name, value)
// ============================================================================
// Utility functions
// ============================================================================
// Conditionally include an element
fn when(condition: Bool, element: Html): Html =
if condition then element else Empty
// Conditionally apply attributes
fn attrIf(condition: Bool, attr: Attr): List> =
if condition then [attr] else []