///|
/// HTML input element type enumeration based on MDN specification
/// https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input
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
} derive(Eq)
///|
/// Converts InputType enum to its corresponding HTML string value
pub fn InputType::to_string(self : InputType) -> String {
match self {
Button => "button"
Checkbox => "checkbox"
Color => "color"
Date => "date"
DatetimeLocal => "datetime-local"
Email => "email"
File => "file"
Hidden => "hidden"
Image => "image"
Month => "month"
Number => "number"
Password => "password"
Radio => "radio"
Range => "range"
Reset => "reset"
Search => "search"
Submit => "submit"
Tel => "tel"
Text => "text"
Time => "time"
Url => "url"
Week => "week"
}
}
///|
/// Creates a `span` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing a `span` element.
///
/// Example:
///
/// ```moonbit nocheck
/// let _ = span(
/// class_name="text-bold",
/// on_click=fn(_e) { println("Clicked!") }, []
/// )
/// ```
///
pub fn span(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the span element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "span", attrs, event, style, children })
}
///|
/// Creates a `p` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing a `p` element.
///
pub fn p(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the p element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "p", attrs, event, style, children })
}
///|
/// Creates a `label` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing a `label` element.
///
pub fn label(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the label element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
/// The "for" attribute to associate the label with a form control.
for_? : String,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
if for_ is Some(for_value) {
attrs.set("htmlFor", for_value)
}
Element({ name: "label", attrs, event, style, children })
}
///|
/// Creates an `h1` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing an `h1` element.
///
pub fn h1(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the h1 element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "h1", attrs, event, style, children })
}
///|
/// Creates an `h2` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing an `h2` element.
///
pub fn h2(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the h2 element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "h2", attrs, event, style, children })
}
///|
/// Creates an `h3` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing an `h3` element.
///
pub fn h3(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the h3 element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "h3", attrs, event, style, children })
}
///|
/// Creates an `h4` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing an `h4` element.
///
pub fn h4(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the h4 element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "h4", attrs, event, style, children })
}
///|
/// Creates an `h5` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing an `h5` element.
///
pub fn h5(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the h5 element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "h5", attrs, event, style, children })
}
///|
/// Creates an `h6` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing an `h6` element.
///
pub fn h6(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the h6 element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "h6", attrs, event, style, children })
}
///|
/// Creates an `a` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing an `a` element.
///
pub fn a(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the a element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// The URL that the hyperlink points to.
href? : String,
/// Where to display the linked URL (e.g., "_blank", "_self").
target? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if href is Some(href) {
attrs.set("href", href)
}
if target is Some(target) {
attrs.set("target", target)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "a", attrs, event, style, children })
}
///|
/// Creates a `div` element with optional React attributes, events, styles, raw
/// HTML, and child nodes.
///
/// Do not provide both `innerHTML` and non-empty `children`; React elements must
/// have exactly one content source.
pub fn div(
id? : String,
class_name? : String,
class_list? : Array[String] = [],
attrs? : ElementAttrs,
event? : ElementEvents,
style? : RespoStyle = respo_style(),
children : Array[VirtualNode],
innerHTML? : String,
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "div", attrs, event, style, children })
}
///|
/// Creates a React form. A function-valued `action` runs in a React Action and
/// receives the submitted `ReactFormData` payload.
pub fn form(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child form controls.
children : Array[VirtualNode],
/// Typed React Action. Function actions submit with POST semantics.
action? : FormAction,
/// Native form method. React function actions use POST regardless of this
/// value, matching React 19 behavior.
method_? : String,
/// Conventional submit event handler for non-Action forms.
on_submit? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if action is Some(action) {
attrs.set_js_value("action", action.to_js_value())
}
if method_ is Some(method_) {
attrs.set("method", method_)
}
if on_submit is Some(on_submit) {
event.set(Submit, on_submit)
}
Element({ name: "form", attrs, event, style, children })
}
///|
/// Combines a base class name with a list of additional class names into a
/// single string, with class names separated by spaces. Returns `None` if both
/// inputs are empty.
fn combine_classes(class_name : String?, class_list : Array[String]) -> String? {
let mut class_content = ""
if class_name is Some(class_name) {
class_content += " " + class_name
}
if !class_list.is_empty() {
for class_name in class_list {
class_content += " " + class_name
}
}
class_content = class_content.trim(chars=" ").to_owned()
if class_content.is_empty() {
None
} else {
Some(class_content)
}
}
///|
/// Creates an `input` element with the specified attributes, event handlers, and
/// properties.
///
/// Returns a virtual DOM node representing an `input` element.
///
pub fn input(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// The type of input (e.g., Text, Password, Email).
type_? : InputType,
/// Form field name.
name? : String,
/// The current value of the input.
value? : String,
/// The initial value of an uncontrolled input. Do not combine with `value`.
default_value? : String,
/// Placeholder text displayed when input is empty.
placeholder? : String,
/// Whether the input is disabled.
disabled? : Bool,
/// Whether a controlled input is intentionally read-only.
read_only? : Bool,
/// Controlled checked value for checkbox and radio inputs. Unlike `disabled`,
/// this is emitted for both true and false values.
checked? : Bool,
/// Initial checked state for an uncontrolled checkbox or radio input. Do not
/// combine with `checked`.
default_checked? : Bool,
/// Overrides the parent form Action for submit and image inputs.
form_action? : FormAction,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
/// Change event handler (fired when value changes and input loses focus).
on_change? : (DOMEvent) -> Unit,
/// Input event handler (fired on every keystroke).
on_input? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if form_action is Some(_) &&
type_ != Some(InputType::Submit) &&
type_ != Some(InputType::Image) {
abort("React input formAction requires type=Submit or type=Image")
}
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if type_ is Some(input_type) {
attrs.set("type", input_type.to_string())
}
if name is Some(name) {
attrs.set("name", name)
}
if value is Some(value) {
attrs.set("value", value)
}
if default_value is Some(default_value) {
attrs.set("defaultValue", default_value)
}
if placeholder is Some(placeholder) {
attrs.set("placeholder", placeholder)
}
if disabled is Some(true) {
attrs.set_bool("disabled", true)
}
if read_only is Some(read_only) {
attrs.set_bool("readOnly", read_only)
}
if checked is Some(checked) {
attrs.set_bool("checked", checked)
}
if default_checked is Some(default_checked) {
attrs.set_bool("defaultChecked", default_checked)
}
if form_action is Some(form_action) {
attrs.set_js_value("formAction", form_action.to_js_value())
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
if on_change is Some(on_change) {
event.set(Change, on_change)
}
if on_input is Some(on_input) {
event.set(Input, on_input)
}
Element({ name: "input", attrs, event, style, children: [] })
}
///|
/// Creates a `button` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing a `button` element.
///
pub fn button(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the button element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// The type of button (e.g., "button", "submit", "reset").
button_type? : String,
/// Form field name for submitter payloads.
name? : String,
/// Form field value for submitter payloads.
value? : String,
/// Whether the button is disabled.
disabled? : Bool,
/// Overrides the parent form Action. This is valid only for submit buttons.
form_action? : FormAction,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if form_action is Some(_) &&
button_type is Some(button_type) &&
button_type != "submit" {
abort("React button formAction requires a submit button")
}
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if button_type is Some(button_type) {
attrs.set("type", button_type)
}
if name is Some(name) {
attrs.set("name", name)
}
if value is Some(value) {
attrs.set("value", value)
}
if disabled is Some(true) {
attrs.set_bool("disabled", true)
}
if form_action is Some(form_action) {
attrs.set_js_value("formAction", form_action.to_js_value())
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "button", attrs, event, style, children })
}
///|
/// Creates a `textarea` element with the specified attributes, event handlers, and
/// properties.
///
/// Returns a virtual DOM node representing a `textarea` element.
///
pub fn textarea(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// The current value of the textarea.
value? : String,
/// The initial value of an uncontrolled textarea. Do not combine with
/// `value`.
default_value? : String,
/// Placeholder text displayed when textarea is empty.
placeholder? : String,
/// Number of visible text lines.
rows? : Int,
/// Number of visible character columns.
cols? : Int,
/// Whether the textarea is disabled.
disabled? : Bool,
/// Whether a controlled textarea is intentionally read-only.
read_only? : Bool,
/// Change event handler (fired when value changes and textarea loses focus).
on_change? : (DOMEvent) -> Unit,
/// Input event handler (fired on every keystroke).
on_input? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if value is Some(value) {
attrs.set("value", value)
}
if default_value is Some(default_value) {
attrs.set("defaultValue", default_value)
}
if placeholder is Some(placeholder) {
attrs.set("placeholder", placeholder)
}
if rows is Some(rows) {
attrs.set_int("rows", rows)
}
if cols is Some(cols) {
attrs.set_int("cols", cols)
}
if disabled is Some(true) {
attrs.set_bool("disabled", true)
}
if read_only is Some(read_only) {
attrs.set_bool("readOnly", read_only)
}
if on_change is Some(on_change) {
event.set(Change, on_change)
}
if on_input is Some(on_input) {
event.set(Input, on_input)
}
Element({ name: "textarea", attrs, event, style, children: [] })
}
///|
/// Creates a `select` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing a `select` element.
///
pub fn select(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes (option elements) of the select element.
children : Array[VirtualNode],
/// The currently selected value.
value? : String,
/// Currently selected values for `multiple=true`.
values? : Array[String],
/// The initially selected value of an uncontrolled select. Do not combine
/// with `value`.
default_value? : String,
/// Initially selected values for an uncontrolled `multiple=true` select.
default_values? : Array[String],
/// Whether the select is disabled.
disabled? : Bool,
/// Whether multiple options can be selected.
multiple? : Bool,
/// Change event handler (fired when selection changes).
on_change? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
let is_multiple = multiple is Some(true)
if is_multiple && (value is Some(_) || default_value is Some(_)) {
abort(
"A multiple React select requires values or default_values arrays instead of scalar values",
)
}
if !is_multiple && (values is Some(_) || default_values is Some(_)) {
abort("React select values and default_values arrays require multiple=true")
}
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if value is Some(value) {
attrs.set("value", value)
}
if values is Some(values) {
attrs.set_js_value(
"value",
@dom.JsObscure::from_array(
values.map(fn(value) { @dom.JsObscure::from_string(value) }),
),
)
}
if default_value is Some(default_value) {
attrs.set("defaultValue", default_value)
}
if default_values is Some(default_values) {
attrs.set_js_value(
"defaultValue",
@dom.JsObscure::from_array(
default_values.map(fn(value) { @dom.JsObscure::from_string(value) }),
),
)
}
if disabled is Some(true) {
attrs.set_bool("disabled", true)
}
if multiple is Some(true) {
attrs.set_bool("multiple", true)
}
if on_change is Some(on_change) {
event.set(Change, on_change)
}
Element({ name: "select", attrs, event, style, children })
}
///|
/// Creates an `option` element with the specified attributes and properties.
///
/// Returns a virtual DOM node representing an `option` element.
///
pub fn option(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the option element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// The value of the option when selected.
value? : String,
/// Whether the option is disabled.
disabled? : Bool,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if value is Some(value) {
attrs.set("value", value)
}
if disabled is Some(true) {
attrs.set_bool("disabled", true)
}
Element({ name: "option", attrs, event, style, children })
}
///|
/// Creates a `section` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing a `section` element.
///
pub fn section(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the section element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "section", attrs, event, style, children })
}
///|
/// Creates an `article` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing an `article` element.
///
pub fn article(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the article element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "article", attrs, event, style, children })
}
///|
/// Creates a `header` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing a `header` element.
///
pub fn header(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the header element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "header", attrs, event, style, children })
}
///|
/// Creates a `footer` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing a `footer` element.
///
pub fn footer(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the footer element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "footer", attrs, event, style, children })
}
///|
/// Creates a `nav` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing a `nav` element.
///
pub fn nav(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the nav element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "nav", attrs, event, style, children })
}
///|
/// Creates an `aside` element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing an `aside` element.
///
pub fn aside(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the aside element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "aside", attrs, event, style, children })
}
///|
/// Creates a `ul` (unordered list) element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing a `ul` element.
///
pub fn ul(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the ul element (typically li elements).
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "ul", attrs, event, style, children })
}
///|
/// Creates an `ol` (ordered list) element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing an `ol` element.
///
pub fn ol(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the ol element (typically li elements).
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "ol", attrs, event, style, children })
}
///|
/// Creates a `li` (list item) element with the specified attributes, event handlers, and
/// children.
///
/// Returns a virtual DOM node representing a `li` element.
///
pub fn li(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the li element.
children : Array[VirtualNode],
/// Raw HTML content to be inserted inside the element.
innerHTML? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if innerHTML is Some(innerHTML) {
attrs.set("innerHTML", innerHTML)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
Element({ name: "li", attrs, event, style, children })
}
///|
/// Creates an `img` element with the specified attributes, event handlers, and
/// image properties.
///
/// Returns a virtual DOM node representing an `img` element.
///
pub fn img(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Image source URL.
src? : String,
/// Alternative text for the image.
alt? : String,
/// Image width.
width? : String,
/// Image height.
height? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
/// Load event handler (fired when image loads successfully).
on_load? : (DOMEvent) -> Unit,
/// Error event handler (fired when image fails to load).
on_error? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if src is Some(src) {
attrs.set("src", src)
}
if alt is Some(alt) {
attrs.set("alt", alt)
}
if width is Some(width) {
attrs.set("width", width)
}
if height is Some(height) {
attrs.set("height", height)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
if on_load is Some(on_load) {
event.set(Load, on_load)
}
if on_error is Some(on_error) {
event.set(Error, on_error)
}
Element({ name: "img", attrs, event, style, children: [] })
}
///|
/// Creates a `video` element with the specified attributes, event handlers, and
/// video properties.
///
/// Returns a virtual DOM node representing a `video` element.
///
pub fn video(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the video element (e.g., source elements).
children : Array[VirtualNode],
/// Video source URL.
src? : String,
/// Whether to show video controls.
controls? : Bool,
/// Whether to autoplay the video.
autoplay? : Bool,
/// Whether to loop the video.
loop_enabled? : Bool,
/// Whether the video is muted.
muted? : Bool,
/// Video width.
width? : String,
/// Video height.
height? : String,
/// Click event handler.
on_click? : (DOMEvent) -> Unit,
/// Play event handler (fired when video starts playing).
on_play? : (DOMEvent) -> Unit,
/// Pause event handler (fired when video is paused).
on_pause? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if src is Some(src) {
attrs.set("src", src)
}
if controls is Some(true) {
attrs.set_bool("controls", true)
}
if autoplay is Some(true) {
attrs.set_bool("autoPlay", true)
}
if loop_enabled is Some(true) {
attrs.set_bool("loop", true)
}
if muted is Some(true) {
attrs.set_bool("muted", true)
}
if width is Some(width) {
attrs.set("width", width)
}
if height is Some(height) {
attrs.set("height", height)
}
if on_click is Some(on_click) {
event.set(Click, on_click)
}
if on_play is Some(on_play) {
event.set(Play, on_play)
}
if on_pause is Some(on_pause) {
event.set(Pause, on_pause)
}
Element({ name: "video", attrs, event, style, children })
}
///|
/// Creates an `audio` element with the specified attributes, event handlers, and
/// audio properties.
///
/// Returns a virtual DOM node representing an `audio` element.
///
pub fn audio(
/// HTML element ID.
id? : String,
/// Base CSS class name.
class_name? : String,
/// Additional CSS class names to be appended to the base class.
class_list? : Array[String] = [],
/// Additional HTML attributes.
attrs? : ElementAttrs,
/// Event handlers map.
event? : ElementEvents,
/// CSS styles.
style? : RespoStyle = respo_style(),
/// Child nodes of the audio element (e.g., source elements).
children : Array[VirtualNode],
/// Audio source URL.
src? : String,
/// Whether to show audio controls.
controls? : Bool,
/// Whether to autoplay the audio.
autoplay? : Bool,
/// Whether to loop the audio.
loop_enabled? : Bool,
/// Whether the audio is muted.
muted? : Bool,
/// Play event handler (fired when audio starts playing).
on_play? : (DOMEvent) -> Unit,
/// Pause event handler (fired when audio is paused).
on_pause? : (DOMEvent) -> Unit,
) -> VirtualNode {
let attrs = attrs.unwrap_or_default()
let event = event.unwrap_or_default()
if id is Some(id) {
attrs.set("id", id)
}
if combine_classes(class_name, class_list) is Some(class_name) {
attrs.set("className", class_name)
}
if src is Some(src) {
attrs.set("src", src)
}
if controls is Some(true) {
attrs.set_bool("controls", true)
}
if autoplay is Some(true) {
attrs.set_bool("autoPlay", true)
}
if loop_enabled is Some(true) {
attrs.set_bool("loop", true)
}
if muted is Some(true) {
attrs.set_bool("muted", true)
}
if on_play is Some(on_play) {
event.set(Play, on_play)
}
if on_pause is Some(on_pause) {
event.set(Pause, on_pause)
}
Element({ name: "audio", attrs, event, style, children })
}