Skip to content

Commit

Permalink
add Component trait and feature-flagged comp! macro to seed proper
Browse files Browse the repository at this point in the history
  • Loading branch information
glennsl committed May 2, 2021
1 parent 9055211 commit 1c9fc18
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Added macro `raw_svg!` (#589).
- Added `browser::dom::Namespace` to `prelude`.
- Adapted to Rust 1.51.0.
- Added an experimental component API, feature-flagged behind `experimental-component-api`, and the `experimental-component` example to demonstrate its use.

## v0.8.0
- [BREAKING] Rename `linear_gradient!` to `linearGradient!` for consistency with the other svg macros (same with `radial_gradient!` and `mesh_gradient!`) (#377).
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,4 @@ exclude = [
default = ["panic-hook"]
panic-hook = ["console_error_panic_hook"]
markdown = ["pulldown-cmark"]
experimental-component-api = []
2 changes: 1 addition & 1 deletion examples/experimental_component/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ edition = "2018"
crate-type = ["cdylib"]

[dependencies]
seed = {path = "../../"}
seed = { path = "../../", features = ["experimental-component-api"] }
15 changes: 9 additions & 6 deletions examples/experimental_component/src/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ pub struct Button<S> {
}

impl<S: Into<Cow<'static, str>>> Button<S> {
pub fn into_component<Ms>(self) -> Component<Ms> {
Component {
pub fn into_component<Ms>(self) -> ButtonComponent<Ms> {
ButtonComponent {
label: self.label.into(),
outlined: false,
disabled: false,
Expand All @@ -19,14 +19,15 @@ impl<S: Into<Cow<'static, str>>> Button<S> {
}
}

pub struct Component<Ms: 'static> {
#[allow(clippy::module_name_repetitions)]
pub struct ButtonComponent<Ms: 'static> {
label: Cow<'static, str>,
outlined: bool,
disabled: bool,
on_clicks: Vec<Rc<dyn Fn() -> Ms>>,
}

impl<Ms> Component<Ms> {
impl<Ms> ButtonComponent<Ms> {
pub const fn outlined(mut self, outlined: bool) -> Self {
self.outlined = outlined;
self
Expand All @@ -41,8 +42,10 @@ impl<Ms> Component<Ms> {
self.on_clicks.push(Rc::new(move || on_click.clone()()));
self
}
}

pub fn into_node(self) -> Node<Ms> {
impl<Ms> Component<Ms> for ButtonComponent<Ms> {
fn render(&self) -> Node<Ms> {
let attrs = {
let mut attrs = attrs! {};

Expand Down Expand Up @@ -84,7 +87,7 @@ impl<Ms> Component<Ms> {
let mut button = button![css, attrs, self.label];

if !self.disabled {
for on_click in self.on_clicks {
for on_click in self.on_clicks.iter().cloned() {
button.add_event_handler(ev(Ev::Click, move |_| on_click()));
}
}
Expand Down
9 changes: 0 additions & 9 deletions examples/experimental_component/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,6 @@ fn view(model: &Model) -> Node<Msg> {
]
}

#[macro_export]
macro_rules! comp {
($init:expr, $($opt_field:ident => $opt_val:expr),* $(,)?) => {
$init.into_component()
$( .$opt_field($opt_val) )*
.into_node()
};
}

// ------ ------
// Start
// ------ ------
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,8 @@ pub mod prelude {
// https://github.com/rust-lang-nursery/reference/blob/master/src/macros-by-example.md
shortcuts::*,
virtual_dom::{
el_key, el_ref::el_ref, AsAtValue, At, AtValue, CSSValue, El, ElRef, Ev, EventHandler,
IntoNodes, Node, St, Tag, ToClasses, UpdateEl, UpdateElForIterator, View,
el_key, el_ref::el_ref, AsAtValue, At, AtValue, CSSValue, Component, El, ElRef, Ev,
EventHandler, IntoNodes, Node, St, Tag, ToClasses, UpdateEl, UpdateElForIterator, View,
},
};
pub use indexmap::IndexMap; // for attrs and style to work.
Expand Down
14 changes: 14 additions & 0 deletions src/shortcuts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,3 +553,17 @@ macro_rules! key_value_pairs {
}
};
}

#[cfg(feature = "experimental-component-api")]
/// Instantiates and renders a `Component`
///
/// NOTE: This is an experimental API that requires the `experimental-component-api` feature.
#[macro_export]
macro_rules! comp {
($init:expr, $($opt_field:ident => $opt_val:expr),* $(,)?) => {
$crate::virtual_dom::component::instantiate(
$init.into_component()
$( .$opt_field($opt_val) )*
)
};
}
2 changes: 2 additions & 0 deletions src/virtual_dom.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod attrs;
pub mod component;
pub mod el_ref;
pub mod event_handler_manager;
pub mod mailbox;
Expand All @@ -11,6 +12,7 @@ pub mod values;
pub mod view;

pub use attrs::Attrs;
pub use component::Component;
pub use el_ref::{el_ref, ElRef, SharedNodeWs};
pub use event_handler_manager::{EventHandler, EventHandlerManager, Listener};
pub use mailbox::Mailbox;
Expand Down
17 changes: 17 additions & 0 deletions src/virtual_dom/component.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use super::Node;

pub trait Component<Ms> {
fn render(&self) -> Node<Ms>;
}

#[allow(clippy::needless_pass_by_value)]
pub fn instantiate<Ms, C: Component<Ms>>(component: C) -> Node<Ms> {
// TODO: This is where we'd create a boundary node and a state container
// that can then either be passed to `render` to be populated, or capture
// hook calls indirectly like React does.
//
// The boundary node will own the state container and remember the component
// configuration, so that it can do a local re-render when triggered by a
// hook.
component.render()
}

0 comments on commit 1c9fc18

Please sign in to comment.