Tiny toy virtual DOM based framework for Rust

Overview

Respo in Rust

Respo Crate

tiny toy virtual DOM based framework for Rust.

Status: experimenting, unhappy without HMR.

Respo was initially designed to work in a dynamic language with persistent data and HMR(hot code replacement), which is dramatically different from Rust. So this is more like an experiment.

Usage

Here is some preview of DOM syntax:

Ok(
  div()
    .class(ui_global())
    .add_style(RespoStyle::default().padding(12.0).to_owned())
    .add_children([
      comp_counter(&states.pick("counter"), store.counted)?,
      comp_panel(&states.pick("panel"))?,
      comp_todolist(memo_caches, &states.pick("todolist"), &store.tasks)?,
    ])
    .to_owned(),
)

CSS-in-Rust:

static_styles!(
  style_remove_button,
  (
    "$0".to_owned(),
    RespoStyle::default()
      .width(CssSize::Px(16.0))
      .height(CssSize::Px(16.0))
      .margin(4.)
      .cursor("pointer".to_owned())
      .margin4(0.0, 0.0, 0.0, 16.0)
      .color(CssColor::Hsl(0, 90, 90)),
  ),
  ("$0:hover".to_owned(), RespoStyle::default().color(CssColor::Hsl(0, 90, 80))),
);

Builtin styles, demonstrated:

function usages
ui_global global styles
ui_fullscreen fullscreen styles
ui_button button styles
ui_input input styles
ui_textarea textarea styles
ui_link link styles
ui_flex flex:1 styles
ui_expand flex:1 styles with scrolls
ui_center flexbox center styles
ui_row flexbox row styles
ui_column flexbox column styles
ui_row_center flexbox row center styles
ui_column_center flexbox column center styles
ui_row_around flexbox row around styles
ui_column_around flexbox column around styles
ui_row_evenly flexbox row evenly styles
ui_column_evenly flexbox column evenly styles
ui_row_parted flexbox row between styles
ui_column_parted flexbox column between styles
ui_row_middle flexbox row between styles
ui_column_middle flexbox column between styles
ui_font_code code font family
ui_font_normal normal font family(Hind)
ui_font_fancy fancy font family(Josefin Sans)

There are several dialog components in the demo. Syntax is not nice enough, so I'm not advertising it. But they work relatively good.

For more components, read code in src/app/, they are just variants like RespoNode::Component(..). It may be sugared in the future, not determined yet.

Store abstraction

