Skip to content

Commit

Permalink
Builder API (#269)
Browse files Browse the repository at this point in the history
* added node! convenience macro

* added add_class and remove_class to

* changed name from value to class

* initial implementation of render-agnostic builder API

* converted from self to &self

* implemented add_dyn_child and add_dyn_only_child

* added add_dyn_text

* added all currently supported HTML tags

* fixed type error when compiling with ssr

* added top level component fn and ability to add child components

* renamed all functions to be more declarative and concise

* renamed add_dyn_class to dyn_class

* added bool_attr and dyn_bool_attr

* added fragment fn

* fixed clippy warnings

* fixed use of unstable feature, intersperse_with, and removed unneeded mut

* gated builder mod behind feature flag

* fully documented current iteration of the Builder API

* Apply suggested changes

* added #[allow(dead_code)] to unimplemented functions

* Update packages/sycamore/src/generic_node/ssr_node.rs

* Update packages/sycamore/src/builder/agnostic/mod.rs

* Apply suggestions from review

* Fix clippy

* Add an example for builder API hello world

Co-authored-by: Luke Chu <[email protected]>
Co-authored-by: Luke Chu <[email protected]>
  • Loading branch information
3 people authored Nov 5, 2021
1 parent 82add18 commit 924ed0c
Show file tree
Hide file tree
Showing 14 changed files with 923 additions and 13 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ members = [
"examples/context",
"examples/counter",
"examples/hello",
"examples/hello-builder",
"examples/higher-order-components",
"examples/iteration",
"examples/ssr",
Expand Down
15 changes: 15 additions & 0 deletions examples/hello-builder/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
authors = ["Luke Chu <[email protected]>"]
edition = "2018"
name = "hello-builder"
publish = false
version = "0.1.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
console_error_panic_hook = "0.1.6"
console_log = "0.2.0"
log = "0.4.14"
sycamore = {path = "../../packages/sycamore", features=["experimental-builder-html"]}
wasm-bindgen = "0.2.78"
15 changes: 15 additions & 0 deletions examples/hello-builder/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Hello World!</title>

<style>
body {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
</style>
</head>
<body></body>
</html>
32 changes: 32 additions & 0 deletions examples/hello-builder/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use sycamore::builder::html::*;
use sycamore::prelude::*;

#[component(App<G>)]
fn app() -> Template<G> {
let name = Signal::new(String::new());

div()
.child(
h1().text("Hello ")
.dyn_child(cloned!((name) => move || {
if *create_selector(cloned!((name) => move || !name.get().is_empty())).get() {
span()
.dyn_text(cloned!((name) => move || name.get().to_string()))
.build()
} else {
span().text("World").build()
}
}))
.text("!")
.build(),
)
.child(input().bind_value(name).build())
.build()
}

fn main() {
console_error_panic_hook::set_once();
console_log::init_with_level(log::Level::Debug).unwrap();

sycamore::render(|| template! { App() });
}
9 changes: 6 additions & 3 deletions packages/sycamore-reactive/src/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,14 @@ impl ReactiveScope {
/// Runs the passed future in the reactive scope pointed to by this handle.
pub async fn extend_future<U>(&self, f: impl Future<Output = U>) -> U {
SCOPES.with(|scopes| {
scopes.borrow_mut().push(ReactiveScope(self.0.clone())); // We now have 2 references to the scope.
scopes.borrow_mut().push(ReactiveScope(self.0.clone())); // We now have 2 references to
// the scope.
});
let u = f.await;
SCOPES.with(|scopes| {
scopes.borrow_mut().pop().unwrap(); // Rationale: pop the scope we pushed above.
// Since we have 2 references to the scope, this will not drop the scope.
// Since we have 2 references to the scope, this
// will not drop the scope.
});
u
}
Expand Down Expand Up @@ -184,7 +186,8 @@ impl ReactiveScopeWeak {
// function call.
if let Some(this) = self.0.upgrade() {
SCOPES.with(|scopes| {
scopes.borrow_mut().push(ReactiveScope(this)); // We now have 2 references to the scope.
scopes.borrow_mut().push(ReactiveScope(this)); // We now have 2 references to the
// scope.
});
let u = f.await;
SCOPES.with(|scopes| {
Expand Down
4 changes: 4 additions & 0 deletions packages/sycamore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ html-escape = { version = "0.2.9", optional = true }
indexmap = { version = "1.7.0", features = ["std"] }
js-sys = "0.3.55"
once_cell = { version = "1.8.0", optional = true }
paste = "1.0"
smallvec = "1.6.1"
sycamore-macro = { path = "../sycamore-macro", version = "=0.6.3" }
sycamore-reactive = { path = "../sycamore-reactive", version = "=0.6.3" }
Expand All @@ -36,6 +37,7 @@ features = [
"Comment",
"Document",
"DocumentFragment",
"DomTokenList",
"Element",
"Event",
"HtmlElement",
Expand All @@ -57,6 +59,8 @@ dom = []
futures = ["wasm-bindgen-futures"]
ssr = ["html-escape", "once_cell"]
serde = ["sycamore-reactive/serde"]
experimental-builder-agnostic = []
experimental-builder-html = ["experimental-builder-agnostic"]

[[bench]]
harness = false
Expand Down
Loading

0 comments on commit 924ed0c

Please sign in to comment.