GitXplorerGitXplorer
s

skima

public
7 stars
0 forks
0 issues

Commits

List of commits on branch master.
Unverified
bccb51186b9385a6a678a72177c853dda115b480

Fix `AnyMarkup` impl

ss-panferov committed 2 years ago
Unverified
244d585f1a36cf62ce29e423932addaa12d16cb1

Add debug tools

ss-panferov committed 2 years ago
Unverified
76575d45668c2a0bd88e843c7bc86d393e2d0f94

Fix effect cleanup

ss-panferov committed 2 years ago
Unverified
dfd05c43d87881d98f2160e7f79037e43554011c

Fix `Either` combinator

ss-panferov committed 2 years ago
Unverified
39b9f727399e41bfd6ea53c6965b8d12158fb9f5

Better `unmount`

ss-panferov committed 2 years ago
Unverified
68f097c4c7938dc4bb6198f4a8f971be50c49320

Prototype Markup-based effects

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.