gxi 0.1.0

CrossPlatform Native Widget based Component System in rust
docs.rs failed to build gxi-0.1.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: gxi-0.6.1

GXI

Cross-Platform Native Widget based Component System in Rust

🎉🥂🥳 Async Support is here

This project implements a component system of GUI widgets and nodes. Using rust proc-macros compiles the component tree to optimized logical n-binary tree flow which prevents the use of any virtual dom or diffing algorithms. Making the component system zero cost. Hence the components are highly optimized, performant, and customized to meet the needs of each project while maintaining the standard features of frameworks like React. Built-in async support allows for quick and performant 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

  • Desktop (GTK) Windows, Mac and Linux
  • Web wasm32-unknown-unknown
  • Platform Independent (Web and GTK)
  • Android
  • Ios

Examples

Example For Desktop GTK App

use gxi::*;

enum Msg {
    INC,
    DEC,
}

comp! {
    Counter {
        count : u32 = 0
    }
    render {
        View [
            View [
                Button ( label = "Inc", on_click = || Msg::INC ),
                Button ( label = "Dec", on_click = || Msg::DEC )
            ],
            Text ( label = &state.count.to_string() )
        ]
    }
    update {
        match msg {
            Msg::INC => {
                let mut state = state.lock().unwrap();
                state.count += 1;
            }
            _ => {
                let mut state = state.lock().unwrap();
                if state.count > 0 {
                    state.count -= 1;
                } else {
                    return Ok(ShouldRender::No);
                }
            }
        }
        Ok(ShouldRender::Yes)
    }
}

Example For Web App

use gxi::*;

enum Msg {
    INC,
    DEC,
}

comp! {
    App {
        count: u32 = 0
    }
    render {
        Div [
            Body ( style = r#"background-color : #121212;"# ),
            Head [
                Title ( inner_html = "Hello World" ),
                Link ( rel = "stylesheet", href = "https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" ),
                Meta ( name = "viewport", content = "width=device-width, initial-scale=1" )
            ],
            A ( href = "https://webbuddy360.com" ) [
                H1 ( label = "hello world" ),
            ],
            Div [
                Button ( label = "Inc", on_click = || Msg::INC , class="btn btn-dark"),
                Button ( label = "Dec", on_click = || Msg::DEC , class="btn btn-light")
            ],
            H2 ( label = &state.count.to_string() , class = "text-info")
        ]
    }
}

#[update(App)]
async fn update<F: Fn() + 'static>(state: AsyncState, msg: Msg, _render: F) -> AsyncResult<ShouldRender> {
    match msg {
        Msg::INC => {
            let mut state = state.lock().unwrap();
            state.count += 1;
        }
        _ => {
            let mut state = state.lock().unwrap();
            if state.count > 0 {
                state.count -= 1;
            } else {
                return Ok(ShouldRender::No);
            }
        }
    }
    Ok(ShouldRender::Yes)
}

More examples here

Contribution

Contributors can help by writing bindings.