GXI

Tests

Zero-Cost Cross-Platform Native Widget based Component System in Rust

Using proc-macros, gxi compiles the component tree to optimized n-binary tree without any virtual dom or diffing algorithm. Making the component system zero-cost. Therefore, the components are highly optimized, ready to meet the needs of every project while maintaining the standard features of frameworks like React. Built-in async support provides zero-cost abstractions to rust futures.

Since the framework is a compiler, therefore, it allows mixing of platform-dependent and independent components, i.e the framework provides components like div, h1 (platform dependent) and React Native like platform-independent components like Text and View. Therefore, making the code portable without losing deep control of the native system.

Platforms

Examples

Example For Desktop GTK App

```rust use crate::*;

enum Msg { INC, DEC, }

gxi! { pub Counter { count : u32 = 0 } render { View [ View ( setorientation = gtk::Orientation::Vertical) [ Button ( setlabel = "Inc", connectclicked = || Msg::INC ), Button ( setlabel = "Dec", connectclicked = || Msg::DEC ) ], Text ( setlabel = &state.count.tostring() ) ] } update { let mut state = getstate_mut!(state); match msg { Msg::INC => state.count += 1, _ => { if state.count > 0 { state.count -= 1; } else { return Ok(ShouldRender::No); } } } Ok(ShouldRender::Yes) } }

//extend the abilities impl Counter { pub fn count(&mut self, count: Option) { if let Some(count) = count { { let mut state = getstatemut!(self.state); state.count = count; } self.mark_dirty(); } } } ```

Async Example Using Web App

```rust use crate::*; use serde_json::Value;

enum Msg { Fetch(bool), }

gxi! { pub async CatFact { catfact : Option = None } render { Init ( oninit = || Msg::Fetch(true) ) [ Button ( class = "btn btn-dark" , onclick = || Msg::Fetch(false), innerhtml = "Fetch Cat Memes" ), Div [ if state.catfact.isnone() { Div ( class = "spinner-border text-info" ) } else { H3 ( class = "text-light", innerhtml = &state.catfact.asref().unwrap() ) } ] ] } update { match msg { Msg::Fetch(force) => { if { let mut state = getstatemut!(state); if state.catfact.issome() { state.catfact = None; drop(state); render(); true } else { false } } || force { let resp = reqwest::get("https://catfact.ninja/fact?maxlength=140").await?; let catfact:Value = serdejson::fromstr(&resp.text().await?)?; let mut state = getstatemut!(state); state.catfact = Some(catfact["fact"].to_string()); Ok(ShouldRender::Yes) } else { Ok(ShouldRender::No) } } } } } ```

Full src here

Code of conduct

Code of conduct can be found at CODEOFCONDUCT.md

Contributing

Make sure to read Contribution Guidelines before contributing.

License & Copyright

Copyright (C) 2020 Aniket Prajapati

Licensed under the MIT LICENSE

Contributors