();
root.children.set_index(1);
}, "username: " }
- input { class: "input", id: "psw", on_click: fn(psw: &mut Input, _, document) {
- if let Some(usr) = document.get_element_by_id::
("usr") {
- document.draw(rsx! {
- text { static "Username: {}\nPassword: {}", usr.text, psw.text }
- });
- }
+
+ input { class: "input", id: "psw", on_click: fn(_, _, document) {
+ let root = document.get_root::
();
+ root.children.set_index(2);
}, "password: " }
+
+ button { class: "input", on_click: fn(_, _, document) {
+ if let Some(usr) = document.get_element_by_id::
("usr") {
+ if let Some(psw) = document.get_element_by_id::
("psw") {
+ document.draw(rsx! {
+ text { static "Username: {}\nPassword: {}", usr.text, psw.text }
+ });
+ }
+ }
+ }, "Submit" }
}
}
diff --git a/src/lib.rs b/src/lib.rs
index d131c3a..ae30531 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,10 +9,26 @@
//!
//! ```rust
//! use osui::prelude::*;
+//!
+//! #[component]
+//! pub fn App() -> Element {
+//! let count = State::new(0);
//!
-//! launch(rsx! {
-//! text { "Hello, World!" }
-//! });
+//! rsx! {
+//! button {
+//! class: "btn",
+//!
+//! on_click: fn(_, _, _) @count {
+//! count += 1;
+//! },
+//!
+//! "The current count is: {count}"
+//! }
+//! }
+//! }
+//! fn main() {
+//! launch!(App);
+//! }
//! ```
//!
//! ## Modules
@@ -42,9 +58,10 @@ pub mod prelude {
pub use crate::ui::Instruction::*;
pub use crate::ui::Number::{Auto, Center};
pub use crate::{self as osui, css, ersx, launch, rsx, ui::*, Handler};
- pub use crate::{style, Document, State};
+ pub use crate::{style, Component, Document, State};
pub use crate::{Children, Element, ElementCore, ElementWidget};
pub use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind};
+ pub use osui_element::component;
pub fn sleep(ms: u64) {
std::thread::sleep(std::time::Duration::from_millis(ms));
}
@@ -77,6 +94,11 @@ pub trait ElementWidget: ElementCore + std::fmt::Debug {
}
}
+pub trait Component: std::fmt::Debug {
+ type Element;
+ fn create_element(self) -> Self::Element;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////////////
/// Structs
//////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/macros.rs b/src/macros.rs
index 0984680..da8547f 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -1,18 +1,18 @@
#[macro_export]
macro_rules! launch {
- ($expr:expr) => {
- let mut element = $expr;
+ ($elem:path) => {
+ let mut element = <$elem>::default().create_element();
let mut document = $crate::Document::with_elem(&mut element);
while document.run() {
- element = $expr;
+ element = <$elem>::default().create_element();
}
};
- ($expr:expr, $css:expr) => {
- let mut element = $expr;
+ ($elem:path, $css:expr) => {
+ let mut element = <$elem>::default().create_element();
let mut document = $crate::Document::with_elem(&mut element);
document.set_css($css);
while document.run() {
- element = $expr;
+ element = <$elem>::default().create_element();
}
};
}
diff --git a/src/main.rs b/src/main.rs
index 87b503d..8e0f9c9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,4 @@
-use osui::{examples::*, launch};
-
+use osui::{examples::login_example::App, prelude::*};
fn main() {
- launch!(login_example::app());
+ launch!(App);
}
diff --git a/src/rsx.rs b/src/rsx.rs
index 18a0b9f..6ad8eda 100644
--- a/src/rsx.rs
+++ b/src/rsx.rs
@@ -17,12 +17,8 @@ macro_rules! parse_rsx_param {
osui::parse_rsx_param!($elem, $($rest)*);
};
- ($elem:expr, static $text:expr) => {
- $elem.children.set_static_force(format!($text))
- };
-
- ($elem:expr, static $text:expr, $($inner:tt)*) => {
- $elem.children.set_static_force(format!($text, $($inner)*))
+ ($elem:expr, static $text:literal $($other:tt)*) => {
+ $elem.children = $crate::Children::StaticText(format!($text $($other)*));
};
($elem:expr, for ($($for:tt)*) $code:block $($rest:tt)*) => {
@@ -85,39 +81,29 @@ macro_rules! parse_rsx_param {
};
($elem:expr, $elem_path:path { $($inner:tt)* } $($rest:tt)*) => {
- if $elem.children.is_none() {$elem.children = $crate::Children::Children(Vec::new(), 0)}
if let $crate::Children::Children(children, _) = &mut $elem.children {
- children.push(osui::ersx!($elem_path { $($inner)* }));
+ children.push($crate::ersx!($elem_path { $($inner)* }));
+ } else {
+ $elem.children = $crate::Children::Children(vec![$crate::ersx!($elem_path { $($inner)* })], 0)
}
osui::parse_rsx_param!($elem, $($rest)*)
};
- ($elem:expr, $text:expr) => {
- $elem.children.set_text_force(std::sync::Arc::new(move || format!($text)))
+ ($elem:expr, $text:literal $($other:tt)*) => {
+ $elem.children = $crate::Children::Text(
+ std::sync::Arc::new(move || format!($text $($other)*))
+ );
};
- ($elem:expr, $text:expr, $($inner:tt)*) => {
- $elem.children.set_text_force(std::sync::Arc::new(move || format!($text, $($inner)*)))
- };
-
- ($elem:expr, ) => {};
- ($elem:expr) => {};
+ ($elem:expr,) => {};
}
#[macro_export]
macro_rules! ersx {
($elem:path { $($inner:tt)* }) => {{
- #[allow(unused_mut)]
- let mut elem = $elem();
+ let mut elem = <$elem>::default();
$crate::parse_rsx_param!(elem, $($inner)*);
- elem
- }};
-
- ($elem:path as $t:ty { $($inner:tt)* }) => {{
- #[allow(unused_mut)]
- let mut elem = paste::paste!{$elem::<$t>}();
- $crate::parse_rsx_param!(elem, $($inner)*);
- elem
+ elem.create_element()
}};
}
diff --git a/src/ui/mod.rs b/src/ui/mod.rs
index 68b170c..f6d0e14 100644
--- a/src/ui/mod.rs
+++ b/src/ui/mod.rs
@@ -7,10 +7,9 @@ pub mod styles;
pub use styles::*;
use crate::prelude::*;
-use osui_element::{elem_fn, element};
+use osui_element::element;
#[element]
-#[elem_fn]
#[derive(Default, Debug)]
pub struct Text {}
@@ -20,13 +19,22 @@ impl ElementWidget for Text<'_> {
}
}
+#[component]
+pub fn text<'a>(class: &'a str, id: &'a str, children: Children, style: Style) -> Box
> {
+ Box::new(Text {
+ class: self.class,
+ id: self.id,
+ children: self.children,
+ style: self.style,
+ })
+}
+
#[derive(Debug)]
pub enum Instruction {
SetStyle(Css),
}
#[element]
-#[elem_fn]
#[derive(Default, Debug)]
pub struct Div {
pub instructions: Vec,
@@ -84,8 +92,24 @@ impl ElementWidget for Div<'_> {
}
}
+#[component]
+pub fn div<'a>(
+ class: &'a str,
+ id: &'a str,
+ children: Children,
+ style: Style,
+ instructions: Vec,
+) -> Box> {
+ Box::new(Div {
+ children: self.children,
+ class: self.class,
+ id: self.id,
+ style: self.style,
+ instructions: self.instructions,
+ })
+}
+
#[element]
-#[elem_fn]
#[derive(Default, Debug)]
pub struct Button {
pub on_click: Handler