GitXplorerGitXplorer
s

skima

public
7 stars
0 forks
0 issues

Commits

List of commits on branch master.
Unverified
0c41f88971126c2e37559741407b35960d5cae5b

Various bug fixes and improvements

ss-panferov committed a year ago
Unverified
634a7a060bae0f724bee99330be8bb5b1bb2e78b

Better `RefCell` handling for `reactive`

ss-panferov committed 2 years ago
Unverified
2ae93ddcacaaee2e4a0721aba70eeb68439193a1

More debug info for some errors

ss-panferov committed 2 years ago
Unverified
058557bd8d8b0701d5a5fa0bcde93070f3795621

Add `Root::portal`

ss-panferov committed 2 years ago
Unverified
be14b0006820e88ebb7ce78437ff273e28a92cb5

`fixed` should render to body

ss-panferov committed 2 years ago
Unverified
68b707b5c70452c6862f9eba2b05f0fe680f32ac

Add `StatefulContext::wrap_res_0`

ss-panferov committed 2 years ago

README

The README file for this repository.

Skima

An experimental library for building web interfaces in Rust with full support of the Rust type system.

The goal is to provide a simple and clean API to build interfaces that should recemble a familliar React way, but better.

Minimal example:

use skima::web::prelude::*;

fn component() -> impl Markup {
  div((
    classname("myclass"),
    h1("Hello world")
  ))
} 

This is a simple funtion that returns some markup. No macros, no hidden magick, just Rust. The returned type impl Markup is hiding a complex type we build internally, which will be something like:

Tag<"div", (ClassName, Tag<"html", &'static str>)>

As you can see, the library does not do any type erasure or heap allocation. Instead, we rely on Rust's tuples and native types like Option to build complex anonymous structures that represent your UI. We are not building a shapeless tree like other libraries do, instead we are building a statically-known tree and this enables some interesting optimizations:

  1. We are not using any virtual DOM to make it work. Because we can guarantee that we return the same type every time, we can just rely on a pre-defined set of rules to update the tree.

  2. We can know in a compile time what parts of the template are static to avoid reconcillation at the runtime.

Features

Components as functions

use skima::web::prelude::*;

#[derive(Eq, PartialEq)]
struct ButtonProps {
  value: usize,
  on_click: Option<Callback<dyn Fn(usize)>>,
}

fn my_button(props: ButtonProps) -> impl Markup {
  div((
    "Button",
    props.value.to_string(),
    props.on_click.map(|f| {
      on("click", move |_| f(props.value))
    })
  ))
}

Option combinator

We implement the Markup trait for the native Option type. This allows to use Rust's native API to render something optionally:

use skima::web::prelude::*;

fn component(show_link: bool) -> impl Markup {
  div((
    show_link.then(|| a("I'm a link"))
  ))
}

Any markup may be wrapped with an Option, so you can toggle classes, attributes and anything else.

Reactivity

use skima::web::prelude::*;

fn counter(name: String) -> impl Markup {
  reactive(|cx| {
    cx.with(0 as usize);

    let on_click = cx.callback_1(|cx, _| {
      let current = cx.get::<usize>();
      cx.set::<usize>(current + 1);
    });

    let current = cx.get::<usize>();

    div((
      current.to_string(), 
      on("click", on_click)
    ))
  })
}

Variables with observe

Take a look: observe

use skima::web::prelude::*;
use observe::{Var, batch};

fn component() -> impl Markup {
  reactive(|cx| {
    let flag = cx.with_memo(|| Var::new(true));

    let text = if *flag.get(cx) {
      "True"
    } else {
      "False"
    };

    let on_click = cx.callback_1({
      let flag = flag.clone();
      move |_, ev| batch(|| flag.toggle())
    });

    div((
      text,
      on("click", on_click),
    ))
  })
}

More features

Undocumented features

Those features do exist and work, but need some documentation and examples (TODO):

  • Event handlers and callbacks
  • Effects and cleanup in reactive components
  • Static optimizations
  • Either combinator
  • Portals
  • Bump allocation
  • Routing helpers

Limitations

  • This library relies heavily on some of the nigtly features, so it works only on the nigtly Rust toolchain.

  • Work in progress.