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.

Docs https://docs.rs/respo

Usage

A preview example, to delare a store:

```rust

[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, MaybeState), }

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

impl RespoStore for Store { type Action = ActionOp;

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

To declare an app:

```rust struct App { store: Rc>, mounttarget: Node, memocaches: MemoCache>, }

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

fn getstore(&self) -> Rc> { self.store.clone() } fn getmounttarget(&self) -> &websys::Node { &self.mounttarget } fn getmemocaches(&self) -> MemoCache> { self.memocaches.to_owned() }

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

fn view(store: Ref, memo_caches: MemoCache>) -> Result, 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(),
)

} } ```

mount app:

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

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

CSS-in-Rust:

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))), );

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

License

Apache License 2.0 .