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
/*! HTML components for [consecuit]. This crate provides components like `div`, `span`, `table` for [consecuit]. ## Basic usage Also see the docs at [consecuit], as it also contain some info on how to use this. First, import the prelude: ``` use consecuit_html::prelude::*; ``` Then you can use the components in the `cc_tree!` macro with the same structure as HTML: ``` cc_tree!( <div> <div> </div> </div> <span>"hello"</span> ) ``` ## Props All components in this crate takes props that can be built with builder pattern. Start with [`html_props()`][elem::html_props()], then add your attributes. Like this: ``` cc_tree!( <div {html_props().class_name("container container-box").onclick(click_handler)}> </div> ) ``` String attributes like `class_name` or `href` take anything that is `Into<Cow<'static, str>>`. In the code above, `class_name` can take `"container container-box"` because it is `&'static str` which is `Into<Cow<'static, str>>`. Event attributes like `onclick` or `oninput` take a [`Callback`][callback::Callback]. A [`Callback`][callback::Callback] can be created with `Callback::new`, like this: ``` let click_handler = Callback::new(move |ev: web_sys::MouseEvent| { web_sys::console::log_1( &"You clicked the button!".into() ); }); cc_tree!( <button {html_props().onclick(click_handler)}>"click me!"</button> ) ``` Sometimes you may get error about ambigous props. For example, many different components take `href`. The compiler won't allow this: ``` <a {html_props().href("https://example.com")}>"Go to web"</a> ``` You have to use [HtmlProps<(web_sys type of your element)>][elem::HtmlProps] instead. For example: ``` <a {HtmlProps::<web_sys::HtmlAnchorElement>::new().href("https://example.com")}>"Go to web"</a> ``` ## Reference To get a reference to the underlying [web_sys] element, you can use the `reference` prop. The `reference` prop takes a [Reference][consecuit::hooks::Reference] of Option of the element type. For instance, the input tag (`<input>`) has [web_sys::HtmlInputElement] as the underlying element. So its reference must be a `Reference<Option<web_sys::HtmlInputElement>>`. ``` let (cc, input_ref): (_, Reference<Option<web_sys::HtmlInputElement>>) = cc.hook(use_ref, ()); cc_tree!( <input {html_props().reference(input_ref)} /> ) ``` The Option inside the reference is guarunteed to be Some after the component rendered atleast once. You can then use the methods in [Reference][consecuit::hooks::Reference] to do things with the underlying [web_sys] element. For example, this read the value of an <input /> and set it to empty. ``` let (cc, input_ref): (_, Reference<Option<web_sys::HtmlInputElement>>) = cc.hook(use_ref, ()); let submit_click_handler = Callback::new(move |_ev| { let input_value = input_ref.visit_with(|opt: &Option<web_sys::HtmlInputElement>| { // Unwrap the Option<web_sys::HtmlInputElement> let inp: &web_sys::HtmlInputElement = opt.as_ref().unwrap(); // Get the value let value = inp.value(); // Set it to empty inp.set_value(""); value }).unwrap(); web_sys::console::log_1(&format!("The submitted value was: {}", input_value).into()); }); cc_tree!( <input {html_props().reference(input_ref)} /> <button {html_props().onclick(submit_click_handler)}>"submit"</button> ) ``` ## Notes Most of the components and props in this crate are generated by a combination of parsing [web_sys]'s API and scraping MDN. Only attributes with a `set_` method provided by [web_sys] are available as props. For example, [web_sys] has `set_class_name`, so we have `class_name` prop. Most notably missing is styling. [web_sys] does not have `set_style`. (it has a more sophisicated system for styling). You have to stick with class names and CSS for now. Contributions are welcome. */ pub mod callback; pub mod components; pub mod elem; mod interfaces; pub mod misc_components; mod shared; pub mod prelude { pub use crate::callback::Callback; pub use crate::components::*; pub use crate::elem::{html_props, HtmlProps}; pub use crate::misc_components::*; pub use web_sys; }