diff --git a/.gitignore b/.gitignore
index 3ca43ae..8f77cef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,5 @@ Cargo.lock
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
+
+dist/
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..a6388cd
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "web1"
+version = "0.1.0"
+edition = "2021"
+description = "Template for starting a Yew project using Trunk"
+readme = "README.md"
+repository = "https://github.com/yewstack/yew-trunk-minimal-template"
+license = "MIT OR Apache-2.0"
+keywords = ["yew", "trunk"]
+categories = ["gui", "wasm", "web-programming"]
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[dependencies]
+yew = { version="0.21", features=["csr"] }
+web-sys = { version = "0.3", features = ["Document", "HtmlElement", "Window"] }
+gloo-utils = "0.1"
+gloo-storage = "0.2"
+serde = { version = "1.0", features = ["derive"] }
\ No newline at end of file
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
new file mode 100644
index 0000000..08017da
--- /dev/null
+++ b/LICENSE-APACHE
@@ -0,0 +1,177 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 0000000..b6c65b2
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,25 @@
+Copyright (c) despiegk
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
index bd39e9e..7f0fff9 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,75 @@
-# webtest
+# Yew Trunk Template
+This is a fairly minimal template for a Yew app that's built with [Trunk].
+
+## Usage
+
+For a more thorough explanation of Trunk and its features, please head over to the [repository][trunk].
+
+### Installation
+
+If you don't already have it installed, it's time to install Rust: .
+The rest of this guide assumes a typical Rust installation which contains both `rustup` and Cargo.
+
+To compile Rust to WASM, we need to have the `wasm32-unknown-unknown` target installed.
+If you don't already have it, install it with the following command:
+
+```bash
+rustup target add wasm32-unknown-unknown
+```
+
+Now that we have our basics covered, it's time to install the star of the show: [Trunk].
+Simply run the following command to install it:
+
+```bash
+cargo install trunk wasm-bindgen-cli
+```
+
+That's it, we're done!
+
+### Running
+
+```bash
+trunk serve
+```
+
+Rebuilds the app whenever a change is detected and runs a local server to host it.
+
+There's also the `trunk watch` command which does the same thing but without hosting it.
+
+### Release
+
+```bash
+trunk build --release
+```
+
+This builds the app in release mode similar to `cargo build --release`.
+You can also pass the `--release` flag to `trunk serve` if you need to get every last drop of performance.
+
+Unless overwritten, the output will be located in the `dist` directory.
+
+## Using this template
+
+There are a few things you have to adjust when adopting this template.
+
+### Remove example code
+
+The code in [src/main.rs](src/main.rs) specific to the example is limited to only the `view` method.
+There is, however, a fair bit of Sass in [index.scss](index.scss) you can remove.
+
+### Update metadata
+
+Update the `version`, `description` and `repository` fields in the [Cargo.toml](Cargo.toml) file.
+The [index.html](index.html) file also contains a `` tag that needs updating.
+
+
+Finally, you should update this very `README` file to be about your app.
+
+### License
+
+The template ships with both the Apache and MIT license.
+If you don't want to have your app dual licensed, just remove one (or both) of the files and update the `license` field in `Cargo.toml`.
+
+There are two empty spaces in the MIT license you need to fill out: `` and `despiegk `.
+
+[trunk]: https://github.com/thedodd/trunk
\ No newline at end of file
diff --git a/ai_instructions.md b/ai_instructions.md
new file mode 100644
index 0000000..fac047a
--- /dev/null
+++ b/ai_instructions.md
@@ -0,0 +1,452 @@
+
+# Yew Framework Documentation for AI Coders: Core Concepts & Coding
+
+This document provides a comprehensive overview of the Yew framework's core coding concepts, designed to equip AI robot coders with the knowledge necessary to build web applications using Rust and WebAssembly.
+
+Yew is a modern Rust framework for building client-side web applications using WebAssembly (Wasm). It enables the development of highly performant web UIs by leveraging Rust's strong type system and rich ecosystem. Yew promotes a component-based architecture for building reusable and maintainable UI elements.
+
+## Fundamental Building Blocks
+
+### The `html!` Macro for UI Composition
+
+Yew employs the `html!` procedural macro for declarative UI construction, drawing inspiration from JSX. This macro is the primary way to define the structure of your component's output.
+
+**Syntax and Features:**
+
+* **Single Root Node:** The `html!` macro always expects a single root HTML node. To render multiple top-level elements without a wrapping container, use the fragment syntax: `<> ... >`.
+* **Embedding Rust Expressions:** Any valid Rust expression can be embedded within the markup using curly braces (`{ expression }`). The expression **must evaluate to a type that implements `Into`**.
+ ```rust
+ let header_text = "Welcome to Yew".to_string();
+ let count = 5;
+ html! {
+ <>
+
{ header_text }
+
{"Current count: "}{ count }
+ >
+ }
+ ```
+ * **Literals:** String literals are typically enclosed in quotes and then a `{}`, e.g., `{"Hello"}`. They are treated as `Text` nodes, inherently mitigating common HTML injection (XSS) risks.
+* **Element / Component Definition:**
+ * **HTML Elements:** Standard HTML elements are written as `child` or self-closing ``.
+ * **Dynamic Tag Names:** For situations where the HTML tag name is determined at runtime, use the `@{expression}` syntax. The expression must be a string.
+ ```rust
+ let level = 3;
+ html! { <@{format!("h{}", level)} class="subtitle">{"Dynamic Heading"}@> }
+ ```
+ * **Yew Components:** Yew components are instantiated like custom HTML tags, using PascalCase for their names: ``.
+* **Attributes and Properties:**
+ * **HTML Attributes:** Set on elements directly: ``.
+ * **Boolean Attributes:** Set with `true` or `false`. `false` is equivalent to omitting the attribute entirely.
+ ```rust
+ html! { }
+ ```
+ * **String-like Attributes:** Can accept `&str`, `String`, or Yew's optimized `AttrValue` (a cheaply cloneable `Rc` or `&'static str`). `AttrValue` is generally recommended for performance-sensitive scenarios, especially when passing values as properties to other components.
+ * **Optional Attributes:** Use `Option` for attribute values. If the `Option` is `None`, the attribute will not be rendered in the DOM.
+ ```rust
+ let maybe_id: Option<&str> = Some("unique-element");
+ html! { } // Renders with id or not
+ ```
+ * **Yew-Specific Properties (Special Props):** These are not directly reflected in the DOM but serve as instructions to Yew's Virtual DOM.
+ * `ref={node_ref_handle}`: Connects a `NodeRef` to a DOM element, allowing direct programmatic access to the underlying DOM node (e.g., for canvas manipulation, scrolling, form input values).
+ * `key={unique_key}`: Provides a unique identifier for elements within a list. Crucial for performance optimization, as Yew uses keys to efficiently reconcile list items during updates, preventing unnecessary re-renders or DOM manipulations. Keys must be unique *within their immediate siblings* (the list itself) and should be stable/deterministic, not based on item position.
+* **Conditional Rendering:** Use standard Rust `if` and `if let` control flow structures directly within the `html!` macro to conditionally render content.
+ ```rust
+ let show_message = true;
+ html! {
+ if show_message {
+
{"This message is visible."}
+ } else {
+
{"Message hidden."}
+ }
+ }
+ ```
+* **List Rendering / Iteration:**
+ * Use `for` syntax directly in `html!`: `{ for collection.iter() }`. This expects the iterator items to be renderable `Html`.
+ * Alternatively, map the collection to `Html` elements and use `.collect::()`.
+ * **Always use `key` for list items** where the order or presence of items can change, as this drastically improves reconciliation performance.
+ ```rust
+ let items = vec!["Apple", "Banana", "Cherry"];
+ html! {
+
+ { for items.iter().map(|item| html! {
{item}
}) }
+
+ }
+ ```
+
+### Components: Function Components
+
+Yew applications are built from components, which encapsulate UI logic and presentation. Function components are the recommended and most common way to define components in modern Yew.
+
+* **Definition:** Declare a function component using the `#[function_component]` attribute on a `fn` that returns `Html`. By convention, component names are PascalCase.
+ ```rust
+ use yew::prelude::*;
+
+ #[function_component]
+ fn MySimpleComponent() -> Html {
+ html! {
{"Hello from a component!"}
}
+ }
+ ```
+* **Properties (Props):** Data is passed from parent to child components using "props". Props are defined by a struct that must implement `Properties` (usually via `#[derive(Properties)]`) and `PartialEq`. The function component accepts an `&Props` reference as its single argument.
+ ```rust
+ #[derive(Properties, PartialEq)]
+ pub struct GreetProps {
+ pub name: String,
+ #[prop_or_default] // Field attribute for optional props with default value
+ pub greeting_text: String,
+ }
+
+ #[function_component]
+ fn Greeter(props: &GreetProps) -> Html {
+ let greeting = if props.greeting_text.is_empty() {
+ "Hello".to_string()
+ } else {
+ props.greeting_text.clone()
+ };
+ html! {
{ format!("{}, {}!", greeting, props.name) }
}
+ }
+ // Usage: html! { } or html! { }
+ ```
+ * **Reactive Nature of Props:** Yew automatically re-renders a component when its props change (detected via `PartialEq`).
+ * **`props!` Macro:** Allows building `Properties` structs programmatically.
+ ```rust
+ use yew::props;
+ let my_props = props! { GreetProps { name: "Charlie".to_string() } };
+ html! { }
+ ```
+* **Children (Special Prop):** If a component's `Props` struct includes a `pub children: Html` field, it can accept nested `html!` content.
+ ```rust
+ #[derive(Properties, PartialEq)]
+ pub struct CardProps {
+ pub title: String,
+ pub children: Html, // This field name is special
+ }
+
+ #[function_component]
+ fn Card(props: &CardProps) -> Html {
+ html! {
+
+
{ &props.title }
+
+ { props.children.clone() }
+
+
+ }
+ }
+ // Usage: html! {
Some content here.
}
+ ```
+* **Generic Components:** Function components can be generic over types, provided the generic type parameters meet the necessary trait bounds (e.g., `PartialEq`).
+ ```rust
+ #[derive(Properties, PartialEq)]
+ pub struct ItemDisplayProps {
+ pub item: T,
+ }
+
+ #[function_component]
+ pub fn ItemDisplay(props: &ItemDisplayProps) -> Html
+ where
+ T: PartialEq + ToHtml + 'static, // 'static for use in VDOM
+ {
+ html! {
{ &props.item }
}
+ }
+ // Usage: html! { item=123 /> }
+ ```
+* **Pure Components:** A function component is "pure" if its output `Html` is solely determined by its props, and it has no side effects or internal mutable state. Yew's reconciliation benefits from pure components.
+ * Simple pure components with no hooks can sometimes be implemented as regular functions returning `Html` to reduce overhead.
+* **Communication Patterns:**
+ * **Parent to Child:** Via [Props](#properties-props).
+ * **Child to Parent:** Via [Callbacks](#callbacks). The parent passes a `Callback` to the child via props, and the child calls `emit()` on it to send data back up.
+
+## State Management and Interactivity
+
+Yew provides "hooks" to manage mutable state and side effects within function components.
+
+### Hooks
+
+Hooks are functions that allow "hooking into" the lifecycle and state management capabilities of function components.
+
+**Rules of Hooks:**
+
+1. **Naming Convention:** Hook function names **must start with `use_`**.
+2. **Top-Level Calls Only:** Hooks can **only be called at the top level of a function component or another hook**, and not inside loops, conditionals without `if let`, or nested functions *unless* within the scrutinee of a top-level `if` or `match` expression.
+3. **Consistent Call Order:** Hooks must be called in the exact same order on every render. This enables Yew to correctly associate state with hook calls.
+4. **No Early Return:** A component using hooks cannot `return` early before all hooks are called unless using [Suspense](#suspense).
+
+**Common Pre-defined Hooks:**
+
+* **`use_state() -> UseStateHandle`:** Manages local component state. Returns a handle that can be dereferenced to get the current value and has a `.set(new_value)` method to update the state. Updating state triggers a re-render.
+ ```rust
+ use yew::prelude::*;
+
+ #[function_component]
+ fn ClickCounter() -> Html {
+ let count = use_state(|| 0); // Initializes with 0
+ let onclick = {
+ let count = count.clone(); // Clone the handle for the closure
+ move |_| {
+ count.set(*count + 1); // Update the state
+ }
+ };
+ html! { }
+ }
+ ```
+* **`use_state_eq() -> UseStateHandle`:** Similar to `use_state`, but only triggers a re-render if the new value is *not* equal to the current value (using `PartialEq`).
+* **`use_memo(f: impl FnOnce(D) -> T, deps: D) -> Rc`:** Memoizes an expensive computation. The `f` closure is only re-executed if `deps` (dependencies) change.
+* **`use_callback(f: F) -> Callback`:** Memoizes a `Callback` instance. The `Callback` is only recreated if its dependencies (captured variables) change.
+* **`use_mut_ref() -> Rc>`:** Provides a mutable reference (`RefCell`) that persists across re-renders without triggering them. Useful for mutable data that doesn't directly affect rendering or for interop with mutable JS APIs.
+* **`use_node_ref() -> NodeRef`:** Creates a `NodeRef` handle, used to get a direct reference to a rendered DOM element.
+ ```rust
+ use yew::prelude::*;
+ use web_sys::HtmlInputElement;
+
+ #[function_component]
+ fn MyInput() -> Html {
+ let input_ref = use_node_ref();
+ let current_value = use_state(|| String::new());
+
+ let on_input_change = {
+ let input_ref = input_ref.clone();
+ let current_value = current_value.clone();
+ move |_| {
+ if let Some(input) = input_ref.cast::() {
+ current_value.set(input.value());
+ }
+ }
+ };
+
+ html! {
+
+
+
{"Input Value: "}{&*current_value}
+
+ }
+ }
+ ```
+* **`use_reducer() -> UseReducerHandle`:** Manages more complex state using a reducer pattern (similar to Redux), allowing state updates based on dispatched "actions". The state must implement the `Reducible` trait.
+* **`use_reducer_eq() -> UseReducerHandle`:** Similar to `use_reducer`, but dispatches only if the new state differs from the old.
+* **`use_effect(f: impl FnOnce() -> impl FnOnce())`:** Runs a side effect after every render. Can return a cleanup closure that runs before the next effect or when the component is unmounted.
+* **`use_effect_with(deps: D, f: impl FnOnce(D) -> impl FnOnce())`:** Runs a side effect only when `deps` (dependencies) change.
+* **`use_context() -> Option>`:** Accesses a context value provided by an ancestor `ContextProvider` component.
+* **`use_force_update()`:** Returns a callback that, when emitted, forces a re-render of the component. Use sparingly.
+
+**Custom Hooks:** Components can extract reusable stateful logic into custom hooks by defining functions starting with `use_` and marking them with `#[hook]`. Custom hooks compose existing hooks.
+
+### Callbacks
+
+`Callback` is a crucial type for event handling and child-to-parent communication. It wraps an `Fn` closure in an `Rc`, making it cheaply clonable.
+
+* **`Callback::from(closure)`:** Creates a `Callback` from a closure.
+* **`callback.emit(value)`:** Invokes the wrapped closure with the given value.
+* **DOM Events:** Event handlers in `html!` (e.g., `onclick`, `oninput`) expect a `Callback` that takes the corresponding `web_sys` event type as an argument.
+ ```rust
+ use yew::prelude::*;
+ use web_sys::MouseEvent;
+
+ #[function_component]
+ fn MyButton() -> Html {
+ let onclick_handler = Callback::from(move |e: MouseEvent| {
+ // Access event properties:
+ log::info!("Click event at: ({}, {})", e.client_x(), e.client_y());
+ // More complex logic...
+ });
+ html! { }
+ }
+ ```
+* **`TargetCast` Trait:** Provided by Yew (within `yew::prelude::*`), this trait extends `web_sys::Event` to safely cast the event target to a specific HTML element type (e.g., `HtmlInputElement`).
+ * `event.target_dyn_into::() -> Option` (safe, checked)
+ * `event.target_unchecked_into::() -> HtmlElementType` (unchecked, use with caution when type is guaranteed)
+
+### Contexts
+
+Contexts provide a way to pass data deeply through the component tree without manually "prop drilling" at every level.
+
+* **Provider (`ContextProvider`):** An ancestor component wraps its children with `ContextProvider`, providing a value of type `T`. `T` must implement `Clone` and `PartialEq`.
+ ```rust
+ // Define your context data
+ #[derive(Clone, Debug, PartialEq)]
+ struct Theme {
+ foreground: String,
+ background: String,
+ }
+
+ #[function_component]
+ fn ThemeProvider(props: &ChildrenProps) -> Html { // ChildrenProps from yew::html
+ let theme = use_state(|| Theme {
+ foreground: "#000".to_string(),
+ background: "#eee".to_string(),
+ });
+ html! {
+ context={(*theme).clone()}>
+ { props.children.clone() }
+ >
+ }
+ }
+ // Usage: html! { }
+ ```
+* **Consumer (`use_context` hook):** Descendant function components use `use_context::()` to retrieve the provided value.
+ ```rust
+ #[function_component]
+ fn ThemedText() -> Html {
+ let theme = use_context::() // Retrieve the Theme context
+ .expect("Theme context not provided!");
+ html! {
+
+ {"This text is themed."}
+
+ }
+ }
+ ```
+* **Mutable Contexts:** To allow children to modify a context value, combine `ContextProvider` with `use_reducer` for a predictable state update mechanism.
+
+### Event Handling and Delegation
+
+Yew integrates with `web-sys` for DOM events. Yew's event system employs event delegation: listeners are not directly attached to individual elements but are handled by a single delegate at the application's root. Events then "bubble up" through Yew's Virtual DOM hierarchy.
+
+* **Event Listener Names:** In `html!`, event listeners start with `on` followed by the event name (e.g., `onclick`, `oninput`).
+* **Manual Event Listeners:** For events not directly supported by `html!` or for fine-grained control, use `use_effect_with` and `gloo-events` (`EventListener`) to manually attach/detach event listeners to `NodeRef`-obtained DOM elements.
+ ```rust
+ use gloo::events::EventListener;
+ use yew::prelude::*;
+ use web_sys::HtmlElement;
+
+ #[function_component]
+ fn CustomEventHandler() -> Html {
+ let div_ref = use_node_ref();
+ use_effect_with(div_ref.clone(), {
+ let div_ref_clone = div_ref.clone();
+ move |_| {
+ let mut listener_obj: Option = None;
+ if let Some(div_element) = div_ref_clone.cast::() {
+ let listener = EventListener::new(&div_element, "custom-event", move |event| {
+ log::info!("Custom event received!");
+ // event.dyn_into::() for richer data
+ });
+ listener_obj = Some(listener);
+ }
+ move || drop(listener_obj) // Cleanup when effect re-runs or component unmounts
+ }
+ });
+ html! {
{"Div with custom event listener"}
}
+ }
+ ```
+
+## Advanced Topics
+
+### Interacting with JavaScript (JS) and Web APIs
+
+Yew compiles to Wasm, but direct interaction with browser APIs often involves `wasm-bindgen` and related crates.
+
+* **`wasm-bindgen`:** Bridges calls between Rust and JavaScript. Used for defining FFI (Foreign Function Interface) to import/export functions.
+* **`web-sys`:** Provides Rust bindings for all Web APIs (DOM, Fetch, etc.). This is the primary way to interact with the browser from Rust.
+ * **Features:** `web-sys` is heavily feature-gated; enable only the necessary features in `Cargo.toml` to avoid bloat (e.g., `features = ["Document", "HtmlElement", "Window"]`).
+ * **Inheritance:** `web-sys` types simulate JavaScript inheritance using Rust's `Deref` and `AsRef` traits. For instance, an `HtmlElement` can deref to `Element`, then `Node`, then `EventTarget`, finally `JsValue`. This allows calling methods from ancestor types.
+ * **`JsCast` Trait:** Crucial for downcasting `JsValue` or generic `EventTarget` (from `web_sys`) to specific, more concrete types (e.g., `HtmlInputElement`). Provides `dyn_into` (checked, returns `Result`) and `unchecked_into` (unchecked, faster).
+* **`js-sys`:** Provides Rust bindings for JavaScript's standard, built-in objects (e.g., `Date`, `Object`).
+* **`wasm-bindgen-futures`:** Bridges Rust `Future`s with JavaScript `Promise`s.
+ * **`spawn_local(future)`:** Spawns a Rust `Future` to run on the current thread's event loop, enabling asynchronous operations (e.g., `async fetch()` calls).
+
+### Asynchronous Operations and Suspense
+
+Yew's `Suspense` component allows suspending component rendering while waiting for an asynchronous task (e.g., data fetching) to complete, showing a fallback UI in the interim. This enables a "Render-as-You-Fetch" pattern.
+
+* **`Suspense` Component:** Wraps children components that might "suspend". Requires a `fallback` prop, which is the `Html` to render during suspension.
+* **Suspending Hooks:** A hook can signal suspension by returning `Err(Suspension)`.
+* **`Suspension::new()`:** Creates a `Suspension` and a `SuspensionHandle`. When `handle.resume()` is called (or `handle` is dropped), the suspended component re-renders.
+ ```rust
+ use yew::prelude::*;
+ use yew::suspense::{Suspension, SuspensionResult};
+
+ // A hypothetical async data loading function
+ async fn fetch_user_data() -> String { "AI Robot Coder".to_string() }
+
+ // This hook will suspend rendering until user data is fetched
+ #[hook]
+ fn use_current_user() -> SuspensionResult {
+ let (suspension, handle) = Suspension::new(); // Create suspension
+ let user_data_state = use_state(|| None ); // Local state for fetched data
+
+ // If data is already there, return Ok.
+ if let Some(data) = &*user_data_state {
+ return Ok(data.clone());
+ }
+
+ // If not, spawn an async task and signal suspension.
+ let user_data_state_clone = user_data_state.clone();
+ wasm_bindgen_futures::spawn_local(async move {
+ let data = fetch_user_data().await;
+ user_data_state_clone.set(Some(data)); // Update state
+ handle.resume(); // Signal the suspension to resume
+ });
+
+ Err(suspension) // Signal that the component should suspend
+ }
+
+ #[function_component]
+ fn UserDisplay() -> HtmlResult { // HtmlResult instead of Html for suspending components
+ let user_name = use_current_user()?; // The '?' operator propagates the suspension
+ Ok(html! {