### Run Kagura Application with Runtime::run Source: https://context7.com/soundrabbit/kagura/llms.txt The `Runtime::run` function mounts the application into the DOM and starts the async event loop. It requires a `BasicDomNode` containing the DOM entry point and the root render closure. This is typically called once from a `#[wasm_bindgen(start)]` function. ```rust use nusa::prelude::*; use nusa::html_component::Sub; use wasm_bindgen::prelude::*; mod app; use app::App; #[wasm_bindgen(start)] pub fn main() { wasm_bindgen_futures::spawn_local(async { kagura::Runtime::run( nusa::dom_node::BasicDomNode::new( // DOM node to mount into web_sys::window() .unwrap() .document() .unwrap() .get_element_by_id("app") .unwrap() .into(), // Root render closure; `this` is a dummy state reference |this| { vec![App::empty(this, None, app::Props::default(), Sub::none())] }, ) ) .await; }); } ``` -------------------------------- ### Kagura Cmd Update Method Example Source: https://context7.com/soundrabbit/kagura/llms.txt Demonstrates combining multiple commands like chaining messages and spawning async tasks within a component's update method. Requires importing kagura::prelude::*. ```rust use kagura::prelude::*; use std::pin::Pin; // Combining commands: chain a message and also spawn a background task fn update(mut self: Pin<&mut Self>, msg: Msg) -> Cmd { match msg { Msg::LoadData => Cmd::list(vec![ Cmd::chain(Msg::SetLoading(true)), Cmd::task(async { // Simulate async fetch let data = fetch_data().await; Cmd::chain(Msg::DataLoaded(data)) }), ]), Msg::SetLoading(flag) => { self.loading = flag; Cmd::none() } Msg::DataLoaded(data) => { self.data = data; self.loading = false; Cmd::none() } } } async fn fetch_data() -> String { // Async operation (e.g., wasm fetch) String::from("fetched result") } ``` -------------------------------- ### Create a Web Page with Kagura and Nusa Source: https://github.com/soundrabbit/kagura/blob/main/kagura/README.md This snippet demonstrates the basic setup for creating a web page using Kagura and Nusa. It requires the `js_sys`, `kagura`, `nusa`, `wasm_bindgen`, `wasm_bindgen_futures`, and `web_sys` crates. The application is run within a local async task, rendering a simple 'Hello World' H1 element. ```rust extern crate js_sys; extern crate kagura; nusa::prelude::*; extern crate wasm_bindgen; extern crate wasm_bindgen_futures; extern crate web_sys; use wasm_bindgen::prelude::*; #[wasm_bindgen(start)] pub fn main() { wasm_bindgen_futures::spawn_local(async { kagura::Runtime::run(nusa::dom_node::BasicDomNode::new(entry_point(), |_| { vec![Html::h1( Attributes::new(), Events::new(), vec![Html::text("Hello World")], )] })) .await; }); } fn entry_point() -> web_sys::Node { web_sys::window() .unwrap() .document() .unwrap() .get_element_by_id("app") .unwrap() .into() } ``` -------------------------------- ### Render Internal SVG with BasicDomNode Source: https://github.com/soundrabbit/kagura/blob/main/nusa/README.md This example demonstrates rendering an SVG element within the virtual-DOM using `BasicDomNode`. It includes attributes for size, viewBox, and a rectangle with fill color. ```rust extern crate js_sys; extern crate kagura; extern crate nusa; extern crate wasm_bindgen; extern crate wasm_bindgen_futures; extern crate web_sys; use nusa::prelude::*; use wasm_bindgen::prelude::*; #[wasm_bindgen(start)] pub fn main() { wasm_bindgen_futures::spawn_local(async { kagura::Runtime::run(nusa::dom_node::BasicDomNode::new(entry_point(), |_| { vec![Html::element( "svg", Attributes::new() .string("width", "400") .string("height", "200") .string("viewBox", "0 0 400 200") .string("xmlns", "http://www.w3.org/2000/svg"), Events::new(), vec![Html::element( "rect", Attributes::new() .num("x", 10.0) .num("y", 10.0) .num("width", 380.0) .num("height", 180.0) .string("fill", "#e74c3c"), Events::new(), vec![], )], )] })) .await; }); } fn entry_point() -> web_sys::Node { web_sys::window() .unwrap() .document() .unwrap() .get_element_by_id("app") .unwrap() .into() } ``` -------------------------------- ### Mount to Real DOM with BasicDomNode Source: https://github.com/soundrabbit/kagura/blob/main/nusa/README.md Use `kagura::Runtime::run` to start the application. `nusa::dom_node::BasicDomNode` is used to mount the virtual-DOM to the real DOM. Ensure an element with id 'app' exists in your HTML. ```rust extern crate js_sys; extern crate kagura; extern crate nusa; extern crate wasm_bindgen; extern crate wasm_bindgen_futures; extern crate web_sys; use nusa::prelude::*; use wasm_bindgen::prelude::*; #[wasm_bindgen(start)] pub fn main() { wasm_bindgen_futures::spawn_local(async { kagura::Runtime::run(nusa::dom_node::BasicDomNode::new(entry_point(), |_| { vec![Html::h1( Attributes::new(), Events::new(), vec![Html::text("Hello World")], )] })) .await; }); } fn entry_point() -> web_sys::Node { web_sys::window() .unwrap() .document() .unwrap() .get_element_by_id("app") .unwrap() .into() } ``` -------------------------------- ### Accessing Underlying DOM Node with Events::refer Source: https://context7.com/soundrabbit/kagura/llms.txt Use `Events::refer` to get access to the underlying `web_sys::Node` once the element is mounted. This is useful for imperative DOM operations like drawing on a canvas or integrating third-party libraries. ```rust use nusa::{Html, HtmlComponent}; use nusa::html::html_element::{Attributes, Events}; use wasm_bindgen::JsCast; pub enum Msg { CanvasMounted(web_sys::Node), } // In Render::render: fn render(&self, _: ()) -> Html { Html::canvas( Attributes::new() .string("width", "400") .string("height", "300"), Events::new().refer(self, |node| Msg::CanvasMounted(node)), vec![], ) } // In Update::update: fn update(self: Pin<&mut Self>, msg: Msg) -> Cmd { match msg { Msg::CanvasMounted(node) => { if let Ok(canvas) = node.dyn_into::() { let ctx = canvas .get_context("2d").unwrap().unwrap() .dyn_into::().unwrap(); ctx.set_fill_style(&wasm_bindgen::JsValue::from("steelblue")); ctx.fill_rect(0.0, 0.0, 400.0, 300.0); } Cmd::none() } } } ``` -------------------------------- ### Nusa Html List Construction Source: https://context7.com/soundrabbit/kagura/llms.txt Builds an unordered HTML list with keyed list items for efficient diffing. Requires importing nusa::Html and specific html_element modules. ```rust use nusa::Html; use nusa::html::html_element::{Attributes, Events}; // Build a list with mixed content fn build_list(items: &[String]) -> Html { Html::ul( Attributes::new().class("my-list"), Events::new(), items .iter() .enumerate() .map(|(i, item)| { Html::li( Attributes::new().index_id(i.to_string()), // keyed diffing Events::new(), vec![Html::text(item.clone())], ) }) .collect(), ) } ``` -------------------------------- ### Create Generic and Namespace-aware HTML Elements with Nusa Source: https://context7.com/soundrabbit/kagura/llms.txt Use `Html::element` for generic HTML tags and `Html::element_ns` for elements requiring explicit namespaces like SVG. The `xmlns` attribute on a parent node propagates its namespace to all descendants. ```rust use nusa::Html; use nusa::html_component::Sub; use nusa::html_element::{Attributes, Events}; // Generic element let custom = Html::element( "my-custom-element", Attributes::new().string("data-value", "42"), Events::new(), vec![Html::text("slot content")], ); // SVG via xmlns propagation (recommended for SVG roots) let svg = Html::element( "svg", Attributes::new() .string("width", "200") .string("height", "200") .string("xmlns", "http://www.w3.org/2000/svg"), Events::new(), vec![ Html::element( "circle", Attributes::new() .num("cx", 100.0) .num("cy", 100.0) .num("r", 80.0) .string("fill", "#3498db"), Events::new(), vec![], ), ], ); // Explicit namespace per element let rect = Html::element_ns( "rect", "http://www.w3.org/2000/svg", Attributes::new().num("width", 50.0).num("height", 50.0), Events::new(), vec![], ); ``` -------------------------------- ### Nusa Html Fragment Construction Source: https://context7.com/soundrabbit/kagura/llms.txt Creates an HTML fragment consisting of multiple root nodes without a wrapper element. Requires importing nusa::Html and specific html_element modules. ```rust use nusa::Html; use nusa::html::html_element::{Attributes, Events}; // Fragment: multiple root nodes without a wrapper element fn build_fragment() -> Html { Html::Fragment(vec![ Html::h1(Attributes::new(), Events::new(), vec![Html::text("Title")]), Html::p(Attributes::new(), Events::new(), vec![Html::text("Body")]), ]) } ``` -------------------------------- ### Nusa Html Element Attributes Builder Source: https://context7.com/soundrabbit/kagura/llms.txt Demonstrates building HTML element attributes using the Attributes builder, supporting various types and custom attributes. Multiple calls for the same attribute name are joined with a delimiter. Requires importing nusa::html::html_element::Attributes. ```rust use nusa::html::html_element::Attributes; let attrs = Attributes::new() .id("main-input") .class("form-control") .class("is-primary") // appended with space -> "form-control is-primary" .type_("text") .placeholder("Enter name") .value("Alice") .checked(false) // false -> attribute omitted entirely .hidden(false) .href("/profile") .src("/avatar.png") .title("User avatar") .style("color", "red") .style("font-size", "14px") // joined with ";" -> "color:red;font-size:14px" .string("data-role", "admin") // arbitrary string attribute .int("tabindex", -1) .nut("data-index", 42) .num("data-ratio", 1.5) .flag("disabled", true); // true -> attribute present with no value ``` -------------------------------- ### Initialize Component State with Constructor Trait in Rust Source: https://context7.com/soundrabbit/kagura/llms.txt Implement the `Constructor` trait to define how a component's initial state is created from its `Props`. This method is called once when the component is first added to the UI tree. ```rust impl Constructor for MyInput { fn constructor(props: Props) -> Self { Self { value: props.initial_value, } } } ``` -------------------------------- ### Kagura BatchProcess Trait for Recurring Tasks Source: https://context7.com/soundrabbit/kagura/llms.txt Shows how to implement the BatchProcess trait for recurring asynchronous tasks like timers or polling. The process is automatically cancelled when the component is dropped. Requires importing kagura::prelude::* and std::future::Future. ```rust use kagura::prelude::*; use std::pin::Pin; use std::future:: Future; struct Ticker { interval_ms: u64, } impl BatchProcess for Ticker { fn poll(&mut self) -> Pin>>> { let ms = self.interval_ms; Box::pin(async move { // Use async-std or wasm-compatible sleep async_std::task::sleep(std::time::Duration::from_millis(ms)).await; Cmd::chain(Msg::Tick) }) } } // In Update::on_assemble: fn on_assemble(self: Pin<&mut Self>) -> Cmd { Cmd::batch(Ticker { interval_ms: 1000 }) } ``` -------------------------------- ### Events::refer Source: https://context7.com/soundrabbit/kagura/llms.txt Provides access to the underlying `web_sys::Node` of a rendered DOM element, delivered as a message once the element is mounted. Useful for imperative DOM access. ```APIDOC ## Events::refer Provides access to the underlying `web_sys::Node` of a rendered DOM element, delivered as a message once the element is mounted. Useful for imperative DOM access (e.g., canvas drawing, focus management, third-party library integration). ```rust use nusa::{Html, HtmlComponent}; use nusa::html::html_element::{Attributes, Events}; use wasm_bindgen::JsCast; pub enum Msg { CanvasMounted(web_sys::Node), } // In Render::render: fn render(&self, _: ()) -> Html { Html::canvas( Attributes::new() .string("width", "400") .string("height", "300"), Events::new().refer(self, |node| Msg::CanvasMounted(node)), vec![], ) } // In Update::update: fn update(self: Pin<&mut Self>, msg: Msg) -> Cmd { match msg { Msg::CanvasMounted(node) => { if let Ok(canvas) = node.dyn_into::() { let ctx = canvas .get_context("2d").unwrap().unwrap() .dyn_into::().unwrap(); ctx.set_fill_style(&wasm_bindgen::JsValue::from("steelblue")); ctx.fill_rect(0.0, 0.0, 400.0, 300.0); } Cmd::none() } } } ``` ``` -------------------------------- ### Attaching DOM Event Listeners with Events Builder Source: https://context7.com/soundrabbit/kagura/llms.txt Use the `Events` builder to attach various DOM event listeners to virtual elements. Handlers receive a `VEvent` and return a component `Msg`. Both bubble and capture phases are supported. ```rust use nusa::html::html_element::Events; // In Render::render(&self, ...) let events = Events::new() .on_click(self, |_e| Msg::Clicked) .on_dblclick(self, |_e| Msg::DoubleClicked) .on_mouseenter(self, |_e| Msg::Hovered(true)) .on_mouseleave(self, |_e| Msg::Hovered(false)) .on_keydown(self, |e| { // e.event() gives the raw web_sys::Event Msg::KeyPressed }) .on_input(self, |value: String| Msg::InputChanged(value)) // extracts value automatically .capture_on_click(self, |_e| Msg::CapturedClick); // capture phase ``` -------------------------------- ### HtmlComponent & Sub (Parent–Child Communication) Source: https://context7.com/soundrabbit/kagura/llms.txt Enables embedding components and subscribing to child events using `Sub::map` to translate child events into parent messages. ```APIDOC ## HtmlComponent & Sub (Parent–Child Communication) `HtmlComponent` is a marker trait that enables a component to be embedded in another component's render output. `Sub` is used by the parent to subscribe to child events, mapping `Child::Event` variants to `Parent::Msg`. ```rust use nusa::html_component::Sub; use nusa::{Html, HtmlComponent}; // --- Child component --- pub enum On { Confirmed(String) } impl HtmlComponent for ChildForm {} // --- Parent render --- impl Render for Parent { type Children = (); fn render(&self, _: ()) -> Html { // Sub::map converts child On events into parent Msg ChildForm::empty( self, Some("child-form".to_string()), // optional index_id for keyed diffing child_form::Props { label: "Name".into() }, Sub::map(|event| match event { child_form::On::Confirmed(val) => Msg::FormSubmitted(val), }), ) } } // Sub::none() when the parent doesn't care about child events: ChildForm::empty(self, None, child_form::Props { label: "Bio".into() }, Sub::none()); ``` ``` -------------------------------- ### Events Source: https://context7.com/soundrabbit/kagura/llms.txt Builder for DOM event listeners attached to a virtual element. Handlers receive a VEvent and return a component Msg. Both bubble and capture phases are supported. ```APIDOC ## Events Builder for DOM event listeners attached to a virtual element. Each handler closure receives a `VEvent` and must return a component `Msg`. The component reference (`self`) is passed to bind the message target. Both bubble-phase (`on_*`) and capture-phase (`capture_on_*`) variants are available. ```rust use nusa::html::html_element::Events; // In Render::render(&self, ...) let events = Events::new() .on_click(self, |_e| Msg::Clicked) .on_dblclick(self, |_e| Msg::DoubleClicked) .on_mouseenter(self, |_e| Msg::Hovered(true)) .on_mouseleave(self, |_e| Msg::Hovered(false)) .on_keydown(self, |e| { // e.event() gives the raw web_sys::Event Msg::KeyPressed }) .on_input(self, |value: String| Msg::InputChanged(value)) // extracts value automatically .capture_on_click(self, |_e| Msg::CapturedClick); // capture phase ``` ``` -------------------------------- ### Render Component UI with Render Trait in Rust Source: https://context7.com/soundrabbit/kagura/llms.txt Implement the `Render` trait to define the component's UI structure using `nusa::Html`. The `render` method takes `Children` and returns the HTML representation. `HtmlComponent` is a marker trait for web components. ```rust use nusa::{Html, HtmlComponent}; use nusa::html::html_element::{Attributes, Events}; use std::pin::Pin; impl Render for MyInput { type Children = (); fn render(&self, _children: Self::Children) -> Html { Html::div( Attributes::new().class("input-wrapper"), Events::new(), vec![ Html::input( Attributes::new() .type_("text") .value(self.value.clone()) .placeholder("Type here…"), Events::new().on_input(self, |v| Msg::UpdateInput(v)), vec![], ), Html::button( Attributes::new(), Events::new().on_click(self, |_| Msg::Submit), vec![Html::text("Submit")], ), ], ) } } impl HtmlComponent for MyInput {} ``` -------------------------------- ### Nusa Html Conditional Rendering Source: https://context7.com/soundrabbit/kagura/llms.txt Renders an HTML element conditionally, or renders nothing if the condition is false. Uses Html::none() to represent no output. Requires importing nusa::Html and specific html_element modules. ```rust use nusa::Html; use nusa::html::html_element::{Attributes, Events}; // Render nothing conditionally fn maybe_banner(show: bool) -> Html { if show { Html::div(Attributes::new().class("banner"), Events::new(), vec![Html::text("Welcome!")]) } else { Html::none() } } ``` -------------------------------- ### Handle State Transitions with Update Trait in Rust Source: https://context7.com/soundrabbit/kagura/llms.txt Implement the `Update` trait to manage component state changes based on incoming messages. The `update` method handles messages, and `on_assemble` and `on_load` manage lifecycle events. Returns a `Cmd` to control runtime actions. ```rust impl Update for MyInput { fn on_assemble(self: Pin<&mut Self>) -> Cmd { // Kick off an async task on assembly Cmd::task(async { Cmd::chain(Msg::UpdateInput(String::from("prefilled"))) }) } fn on_load(mut self: Pin<&mut Self>, props: Props) -> Cmd { self.value = props.initial_value; Cmd::none() } fn update(mut self: Pin<&mut Self>, msg: Msg) -> Cmd { match msg { Msg::UpdateInput(v) => { self.value = v; Cmd::none() } Msg::Submit => Cmd::submit(On::Submitted(self.value.clone())), } } } ``` -------------------------------- ### Passing Slot Children with HtmlComponent::new Source: https://context7.com/soundrabbit/kagura/llms.txt Use `HtmlComponent::new` when a parent component needs to pass slot children to a child component. The child component must declare its `Children` associated type accordingly. ```rust // Child declares Children = Vec impl Render for Panel { type Children = Vec; fn render(&self, children: Self::Children) -> Html { Html::div( Attributes::new().class("panel"), Events::new(), children, ) } } impl HtmlComponent for Panel {} // Parent passes children via ::new impl Render for Page { type Children = (); fn render(&self, _: ()) -> Html { Panel::new( self, None, panel::Props {}, Sub::none(), vec![ Html::h2(Attributes::new(), Events::new(), vec![Html::text("Section")]), Html::p(Attributes::new(), Events::new(), vec![Html::text("Content here.")]), ], ) } } ``` -------------------------------- ### Parent-Child Communication with Sub::map Source: https://context7.com/soundrabbit/kagura/llms.txt Use `Sub::map` to subscribe to child component events and map them to the parent's `Msg` type. This enables communication from child to parent. ```rust use nusa::html_component::Sub; use nusa::{Html, HtmlComponent}; // --- Child component --- pub enum On { Confirmed(String) } impl HtmlComponent for ChildForm {} // --- Parent render --- impl Render for Parent { type Children = (); fn render(&self, _: ()) -> Html { // Sub::map converts child On events into parent Msg ChildForm::empty( self, Some("child-form".to_string()), // optional index_id for keyed diffing child_form::Props { label: "Name".into() }, Sub::map(|event| match event { child_form::On::Confirmed(val) => Msg::FormSubmitted(val), }), ) } } // Sub::none() when the parent doesn't care about child events: ChildForm::empty(self, None, child_form::Props { label: "Bio".into() }, Sub::none()); ``` -------------------------------- ### HtmlComponent::new (with Children Slot) Source: https://context7.com/soundrabbit/kagura/llms.txt Used when a parent component passes slot children into a child component's `Children` associated type. ```APIDOC ## HtmlComponent::new (with Children Slot) `HtmlComponent::new` is used instead of `::empty` when the parent passes slot children into the child component's `Children` associated type. ```rust // Child declares Children = Vec impl Render for Panel { type Children = Vec; fn render(&self, children: Self::Children) -> Html { Html::div( Attributes::new().class("panel"), Events::new(), children, ) } } impl HtmlComponent for Panel {} // Parent passes children via ::new impl Render for Page { type Children = (); fn render(&self, _: ()) -> Html { Panel::new( self, None, panel::Props {}, Sub::none(), vec![ Html::h2(Attributes::new(), Events::new(), vec![Html::text("Section")]), Html::p(Attributes::new(), Events::new(), vec![Html::text("Content here.")]), ], ) } } ``` ``` -------------------------------- ### Define Component Associated Types in Rust Source: https://context7.com/soundrabbit/kagura/llms.txt Implement the `Component` trait to declare the associated types `Props`, `Msg`, and `Event` for a Kagura component. This establishes the contract for input, internal messages, and output. ```rust use kagura::prelude::*; use nusa::prelude::*; pub struct Props { pub initial_value: String, } pub enum Msg { UpdateInput(String), Submit, } pub enum On { Submitted(String), } pub struct MyInput { value: String, } impl Component for MyInput { type Props = Props; type Msg = Msg; type Event = On; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.