Sign in

    #Luna Core

    Core functionality of the Luna UI library. Platform-independent.

    #Module Structure

    SubmoduleResponsibility
    signal/Reactive primitives (Signal, Effect, Computed)
    render/VNode → HTML string rendering
    routes/Type-safe routing
    serialize/State serialization/deserialization
    vnode.mbtVNode type definitions

    #VNode

    Virtual DOM node. Type parameter E represents the event type.

    pub enum Node[E] {
    Element(VElement[E]) // HTML element
    Text(String) // Static text
    DynamicText(() -> String) // Dynamic text
    Fragment(Array[Node[E]]) // Fragment
    Show(...) // Conditional rendering
    For(...) // List rendering
    Island(VIsland[E]) // Hydration boundary
    WcIsland(VWcIsland[E]) // Web Components Island
    Async(VAsync[E]) // Async node
    // ...
    }

    #Signal

    Reactive value container.

    let count = @signal.signal(0)
    count.get() // 0
    count.set(1) // Set value
    count.update(fn(n) { n + 1 }) // Update function

    // Derived value
    let doubled = @signal.computed(fn() { count.get() * 2 })

    // Side effects
    @signal.effect(fn() {
    println(count.get())
    })

    #Attr

    Attribute values. Supports static/dynamic/event handlers.

    pub enum Attr[E] {
    VStatic(String) // Static value
    VDynamic(() -> String) // Signal-linked
    VHandler(EventHandler[E]) // Event handler
    VAction(String) // Declarative action
    }

    #TriggerType

    Hydration triggers.

    pub enum TriggerType {
    Load // On page load
    Idle // On requestIdleCallback
    Visible // On IntersectionObserver detection
    Media(String) // On media query match
    None // Manual trigger
    }

    #References

    Attr

    pub enum Attr[E] {
    VStatic(String)
    VDynamic(() -> String)
    VHandler(EventHandler[E])
    VAction(String)
    }

    Attribute value that can be static or dynamic (signal-based)

    ComponentRef

    pub(all) struct ComponentRef[T] {
    url : String
    props : T
    wc : Bool
    trigger : TriggerType
    }

    Component reference for type-safe Island embedding Represents a client-side component that can be embedded in server-rendered HTML
    • url: Path to the client JavaScript (e.g., "/static/counter.js")
    • props: Component props (must be ToJson serializable)
    • wc: Whether this is a Web Components based Island
    • trigger: When to hydrate the component

    EventHandler

    pub struct EventHandler[E] {
    callback : (E) -> Unit
    }

    Event handler type - newtype wrapper for callback function

    EventHandler::get_callback

    fn[E] EventHandler::get_callback(self : EventHandler[E]) -> ((E) -> Unit)

    Get the callback function

    MatchCase

    pub struct MatchCase[E] {
    when : () -> Bool
    render : () -> Node[E]
    }

    Match case for Switch - pairs a condition with content

    Node

    pub enum Node[E] {
    Element(VElement[E])
    Text(String)
    DynamicText(() -> String)
    Fragment(Array[Node[E]])
    Show(() -> Bool, () -> Node[E])
    For(() -> Array[Node[E]])
    Component(() -> Node[E])
    Island(VIsland[E])
    WcIsland(VWcIsland[E])
    Async(VAsync[E])
    ErrorBoundary(VErrorBoundary[E])
    Switch(VSwitch[E])
    InternalRef(VInternalRef[E])
    RawHtml(String)
    }

    Virtual DOM node types

    TriggerType

    #alias(Trigger)
    pub(all) enum TriggerType {
    Load
    Idle
    Visible
    Media(String)
    None
    }

    Hydration trigger types - when to hydrate a component

    TriggerType::parse

    fn TriggerType::parse(s : String) -> TriggerType

    Parse TriggerType from string

    TriggerType::to_string

    fn TriggerType::to_string(self : TriggerType) -> String

    Convert TriggerType to attribute value

    VAsync

    pub struct VAsync[E] {
    render : async () -> Node[E]
    fallback : () -> Node[E]
    on_error : (Error) -> Node[E]?
    }

    Virtual Async node for async rendering with error handling Note: async functions implicitly raise Error, no need for raise? annotation

    VElement

    pub struct VElement[E] {
    tag : String
    attrs : Array[(String, Attr[E])]
    children : Array[Node[E]]
    }

    Virtual element node

    VErrorBoundary

    pub struct VErrorBoundary[E] {
    children : () -> Node[E] raise
    fallback : (Error, () -> Unit) -> Node[E] raise
    }

    Virtual ErrorBoundary node for catching rendering errors Similar to Solid.js ErrorBoundary - catches errors during:
    • Child component rendering
    • Effects and memos within children Does NOT catch:
    • Event handler errors
    • Async errors outside render cycle

    VInternalRef

    pub struct VInternalRef[E] {
    url : String
    state : String
    trigger : TriggerType
    wc : Bool
    styles : String
    children : Array[Node[E]]
    }

    Virtual Internal Reference node for type-safe Island embedding

    VIsland

    pub struct VIsland[E] {
    id : String
    url : String
    state : String
    trigger : TriggerType
    children : Array[Node[E]]
    }

    Virtual Island node - serializable hydration unit

    VSwitch

    pub struct VSwitch[E] {
    cases : Array[MatchCase[E]]
    fallback : () -> Node[E]?
    }

    Virtual Switch node - renders first matching case Similar to Solid.js /
    • cases: array of condition-content pairs, evaluated in order
    • fallback: optional content when no case matches

    VWcIsland

    pub struct VWcIsland[E] {
    name : String
    url : String
    styles : String
    state : String
    trigger : TriggerType
    children : Array[Node[E]]
    }

    Virtual Web Components Island node - Web Components based hydration unit Uses Declarative Shadow DOM for SSR and DOM Parts for partial updates

    action

    fn[E, A : Show] action(a : A) -> Attr[E]

    Create an action attribute value - dispatches named action on event Used for declarative event handling with enum types: ("onclick", action(Increment)) // requires derive(Show)

    Example:
    pub enum MyAction { Increment; Decrement } derive(Show) @luna.h("button", [("onclick", action(Increment))], [...])

    async_

    fn[E] async_(render~ : async () -> Node[E], fallback~ : () -> Node[E], on_error? : (Error) -> Node[E]?) -> Node[E]

    Create an async VNode with fallback
    • render: async function that produces the content (may raise errors)
    • fallback: shown while loading or on error (if no on_error handler)
    • on_error: optional custom error UI handler

    attr_dynamic

    fn[E] attr_dynamic(getter : () -> String) -> Attr[E]

    Create a dynamic attribute value

    attr_dynamic_style

    fn[E] attr_dynamic_style(getter : () -> String) -> Attr[E]

    Create a dynamic style attribute value

    attr_handler

    fn[E] attr_handler(handler : EventHandler[E]) -> Attr[E]

    Create a handler attribute value

    attr_static

    fn[E] attr_static(value : String) -> Attr[E]

    Create a static attribute value

    attr_style

    fn[E] attr_style(style : String) -> Attr[E]

    Create a style attribute value (string form, e.g. "color: red; margin: 10px")

    component

    fn[E] component(render : () -> Node[E]) -> Node[E]

    Create a component VNode

    component_ref

    fn[T] component_ref(url : String, props : T, trigger? : TriggerType) -> ComponentRef[T]

    Create a ComponentRef for a regular Island component

    error_boundary

    fn[E] error_boundary(children~ : () -> Node[E] raise, fallback~ : (Error, () -> Unit) -> Node[E] raise) -> Node[E]

    Create an error boundary VNode Catches errors during child rendering and displays fallback UI
    • children: lazy function that produces child content (may throw)
    • fallback: function receiving (error, reset) that produces fallback UI
      • error: the caught Error
      • reset: function to retry rendering children

    Example:
    error_boundary( children=fn() { risky_component() }, fallback=fn(err, reset) { h("div", [], [ text("Error: " + err.to_string()), h("button", [("onclick", handler(fn(_) { reset() }))], [text("Retry")]) ]) } )

    event_handler

    fn event_handler() -> EventHandler[Unit]

    Create a placeholder event handler for SSR (noop)

    for_each

    fn[E] for_each(items : () -> Array[Node[E]]) -> Node[E]

    Create a list VNode

    fragment

    fn[E] fragment(children : Array[Node[E]]) -> Node[E]

    Create a fragment VNode
    fn[E] h(tag : String, attrs : Array[(String, Attr[E])], children : Array[Node[E]]) -> Node[E]

    Create a VNode element

    handler

    fn[E] handler(f : (E) -> Unit) -> EventHandler[E]

    Create an event handler from a callback

    handler_from_callback

    fn handler_from_callback(f : () -> Unit) -> EventHandler[Unit]

    Create an event handler from a simple callback (ignores event, for SSR compatibility)

    has_dynamic_content

    fn[E] has_dynamic_content(attrs : Array[(String, Attr[E])]) -> Bool

    Check if element has dynamic content that needs hydration

    internal_ref

    fn[E] internal_ref(url : String, state : String, trigger? : TriggerType, wc? : Bool, styles? : String, children? : Array[Node[E]]) -> Node[E]

    Create an internal reference VNode (for server_dom.island())

    island

    fn[E] island(id : String, url : String, state : String, children : Array[Node[E]], trigger? : TriggerType) -> Node[E]

    Create an island VNode for partial hydration

    match_case

    fn[E] match_case(when~ : () -> Bool, render~ : () -> Node[E]) -> MatchCase[E]

    Create a match case for Switch
    • when: condition function, evaluated lazily
    • render: content to render when condition is true

    raw_html

    fn[E] raw_html(content : String) -> Node[E]

    Create a raw HTML VNode (content is not escaped) Use with caution: content should be trusted or sanitized

    show

    fn[E] show(when : () -> Bool, child : () -> Node[E]) -> Node[E]

    Create a conditional VNode

    switch_

    fn[E] switch_(cases~ : Array[MatchCase[E]], fallback? : () -> Node[E]?) -> Node[E]

    Create a switch VNode - renders first matching case Similar to Solid.js /

    Example:
    switch_( cases=[ match_case(when=fn() { state.get() == 1 }, render=fn() { text("One") }), match_case(when=fn() { state.get() == 2 }, render=fn() { text("Two") }), ], fallback=Some(fn() { text("Other") }) )

    text

    fn[E] text(content : String) -> Node[E]

    Create a text VNode

    text_dyn

    fn[E] text_dyn(content : () -> String) -> Node[E]

    Create a dynamic text VNode

    text_of

    fn[E, T : Show] text_of(sig :
    Signal
    [T]) -> Node[E]

    Create a text VNode from a signal

    wc_component_ref

    fn[T] wc_component_ref(url : String, props : T, trigger? : TriggerType) -> ComponentRef[T]

    Create a ComponentRef for a Web Components Island

    wc_island

    fn[E] wc_island(name : String, url : String, styles : String, state : String, children : Array[Node[E]], trigger? : TriggerType) -> Node[E]

    Create a Web Components island VNode for partial hydration Uses Declarative Shadow DOM for SSR