1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
//! A Rust Front-End Library. //! //! Experimental. //! //! Relies on [rustwasm](https://github.com/rustwasm). //! //! Very lightweight and does not support much of the [HTML Standard](https://html.spec.whatwg.org/). More work needs to be done to truly make this a viable option //! for creating client side front-ends with [rustwasm](https://github.com/rustwasm). //! ### Features //! * State Management //! * [JSX](https://github.com/facebook/jsx) -like syntax //! * [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction) construction from a Virtual [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction). //! //! # Use //! ```ignore //! use crate::main_component::Main; //! use wasm_bindgen::prelude::*; //! extern crate rust_fel; //! //! // invoked when the wasm module is instantiated //! #[wasm_bindgen(start)] //! pub fn main() -> Result<(), JsValue> { //! let main = Main::create(); //! let app = rust_fel::App::new(main); //! app.mount("root"); //! //! Ok(()) //! //! ``` //! # Examples //! A ```rust_fel``` [struct](https://doc.rust-lang.org/std/keyword.struct.html) component implements [rust_fel::Component](../rust_fel/trait.Component.html) //!```ignore //!use crate::action::Action; //!use crate::handle; //!use crate::main_child::{ChildProps, MainChild}; //!use std::cell::RefCell; //!use std::rc::Rc; //!use wasm_bindgen::JsCast; //! //!#[derive(Debug, Default, Clone)] //!pub struct MainState { //! count: i32, //!} //! //!pub enum Actions { //! Counter(Action), //!} //! //!#[derive(Debug, Default, Clone)] //!pub struct Main { //! child: handle::Handle<MainChild>, //! id: String, //! state: MainState, //! props: String, //!} //! //!impl Main { //! pub fn create() -> handle::Handle<Self> { //! let main = Main { //! id: "main".to_owned(), //! state: MainState { //! count: 0, //! }, //! child: MainChild::create(), //! ..Default::default() //! }; //! handle::Handle(Rc::new(RefCell::new(main))) //! } //!} //! //!impl rust_fel::Component for handle::Handle<Main> { //! type Properties = String; //! type Message = Actions; //! type State = MainState; //! //! fn add_props(&mut self, props: Self::Properties) { //! self.0.borrow_mut().props = props; //! } //! //! fn reduce_state(&mut self, message: Actions) { //! match message { //! Actions::Counter(Action::Increment) => self.0.borrow_mut().state.count += 100, //! Actions::Counter(Action::Decrement) => self.0.borrow_mut().state.count -= 100, //! } //! //! rust_fel::re_render(self.render(), Some(self.0.borrow().id.clone())); //! } //! //! fn render(&self) -> rust_fel::Element { //! let mut clone_for_props_closure = self.clone(); //! let mut clone_for_inc = self.clone(); //! let mut borrow = self.0.borrow_mut(); //! let state = borrow.state.clone(); //! let props_closure = Rc::new(RefCell::new(move || { //! clone_for_props_closure.reduce_state(Actions::Counter(Action::Decrement)) //! })); //! //! let child_props = ChildProps { //! counter_props: state.count.to_string(), //! closure: Some(props_closure), //! }; //! //! borrow.child.add_props(child_props); //! //! let main_text = rust_fel::html(format!( //! "<span | data-cy=main-text| >Main {}</span>", //! state.count.to_string() //! )); //! //! let inc_button_text = rust_fel::Element::new( //! "TEXT_ELEMENT".to_owned(), //! rust_fel::Props { //! text: Some("Increment".to_owned()), //! ..Default::default() //! }, //! ); //! //! let inc_button = rust_fel::Element::new( //! "button".to_owned(), //! rust_fel::Props { //! on_click: Some(Box::new(move || { //! clone_for_inc.reduce_state(Actions::Counter(Action::Increment)) //! })), //! data_cy: Some("increment-main".to_owned()), //! children: Some(vec![inc_button_text]), //! ..Default::default() //! }, //! ); //! //! let main_el = rust_fel::Element::new( //! "div".to_owned(), //! rust_fel::Props { //! class_name: Some("main-el".to_owned()), //! children: Some(vec![main_text, inc_button, input_wrapper]), //! ..Default::default() //! }, //! ); //! //! let child_wrapper = rust_fel::Element::new( //! "div".to_owned(), //! rust_fel::Props { //! class_name: Some("child-wrapper".to_owned()), //! children: Some(vec![borrow.child.render()]), //! ..Default::default() //! }, //! ); //! //! rust_fel::Element::new( //! "div".to_owned(), //! rust_fel::Props { //! id: Some(borrow.id.clone()), //! class_name: Some("main".to_owned()), //! children: Some(vec![main_el, child_wrapper]), //! ..Default::default() //! }, //! ) //! } //!} //! //!``` //! A ```rust_fel``` functional component with [rust_fel::html](../rust_fel/rsx/fn.html.html) //!```ignore //!pub fn theme_switcher(on_click: rust_fel::ClosureProp, title: String) -> rust_fel::Element { //! let text = rust_fel::html(format!( //! "<span |class=theme-switcher-text|>{}</span>", //! title //! )); //! //! let theme_button = rust_fel::Element::new( //! "button".to_owned(), //! rust_fel::Props { //! on_click: Some(on_click), //! type_attr: Some("button".to_owned()), //! class_name: Some("theme-switcher-button".to_owned()), //! children: Some(vec![text]), //! data_cy: Some(title), //! ..Default::default() //! }, //! ); //! //! rust_fel::Element::new( //! "li".to_owned(), //! rust_fel::Props { //! children: Some(vec![theme_button]), //! ..Default::default() //! }, //! ) //!} //!``` #![doc(html_root_url = "https://docs.rs/rust-fel/0.1.0")] // Must be kept in sync with Cargo.toml #![allow(clippy::single_match)] /// Module containing the [rust_fel::App](../rust_fel/struct.App.html) [struct](https://doc.rust-lang.org/std/keyword.struct.html) which mounts your ```App``` to the [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction). pub mod app; /// Module containing the [rust_fel::Component](../rust_fel/trait.Component.html) trait. Necessary for state management at the [struct](https://doc.rust-lang.org/std/keyword.struct.html) level. pub mod component; /// Module containing the [rust_fel::Element](../rust_fel/struct.Element.html) [struct](https://doc.rust-lang.org/std/keyword.struct.html) which acts as a Virtual [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction). pub mod element; /// Module containing the [rust_fel::Props](../rust_fel/struct.Props.html) [struct](https://doc.rust-lang.org/std/keyword.struct.html) which allows an [rust_fel::Element](../rust_fel/struct.Element.html) to have ```properties``` and ```children```. pub mod props; /// Module containing the functions to ```render``` and [rust_fel::re_render](../rust_fel/fn.re_render.html) the [rust_fel::App](../rust_fel/struct.App.html). pub mod render; /// Module containing all the functions needed for the [rust_fel::html](../rust_fel/fn.html.html) function to create [rust_fel::Element](../rust_fel/struct.Element.html) from strings of [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML). pub mod rsx; #[doc(inline)] pub use crate::app::App; #[doc(inline)] pub use crate::component::Component; #[doc(inline)] pub use crate::element::Element; #[doc(inline)] pub use crate::props::{ClosureProp, Props}; #[doc(inline)] pub use crate::render::re_render; #[doc(inline)] pub use crate::rsx::html;