consecuit_html 0.2.0

HTML components for the Consecuit web UI framework.
Documentation
/*! 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;
}