cocoanut 0.2.3

A minimal, declarative macOS GUI framework for Rust
use crate::view::View;

pub trait Component {
    fn render(&self) -> View;
}

pub trait ComponentState {
    type Props;

    fn new(props: Self::Props) -> Self;
    fn render(&self) -> View;
}

#[macro_export]
macro_rules! component {
    ($name:ident, $body:expr) => {
        pub fn $name() -> $crate::view::View {
            $body
        }
    };
}

#[macro_export]
macro_rules! stateful_component {
    ($name:ident { $($field:ident: $ty:ty),* $(,)? } => $render:expr) => {
        pub struct $name {
            $(pub $field: $ty),*
        }

        impl $crate::component::Component for $name {
            fn render(&self) -> $crate::view::View {
                $render(self)
            }
        }
    };
}

#[cfg(test)]
mod tests {
    use crate::component::Component;
    use crate::view::View;

    crate::component! {
        test_banner,
        View::text("banner")
    }

    #[test]
    fn component_macro_renders_view() {
        let v = test_banner();
        assert_eq!(v.view_type(), "Text");
    }

    #[test]
    fn component_trait_render() {
        struct StaticRow;
        impl Component for StaticRow {
            fn render(&self) -> View {
                View::label("row")
            }
        }
        assert_eq!(StaticRow.render().view_type(), "Label");
    }
}