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.
Here is some preview of DOM syntax:
rust
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:
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.
Declaring a store:
```rust
pub struct Store { pub states: StatesTree, // TODO you app data }
pub enum ActionOp {
// TODO
StatesChange(Vec
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(()) } } ```
Declaring an app:
```rust
struct App {
store: Rc
impl RespoApp for App { type Model = Store; type Action = ActionOp;
fn getstore(&self) -> Rc
fn dispatch(store: &mut RefMut
fn view(store: Ref
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:
```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"); ```
Apache License 2.0 .