Declaring a store:

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Store {
  pub states: StatesTree,
  // TODO you app data
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ActionOp {
  // TODO
  StatesChange(Vec<String>, MaybeState),
}

impl RespoAction for ActionOp {
  fn wrap_states_action(cursor: &[String], a: MaybeState) -> Self {
    Self::StatesChange(cursor.to_vec(), a)
  }
}

impl RespoStore for Store {
  type Action = ActionOp;

  fn get_states(&self) -> StatesTree {
    self.states.to_owned()
  }
  fn update(&mut self, op: Self::Action) -> Result<(), String> {
    match op {
      // TODO
    }
    Ok(())
  }
}

Declaring an app:

struct App {
  store: Rc<RefCell<Store>>,
  mount_target: Node,
  memo_caches: MemoCache<RespoNode<ActionOp>>,
}

impl RespoApp for App {
  type Model = Store;
  type Action = ActionOp;

  fn get_store(&self) -> Rc<RefCell<Self::Model>> {
    self.store.clone()
  }
  fn get_mount_target(&self) -> &web_sys::Node {
    &self.mount_target
  }
  fn get_memo_caches(&self) -> MemoCache<RespoNode<Self::Action>> {
    self.memo_caches.to_owned()
  }

  fn dispatch(store: &mut RefMut<Self::Model>, op: Self::Action) -> Result<(), String> {
    store.update(op)
  }

  fn view(store: Ref<Self::Model>, memo_caches: MemoCache<RespoNode<Self::Action>>) -> Result<RespoNode<Self::Action>, String> {
    let states = &store.states;
    // util::log!("global store: {:?}", store);

    Ok(
      div()
        .class(ui_global())
        .add_style(RespoStyle::default().padding(12.0).to_owned())
        .add_children([
          comp_counter(&states.pick("counter"), store.counted)?,
          comp_panel(&states.pick("panel"))?,
          comp_todolist(memo_caches, &states.pick("todolist"), &store.tasks)?,
        ])
        .to_owned(),
    )
  }
}

Mounting app:

let app = App {
    mount_target: query_select_node(".app").expect("mount target"),
    store: Rc::new(RefCell::new(Store {
      counted: 0,
      states: StatesTree::default(),
      tasks: vec![],
    })),
    memo_caches: MemoCache::default(),
  };

  app.render_loop().expect("app render");

License

Apache License 2.0 .

You might also like...
bn.js bindings for Rust & WebAssembly with primitive-types support

bn.rs bn.js bindings for Rust & WebAssembly with primitive-types support Write Rust code that uses BN use std::str::FromStr; use primitive_types::{H1

A simple compile-to-WebAssembly language rewritten in Rust

chasm A very simple compile-to-WebAssembly language You can play with chasm online. This is a rewrite in Rust of the compiler for the language chasm.

Stylist is a CSS-in-Rust styling solution for WebAssembly Applications.

Stylist Stylist is a CSS-in-Rust styling solution for WebAssembly Applications. This is a fork of css-in-rust. Install Add the following to your Cargo

Rust WebGL2 wrapper with a focus on making high-performance WebAssembly graphics code easier to write and maintain
Rust WebGL2 wrapper with a focus on making high-performance WebAssembly graphics code easier to write and maintain

Limelight Limelight is a WebGL2 wrapper with a focus on making high-performance WebAssembly graphics code easier to write and maintain. demo.mov live

WebAssembly serialization/deserialization in rust

parity-wasm Low-level WebAssembly format library. Documentation Rust WebAssembly format serializing/deserializing Add to Cargo.toml [dependencies] par

This is a webpack loader that loads Rust code as a WebAssembly module

rust-native-wasm-loader This is a webpack loader that loads Rust code as a WebAssembly module. It uses the native Rust support for compiling to wasm32

Jest preprocessor/transformer for Rust

rs-jest tl;dr -- see examples This is a jest transformer that loads Rust code so it can be interop with Javascript base project. Currently, the Rust c

Wasm video filter booth app written in Rust
Wasm video filter booth app written in Rust

Video effect booth written in Rust and WebAssembly Play with it here: https://mtharrison.github.io/wasmbooth/ Aim I wrote this purely to teach myself

TodoMVC in Rust from Scratch (YouTube video tutorial)

TodoMVC in Rust from Scratch (YouTube video tutorial)

Comments
  • some very early skeleton color

    some very early skeleton color

    nailed down basic ideas on a viable implementation. JavaScript/ClojureScript are too dynamic, while Rust demands on static types and results in very different choices.

    opened by tiye 0
Releases(0.0.17)
Owner
Respo
A virtual DOM MVC library in ClojureScript/Calcit-js
Respo
darkforest is a console and web-based Roguelike written in Rust and WebAssembly.

darkforest darkforest is a console and web-based Roguelike written in Rust and WebAssembly. Key Features TBA Quick Start TBA How To Contribute Contrib

Chris Ohk 5 Oct 5, 2021
A handy calculator, based on Rust and WebAssembly.

qubit ?? Visit Website To Use Calculator Example ?? Visit Website To Use Calculator 2 + 2

Abhimanyu Sharma 55 Dec 26, 2022
Rust-based WebAssembly bindings to read and write Apache Parquet files

parquet-wasm WebAssembly bindings to read and write the Parquet format to Apache Arrow. This is designed to be used alongside a JavaScript Arrow imple

Kyle Barron 103 Dec 25, 2022
Sealed boxes implementation for Rust/WebAssembly.

Sealed boxes for Rust/WebAssembly This Rust crate provides libsodium sealed boxes for WebAssembly. Usage: // Recipient: create a new key pair let reci

Frank Denis 16 Aug 28, 2022
WebAssembly on Rust is a bright future in making application runs at the Edge or on the Serverless technologies.

WebAssembly Tour WebAssembly on Rust is a bright future in making application runs at the Edge or on the Serverless technologies. We spend a lot of ti

Thang Chung 129 Dec 28, 2022
Autogenerated async RPC bindings that instantly connect a JS frontend to a Rust backend service via WebSockets and WASM.

Turbocharger Autogenerated async RPC bindings that instantly connect a JS frontend to a Rust backend service via WebSockets and WASM. See https://gith

null 28 Jan 2, 2023
MORUS cipher for Rust.

MORUS for Rust This is a Rust implementation of MORUS (MORUS-1280-128), ported from the Zig implementation. MORUS is a fast authenticated cipher for p

Frank Denis 4 Oct 24, 2022
A Rust ESP stack trace decoder that can also runs in your browser thanks to WebAssembly

ESP Stack Trace Decoder A Rust ESP stack trace decoder that can also runs in your browser thanks to WebAssembly. It is composed of a ⌨️ Rust library,

Maxime BORGES 20 Oct 5, 2022
Simple file sharing with client-side encryption, powered by Rust and WebAssembly

Hako Simple file sharing with client-side encryption, powered by Rust and WebAssembly Not feature-packed, but basic functionalities are just working.

Jaehyeon Park 30 Nov 25, 2022
Wasm runtime written in Rust

Wasm runtime written in Rust

Teppei Fukuda 1 Oct 29, 2021