Sign in

    preact

    Type-safe MoonBit bindings for Preact with virtual DOM, hooks, and CSS-in-JS support (early experimental)

    preact
    binding
    Download zip
    Author
    Version
    0.0.1-a2
    License
    Apache-2.0
    Last updated
    last year
    Downloads
    41

    #tiye/preact

    MoonBit bindings for Preact

    ⚠️ Early Development Warning: This library is in a very early stage of development. The API is unstable and may change frequently. This is a hobby project and should not be used in production environments.

    #Quick Start

    Here's a simple example of how to use this library:

    // Define your component props
    struct ContainerProps {} derive(Default)

    // Implement JsValueTrait for props
    impl @preact.JsValueTrait for ContainerProps with to_value(_self) -> @preact.JsValue {
    @preact.JsObject::new().to_value()
    }

    impl @preact.JsValueTrait for ContainerProps with from_value(
    _value : @preact.JsValue,
    ) -> ContainerProps {
    ContainerProps::default()
    }

    // Create a functional component
    fn comp_container(_v : ContainerProps) -> @preact.VirtualNode {
    let (counter, set_counter) = @preact.use_state(0.0.to_float())

    @preact.div(
    id="container",
    style=@css.respo_style(
    color=Blue,
    font_family="Arial",
    padding=10.0 |> Px
    ),
    on_click=fn(_) {
    println("clicked \{counter}")
    set_counter(counter + 1.0)
    },
    [
    @preact.Fragment([Text("Demo: ")]),
    Text("Counter \{counter}")
    ],
    )
    }

    // Render to DOM
    fn main {
    let window = @dom.window()
    let doc = window.document()
    let body = doc.body()
    let props = ContainerProps::default()

    @preact.render(
    @preact.component(comp_container, props, []),
    body,
    )
    println("loaded")
    }

    #Features

    • Type-safe virtual DOM construction
    • React-style hooks (useState)
    • CSS-in-JS styling support
    • Event handling
    • Component composition

    #Project Status

    This is an experimental hobby project exploring MoonBit bindings for Preact. The API is subject to frequent changes and breaking updates. Use at your own risk!

    #License

    Apache 2.0

    CastJsValueTrait

    pub(open) trait CastJsValueTrait {
    to_js_value(Self) -> JsValue = _
    }

    JsValueTrait

    pub(open) trait JsValueTrait {
    to_value(Self) -> JsValue
    from_value(JsValue) -> Self
    }

    impl JsValueTrait for Int

    DOMEvent

    pub type DOMEvent

    DOMEvent::alt_key

    fn DOMEvent::alt_key(self : DOMEvent) -> Bool

    检查是否按下了 Alt 键

    DOMEvent::client_x

    fn DOMEvent::client_x(self : DOMEvent) -> Int

    获取鼠标事件的 X 坐标

    DOMEvent::client_y

    fn DOMEvent::client_y(self : DOMEvent) -> Int

    获取鼠标事件的 Y 坐标

    DOMEvent::ctrl_key

    fn DOMEvent::ctrl_key(self : DOMEvent) -> Bool

    检查是否按下了 Ctrl 键

    DOMEvent::key

    fn DOMEvent::key(self : DOMEvent) -> String

    获取键盘事件的键值

    DOMEvent::key_code

    fn DOMEvent::key_code(self : DOMEvent) -> Int

    获取键盘事件的键码

    DOMEvent::meta_key

    fn DOMEvent::meta_key(self : DOMEvent) -> Bool

    检查是否按下了 Meta 键(Mac 上的 Cmd 键)

    DOMEvent::prevent_default

    fn DOMEvent::prevent_default(self : DOMEvent) -> Unit

    阻止事件的默认行为

    DOMEvent::shift_key

    fn DOMEvent::shift_key(self : DOMEvent) -> Bool

    检查是否按下了 Shift 键

    DOMEvent::stop_propagation

    fn DOMEvent::stop_propagation(self : DOMEvent) -> Unit

    阻止事件冒泡

    DOMEvent::target_value

    fn DOMEvent::target_value(self : DOMEvent) -> String

    获取事件目标元素的值(通常用于 input、textarea 等表单元素)

    DOMEvent::to_js_any_value

    fn DOMEvent::to_js_any_value(self : DOMEvent) -> JsValue

    DOMEventType

    pub(all) enum DOMEventType {
    Click
    DoubleClick
    MouseDown
    MouseUp
    MouseMove
    MouseEnter
    MouseLeave
    MouseOver
    MouseOut
    ContextMenu
    KeyDown
    KeyUp
    KeyPress
    Input
    Change
    Submit
    Reset
    Focus
    Blur
    Select
    Load
    Unload
    Resize
    Scroll
    Drag
    DragStart
    DragEnd
    DragEnter
    DragLeave
    DragOver
    Drop
    TouchStart
    TouchMove
    TouchEnd
    TouchCancel
    Error
    Abort
    CanPlay
    CanPlayThrough
    DurationChange
    Ended
    LoadedData
    LoadedMetadata
    LoadStart
    Pause
    Play
    Playing
    Progress
    RateChange
    Seeked
    Seeking
    Stalled
    Suspend
    TimeUpdate
    VolumeChange
    Waiting
    }

    DOM 事件类型枚举
    impl Eq for DOMEventType

    DOMEventType::to_string

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

    将 DOMEventType 转换为字符串

    ElementAttrs

    pub type ElementAttrs Map[String, String]

    ElementAttrs::add

    fn ElementAttrs::add(self : ElementAttrs, key : String, value : String) -> ElementAttrs

    ElementAttrs::inner

    #deprecated("Use `struct T(A)` to declare a newtype and use `.0` access the underlying type instead.")
    fn ElementAttrs::inner(self : ElementAttrs) -> Map[String, String]
    Convert newtype to its underlying type, automatically derived.

    ElementAttrs::new

    ElementAttrs::set

    fn ElementAttrs::set(self : ElementAttrs, key : String, value : String) -> Unit

    ElementEvents

    type ElementEvents

    ElementEvents::add

    fn ElementEvents::add(self : ElementEvents, event_type : DOMEventType, value : (DOMEvent) -> Unit) -> ElementEvents

    使用 DOMEventType 添加事件处理器

    ElementEvents::new

    ElementEvents::set

    fn ElementEvents::set(self : ElementEvents, event_type : DOMEventType, value : (DOMEvent) -> Unit) -> Unit

    使用 DOMEventType 设置事件处理器

    ElementEvents::to_js_value

    fn ElementEvents::to_js_value(self : ElementEvents) -> JsValue

    InputType

    pub(all) enum InputType {
    Button
    Checkbox
    Color
    Date
    DatetimeLocal
    Email
    File
    Hidden
    Image
    Month
    Number
    Password
    Radio
    Range
    Reset
    Search
    Submit
    Tel
    Text
    Time
    Url
    Week
    }

    HTML input element type enumeration based on MDN specification https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input
    impl Eq for InputType

    InputType::to_string

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

    Converts InputType enum to its corresponding HTML string value

    JsArray

    pub type JsArray

    JsArray::as_value

    fn JsArray::as_value(self : JsArray) -> JsValue

    JsArray::new

    fn JsArray::new() -> JsArray

    JsArray::op_get

    fn JsArray::op_get(self : JsArray, index : Int) -> JsValue

    JsArray::op_set

    fn JsArray::op_set(self : JsArray, index : Int, value : JsValue) -> Unit

    JsArray::to_string

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

    JsObject

    type JsObject

    JsObject::as_value

    fn JsObject::as_value(self : JsObject) -> JsValue

    Converts a JavaScript object to a JavaScript value.

    Parameters:

    • self : The JavaScript object to convert.

    Returns a JsValue representing the same object.

    Example:

    let obj = @tiye/preact.JsObject::new()
    let _value = obj.as_value()

    JsObject::get

    fn JsObject::get(self : JsObject, key : String) -> JsValue

    JsObject::new

    fn JsObject::new() -> JsObject

    JsValue

    type JsValue

    JsValue::from_object

    fn JsValue::from_object(value : JsObject) -> JsValue

    VirtualElement

    pub struct VirtualElement {
    name : String
    attrs : ElementAttrs
    event : ElementEvents
    style :
    RespoStyle

    children : Array[VirtualNode]
    }

    Represents a virtual DOM element with all its properties and children.

    This structure encapsulates all the information needed to create and manage a DOM element in the virtual DOM tree, including its tag name, attributes, event handlers, styles, and child nodes.

    VirtualElement::to_node

    VirtualNode

    pub(all) enum VirtualNode {
    Element(VirtualElement)
    Fragment(Array[VirtualNode])
    Text(String)
    JsNode(JsValue)
    }

    Represents a virtual DOM node in the Preact rendering system.

    This is the core type for building virtual DOM trees. Each variant represents a different kind of node that can be rendered to the actual DOM.

    VirtualNode::to_js_value

    fn VirtualNode::to_js_value(self : VirtualNode) -> JsValue

    fn a(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, href? : String, target? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an a element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing an a element.

    article

    fn article(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an article element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing an article element.

    aside

    fn aside(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an aside element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing an aside element.

    audio

    fn audio(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], src? : String, controls? : Bool, autoplay? : Bool, loop_enabled? : Bool, muted? : Bool, on_play? : (DOMEvent) -> Unit, on_pause? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an audio element with the specified attributes, event handlers, and audio properties.

    Returns a virtual DOM node representing an audio element.

    button

    fn button(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, button_type? : String, disabled? : Bool, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a button element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing a button element.

    component

    fn[T : JsValueTrait] component(f : (T) -> VirtualNode, props : T, children : Array[VirtualNode]) -> VirtualNode

    Creates a component virtual node from a function, props, and children.

    This bridges MoonBit component functions with Preact's rendering system, enabling type-safe component creation with strongly-typed props.

    Example

    struct ButtonProps {
    text : String
    disabled : Bool
    } derive(Default)

    fn my_button(props : ButtonProps) -> VirtualNode {
    button(disabled=props.disabled, [Text(props.text)])
    }

    let node = component(my_button, ButtonProps { text: "Click me", disabled: false }, [])

    console_log2

    fn console_log2(msg : String, v : JsValue) -> Unit

    contained_static_style

    #callsite(autofill(loc))
    fn[U : Show] contained_static_style(rules : Array[(String?, U,
    RespoStyle
    )], loc~ : SourceLoc) -> String

    Declare a static style in the head of the documentm for example
    let style_demo : String = contained_static_style(
    [(Some("@media only screen and (max-width: 600px)"), "&", respo_style(margin=4 |> Px, background_color=Hsl(200, 90, 96)))],
    )

    create_element

    fn create_element(name : String, attrs : ElementAttrs, event : ElementEvents, style~ :
    RespoStyle
    , children : Array[VirtualNode]) -> VirtualElement

    Creates a virtual DOM element with the specified properties.

    This is the internal implementation used by built-in element functions like div, span, etc. It can also be used to create custom HTML elements that are not provided by the library.

    Parameters

    • name: HTML tag name (e.g., "div", "span", "custom-element")
    • attrs: Element attributes
    • event: Event handlers
    • style: CSS styles
    • children: Child virtual nodes

    Example

    // Create a custom element
    let _custom_elem = create_element(
    "my-custom-element",
    ElementAttrs::new(),
    ElementEvents::new(),
    style=@css.respo_style(),
    [Text("Custom content")]
    )

    declare_contained_style

    #deprecated("This function is deprecated.")
    #callsite(autofill(loc))
    fn[U : Show] declare_contained_style(rules : Array[(String?, U,
    RespoStyle
    )], loc~ : SourceLoc) -> String

    use contained_static_style instead

    div

    fn div(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    fn footer(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a footer element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing a footer element.

    fn h1(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an h1 element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing an h1 element.

    fn h2(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an h2 element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing an h2 element.

    fn h3(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an h3 element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing an h3 element.

    fn h4(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an h4 element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing an h4 element.

    fn h5(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an h5 element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing an h5 element.

    fn h6(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an h6 element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing an h6 element.

    fn header(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a header element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing a header element.

    img

    fn img(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , src? : String, alt? : String, width? : String, height? : String, on_click? : (DOMEvent) -> Unit, on_load? : (DOMEvent) -> Unit, on_error? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an img element with the specified attributes, event handlers, and image properties.

    Returns a virtual DOM node representing an img element.

    input

    fn input(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , type_? : InputType, value? : String, placeholder? : String, disabled? : Bool, on_click? : (DOMEvent) -> Unit, on_change? : (DOMEvent) -> Unit, on_input? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an input element with the specified attributes, event handlers, and properties.

    Returns a virtual DOM node representing an input element.

    label

    fn label(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit, for_? : String) -> VirtualNode

    Creates a label element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing a label element.

    fn li(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a li (list item) element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing a li element.

    fn nav(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a nav element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing a nav element.

    fn ol(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates an ol (ordered list) element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing an ol element.

    option

    fn option(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, value? : String, selected? : Bool, disabled? : Bool) -> VirtualNode

    Creates an option element with the specified attributes and properties.

    Returns a virtual DOM node representing an option element.

    fn p(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a p element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing a p element.

    render

    fn render(vdom : VirtualNode, parent :
    Element
    ) -> Unit

    Renders a virtual DOM node to the specified parent element.

    This function takes a virtual DOM node and a parent DOM element, then uses the Preact rendering engine to render the virtual node as a real DOM element within the parent.

    Parameters

    • vdom: The virtual DOM node to render.
    • parent: The parent DOM element where the rendered node will be appended.

    Example

    // Render a virtual element to the document body
    let custom_elem = create_element(
    "my-custom-element",
    ElementAttrs::new(),
    ElementEvents::new(),
    style=@css.respo_style(),
    [Text("Custom content")]
    )
    render(custom_elem.to_node(), document.body)

    section

    fn section(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a section element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing a section element.

    select

    fn select(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], value? : String, disabled? : Bool, multiple? : Bool, on_change? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a select element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing a select element.

    span

    fn span(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a span element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing a span element.

    Example:

    let _ = span(
    class_name="text-bold",
    on_click=fn(_e) { println("Clicked!") }, []
    )

    static_style

    #callsite(autofill(loc))
    fn[U : Show] static_style(rules : Array[(U,
    RespoStyle
    )], loc~ : SourceLoc) -> String

    Declare a static style in the head of the documentm for example
    let style_demo : String = static_style(
    [("&", respo_style(margin=4 |> Px, background_color=Hsl(200, 90, 96)))],
    )

    textarea

    fn textarea(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , value? : String, placeholder? : String, rows? : Int, cols? : Int, disabled? : Bool, on_change? : (DOMEvent) -> Unit, on_input? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a textarea element with the specified attributes, event handlers, and properties.

    Returns a virtual DOM node representing a textarea element.

    fn ul(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], innerHTML? : String, on_click? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a ul (unordered list) element with the specified attributes, event handlers, and children.

    Returns a virtual DOM node representing a ul element.

    use_state

    fn[T] use_state(initial : T) -> (T, (T) -> Unit)

    video

    fn video(id? : String, class_name? : String, class_list? : Array[String], attrs? : ElementAttrs, event? : ElementEvents, style? :
    RespoStyle
    , children : Array[VirtualNode], src? : String, controls? : Bool, autoplay? : Bool, loop_enabled? : Bool, muted? : Bool, width? : String, height? : String, on_click? : (DOMEvent) -> Unit, on_play? : (DOMEvent) -> Unit, on_pause? : (DOMEvent) -> Unit) -> VirtualNode

    Creates a video element with the specified attributes, event handlers, and video properties.

    Returns a virtual DOM node representing a video element.