Merge branch 'main' into cargo-leptos-beta

This commit is contained in:
Ben Wishovich 2022-12-27 12:49:17 -08:00 committed by GitHub
commit f8f0d9fae0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 94 additions and 75 deletions

View file

@ -76,7 +76,18 @@ Here are some resources for learning more about Leptos:
## `nightly` Note
Most of the examples assume youre using `nightly` Rust. If youre on stable, note the following:
Most of the examples assume youre using `nightly` Rust.
To set up your rustup toolchain using nightly and
add the ability to compile Rust to WebAssembly:
```
rustup toolchain install nightly
rustup default nightly
rustup target add wasm32-unknown-unknown
```
If youre on stable, note the following:
1. You need to enable the `"stable"` flag in `Cargo.toml`: `leptos = { version = "0.0", features = ["stable"] }`
2. `nightly` enables the function call syntax for accessing and setting signals. If youre using `stable`,
@ -147,17 +158,17 @@ There are some practical differences that make a significant difference:
- **Read-write segregation:** Leptos, like Solid, encourages read-write segregation between signal getters and setters, so you end up accessing signals with tuples like `let (count, set_count) = create_signal(cx, 0);` _(If you prefer or if it's more convenient for your API, you can use `create_rw_signal` to give a unified read/write signal.)_
- **Signals are functions:** In Leptos, you can call a signal to access it rather than calling a specific method (so, `count()` instead of `count.get()`) This creates a more consistent mental model: accessing a reactive value is always a matter of calling a function. For example:
```rust
let (count, set_count) = create_signal(cx, 0); // a signal
let double_count = move || count() * 2; // a derived signal
let memoized_count = create_memo(cx, move |_| count() * 3); // a memo
// all are accessed by calling them
assert_eq!(count(), 0);
assert_eq!(double_count(), 0);
assert_eq!(memoized_count(), 0);
```rust
let (count, set_count) = create_signal(cx, 0); // a signal
let double_count = move || count() * 2; // a derived signal
let memoized_count = create_memo(cx, move |_| count() * 3); // a memo
// all are accessed by calling them
assert_eq!(count(), 0);
assert_eq!(double_count(), 0);
assert_eq!(memoized_count(), 0);
// this function can accept any of those signals
fn do_work_on_signal(my_signal: impl Fn() -> i32) { ... }
```
// this function can accept any of those signals
fn do_work_on_signal(my_signal: impl Fn() -> i32) { ... }
```
- **Signals and scopes are `'static`:** Both Leptos and Sycamore ease the pain of moving signals in closures (in particular, event listeners) by making them `Copy`, to avoid the `{ let count = count.clone(); move |_| ... }` that's very familiar in Rust UI code. Sycamore does this by using bump allocation to tie the lifetimes of its signals to its scopes: since references are `Copy`, `&'a Signal<T>` can be moved into a closure. Leptos does this by using arena allocation and passing around indices: types like `ReadSignal<T>`, `WriteSignal<T>`, and `Memo<T>` are actually wrapper for indices into an arena. This means that both scopes and signals are both `Copy` and `'static` in Leptos, which means that they can be moved easily into closures without adding lifetime complexity.

View file

@ -10,7 +10,7 @@ This document is intended as a running list of common issues, with example code
```rust
let (a, set_a) = create_signal(cx, 0);
let (b, set_a) = create_signal(cx, false);
let (b, set_b) = create_signal(cx, false);
create_effect(cx, move |_| {
if a() > 5 {

View file

@ -9,7 +9,7 @@ use leptos::*;
/// - **step** [`i32`] - The change that should be applied on each step.
#[component]
pub fn SimpleCounter(cx: Scope, initial_value: i32, step: i32) -> web_sys::Element {
let (value, set_value) = create_signal(cx, 0);
let (value, set_value) = create_signal(cx, initial_value);
view! { cx,
<div>

View file

@ -27,7 +27,9 @@ cfg_if! {
let conf = get_configuration(Some("Cargo.toml")).await.unwrap();
let addr = conf.leptos_options.site_address.clone();
HttpServer::new(move || {
let leptos_options = &conf.leptos_options;
App::new()
.service(Files::new("/pkg", "./pkg"))
.service(css)

View file

@ -1,6 +1,6 @@
[package]
name = "leptos_actix"
version = "0.0.2"
version = "0.0.3"
edition = "2021"
authors = ["Greg Johnston"]
license = "MIT"

View file

@ -1,6 +1,6 @@
[package]
name = "leptos_axum"
version = "0.0.4"
version = "0.0.5"
edition = "2021"
authors = ["Greg Johnston"]
license = "MIT"

View file

@ -1,6 +1,6 @@
[package]
name = "leptos"
version = "0.0.20"
version = "0.0.21"
edition = "2021"
authors = ["Greg Johnston"]
license = "MIT"
@ -9,12 +9,12 @@ description = "Leptos is a full-stack, isomorphic Rust web framework leveraging
readme = "../README.md"
[dependencies]
leptos_core = { path = "../leptos_core", default-features = false, version = "0.0.20" }
leptos_config = { path = "../leptos_config", default-features = false, version = "0.0.20" }
leptos_dom = { path = "../leptos_dom", default-features = false, version = "0.0.20" }
leptos_macro = { path = "../leptos_macro", default-features = false, version = "0.0.20" }
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.20" }
leptos_server = { path = "../leptos_server", default-features = false, version = "0.0.20" }
leptos_core = { path = "../leptos_core", default-features = false, version = "0.0.21" }
leptos_config = { path = "../leptos_config", default-features = false, version = "0.0.21" }
leptos_dom = { path = "../leptos_dom", default-features = false, version = "0.0.21" }
leptos_macro = { path = "../leptos_macro", default-features = false, version = "0.0.21" }
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.21" }
leptos_server = { path = "../leptos_server", default-features = false, version = "0.0.21" }
[build-dependencies]
rustc_version = "0.4"

View file

@ -1,6 +1,6 @@
[package]
name = "leptos_config"
version = "0.0.20"
version = "0.0.21"
edition = "2021"
authors = ["Greg Johnston"]
license = "MIT"

View file

@ -1,6 +1,6 @@
[package]
name = "leptos_core"
version = "0.0.20"
version = "0.0.21"
edition = "2021"
authors = ["Greg Johnston"]
license = "MIT"
@ -8,9 +8,9 @@ repository = "https://github.com/gbj/leptos"
description = "Core functionality for the Leptos web framework."
[dependencies]
leptos_dom = { path = "../leptos_dom", default-features = false, version = "0.0.20" }
leptos_macro = { path = "../leptos_macro", default-features = false, version = "0.0.20" }
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.20" }
leptos_dom = { path = "../leptos_dom", default-features = false, version = "0.0.21" }
leptos_macro = { path = "../leptos_macro", default-features = false, version = "0.0.21" }
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.21" }
log = "0.4"
typed-builder = "0.11"

View file

@ -1,6 +1,6 @@
[package]
name = "leptos_dom"
version = "0.0.20"
version = "0.0.21"
edition = "2021"
authors = ["Greg Johnston"]
license = "MIT"
@ -12,7 +12,7 @@ cfg-if = "1"
futures = "0.3"
html-escape = "0.2"
js-sys = "0.3"
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.20" }
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.21" }
serde_json = "1"
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4.31"

View file

@ -1,6 +1,6 @@
[package]
name = "leptos_macro"
version = "0.0.20"
version = "0.0.21"
edition = "2021"
authors = ["Greg Johnston"]
license = "MIT"
@ -19,9 +19,9 @@ quote = "1"
syn = { version = "1", features = ["full", "parsing", "extra-traits"] }
syn-rsx = "0.9"
uuid = { version = "1", features = ["v4"] }
leptos_dom = { path = "../leptos_dom", version = "0.0.20" }
leptos_reactive = { path = "../leptos_reactive", version = "0.0.20" }
leptos_server = { path = "../leptos_server", version = "0.0.20" }
leptos_dom = { path = "../leptos_dom", version = "0.0.21" }
leptos_reactive = { path = "../leptos_reactive", version = "0.0.21" }
leptos_server = { path = "../leptos_server", version = "0.0.21" }
lazy_static = "1.4"
[dev-dependencies]

View file

@ -1,6 +1,6 @@
[package]
name = "leptos_reactive"
version = "0.0.20"
version = "0.0.21"
edition = "2021"
authors = ["Greg Johnston"]
license = "MIT"

View file

@ -49,7 +49,7 @@ use std::fmt::Debug;
/// ```
pub fn create_effect<T>(cx: Scope, f: impl Fn(Option<T>) -> T + 'static)
where
T: Debug + 'static,
T: 'static,
{
cfg_if! {
if #[cfg(not(feature = "ssr"))] {
@ -90,7 +90,7 @@ where
/// # }).dispose();
pub fn create_isomorphic_effect<T>(cx: Scope, f: impl Fn(Option<T>) -> T + 'static)
where
T: Debug + 'static,
T: 'static,
{
let e = cx.runtime.create_effect(f);
cx.with_scope_property(|prop| prop.push(ScopeProperty::Effect(e)))
@ -99,7 +99,7 @@ where
#[doc(hidden)]
pub fn create_render_effect<T>(cx: Scope, f: impl Fn(Option<T>) -> T + 'static)
where
T: Debug + 'static,
T: 'static,
{
create_effect(cx, f);
}

View file

@ -215,7 +215,7 @@ where
#[cfg(not(feature = "stable"))]
impl<T> FnOnce<()> for Memo<T>
where
T: Debug + Clone,
T: Clone,
{
type Output = T;
@ -227,7 +227,7 @@ where
#[cfg(not(feature = "stable"))]
impl<T> FnMut<()> for Memo<T>
where
T: Debug + Clone,
T: Clone,
{
extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
self.get()
@ -237,7 +237,7 @@ where
#[cfg(not(feature = "stable"))]
impl<T> Fn<()> for Memo<T>
where
T: Debug + Clone,
T: Clone,
{
extern "rust-call" fn call(&self, _args: ()) -> Self::Output {
self.get()

View file

@ -67,7 +67,7 @@ pub fn create_resource<S, T, Fu>(
) -> Resource<S, T>
where
S: PartialEq + Debug + Clone + 'static,
T: Debug + Serializable + 'static,
T: Serializable + 'static,
Fu: Future<Output = T> + 'static,
{
// can't check this on the server without running the future
@ -92,7 +92,7 @@ pub fn create_resource_with_initial_value<S, T, Fu>(
) -> Resource<S, T>
where
S: PartialEq + Debug + Clone + 'static,
T: Debug + Serializable + 'static,
T: Serializable + 'static,
Fu: Future<Output = T> + 'static,
{
let resolved = initial_value.is_some();
@ -174,7 +174,7 @@ pub fn create_local_resource<S, T, Fu>(
) -> Resource<S, T>
where
S: PartialEq + Debug + Clone + 'static,
T: Debug + 'static,
T: 'static,
Fu: Future<Output = T> + 'static,
{
let initial_value = None;
@ -196,7 +196,7 @@ pub fn create_local_resource_with_initial_value<S, T, Fu>(
) -> Resource<S, T>
where
S: PartialEq + Debug + Clone + 'static,
T: Debug + 'static,
T: 'static,
Fu: Future<Output = T> + 'static,
{
let resolved = initial_value.is_some();
@ -245,7 +245,7 @@ where
fn load_resource<S, T>(_cx: Scope, _id: ResourceId, r: Rc<ResourceState<S, T>>)
where
S: PartialEq + Debug + Clone + 'static,
T: Debug + 'static,
T: 'static,
{
r.load(false)
}
@ -254,7 +254,7 @@ where
fn load_resource<S, T>(cx: Scope, id: ResourceId, r: Rc<ResourceState<S, T>>)
where
S: PartialEq + Debug + Clone + 'static,
T: Debug + Serializable + 'static,
T: Serializable + 'static,
{
use wasm_bindgen::{JsCast, UnwrapThrowExt};
@ -320,7 +320,7 @@ where
impl<S, T> Resource<S, T>
where
S: Debug + Clone + 'static,
T: Debug + 'static,
T: 'static,
{
/// Clones and returns the current value of the resource ([Option::None] if the
/// resource is still pending). Also subscribes the running effect to this
@ -427,7 +427,7 @@ where
pub struct Resource<S, T>
where
S: Debug + 'static,
T: Debug + 'static,
T: 'static,
{
runtime: RuntimeId,
pub(crate) id: ResourceId,
@ -444,7 +444,7 @@ slotmap::new_key_type! {
impl<S, T> Clone for Resource<S, T>
where
S: Debug + Clone + 'static,
T: Debug + Clone + 'static,
T: Clone + 'static,
{
fn clone(&self) -> Self {
Self {
@ -459,7 +459,7 @@ where
impl<S, T> Copy for Resource<S, T>
where
S: Debug + Clone + 'static,
T: Debug + Clone + 'static,
T: Clone + 'static,
{
}
@ -467,7 +467,7 @@ where
impl<S, T> FnOnce<()> for Resource<S, T>
where
S: Debug + Clone + 'static,
T: Debug + Clone + 'static,
T: Clone + 'static,
{
type Output = Option<T>;
@ -480,7 +480,7 @@ where
impl<S, T> FnMut<()> for Resource<S, T>
where
S: Debug + Clone + 'static,
T: Debug + Clone + 'static,
T: Clone + 'static,
{
extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
self.read()
@ -491,7 +491,7 @@ where
impl<S, T> Fn<()> for Resource<S, T>
where
S: Debug + Clone + 'static,
T: Debug + Clone + 'static,
T: Clone + 'static,
{
extern "rust-call" fn call(&self, _args: ()) -> Self::Output {
self.read()
@ -502,7 +502,7 @@ where
pub(crate) struct ResourceState<S, T>
where
S: 'static,
T: Debug + 'static,
T: 'static,
{
scope: Scope,
value: ReadSignal<Option<T>>,
@ -520,7 +520,7 @@ where
impl<S, T> ResourceState<S, T>
where
S: Debug + Clone + 'static,
T: Debug + 'static,
T: 'static,
{
pub fn read(&self) -> Option<T>
where
@ -663,7 +663,7 @@ pub(crate) trait SerializableResource {
impl<S, T> SerializableResource for ResourceState<S, T>
where
S: Debug + Clone,
T: Debug + Serializable,
T: Serializable,
{
fn as_any(&self) -> &dyn Any {
self
@ -683,9 +683,6 @@ pub(crate) trait UnserializableResource {
}
impl<S, T> UnserializableResource for ResourceState<S, T>
where
S: Debug,
T: Debug,
{
fn as_any(&self) -> &dyn Any {
self

View file

@ -234,7 +234,16 @@ impl Debug for Runtime {
impl Runtime {
pub fn new() -> Self {
Self::default()
cfg_if! {
if #[cfg(any(feature = "csr", feature = "hydration"))] {
Self::default()
} else {
Runtime {
shared_context: RefCell::new(Some(Default::default())),
..Self::default()
}
}
}
}
pub(crate) fn create_unserializable_resource<S, T>(
@ -243,7 +252,7 @@ impl Runtime {
) -> ResourceId
where
S: Debug + Clone + 'static,
T: Debug + 'static,
T: 'static,
{
self.resources
.borrow_mut()
@ -256,7 +265,7 @@ impl Runtime {
) -> ResourceId
where
S: Debug + Clone + 'static,
T: Debug + Serializable + 'static,
T: Serializable + 'static,
{
self.resources
.borrow_mut()
@ -297,7 +306,7 @@ impl Runtime {
) -> U
where
S: Debug + 'static,
T: Debug + 'static,
T: 'static,
{
let resources = self.resources.borrow();
let res = resources.get(id);

View file

@ -228,7 +228,7 @@ impl<T> Copy for ReadSignal<T> {}
#[cfg(not(feature = "stable"))]
impl<T> FnOnce<()> for ReadSignal<T>
where
T: Debug + Clone,
T: Clone,
{
type Output = T;
@ -240,7 +240,7 @@ where
#[cfg(not(feature = "stable"))]
impl<T> FnMut<()> for ReadSignal<T>
where
T: Debug + Clone,
T: Clone,
{
extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
self.get()
@ -250,7 +250,7 @@ where
#[cfg(not(feature = "stable"))]
impl<T> Fn<()> for ReadSignal<T>
where
T: Debug + Clone,
T: Clone,
{
extern "rust-call" fn call(&self, _args: ()) -> Self::Output {
self.get()
@ -734,7 +734,7 @@ where
#[cfg(not(feature = "stable"))]
impl<T> FnOnce<()> for RwSignal<T>
where
T: Debug + Clone,
T: Clone,
{
type Output = T;
@ -746,7 +746,7 @@ where
#[cfg(not(feature = "stable"))]
impl<T> FnMut<()> for RwSignal<T>
where
T: Debug + Clone,
T: Clone,
{
extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
self.get()
@ -756,7 +756,7 @@ where
#[cfg(not(feature = "stable"))]
impl<T> Fn<()> for RwSignal<T>
where
T: Debug + Clone,
T: Clone,
{
extern "rust-call" fn call(&self, _args: ()) -> Self::Output {
self.get()

View file

@ -1,6 +1,6 @@
[package]
name = "leptos_server"
version = "0.0.20"
version = "0.0.21"
edition = "2021"
authors = ["Greg Johnston"]
license = "MIT"
@ -8,8 +8,8 @@ repository = "https://github.com/gbj/leptos"
description = "RPC for the Leptos web framework."
[dependencies]
leptos_dom = { path = "../leptos_dom", default-features = false, version = "0.0.20" }
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.20" }
leptos_dom = { path = "../leptos_dom", default-features = false, version = "0.0.21" }
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.21" }
form_urlencoded = "1"
gloo-net = "0.2"
lazy_static = "1"

View file

@ -1,6 +1,6 @@
[package]
name = "leptos_meta"
version = "0.0.5"
version = "0.0.6"
edition = "2021"
authors = ["Greg Johnston"]
license = "MIT"

View file

@ -1,6 +1,6 @@
[package]
name = "leptos_router"
version = "0.0.6"
version = "0.0.7"
edition = "2021"
authors = ["Greg Johnston"]
license = "MIT"