mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-27 15:44:42 -05:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b54f80f529 | ||
|
|
a48a2994ee | ||
|
|
aedcd5148c | ||
|
|
9160d8aaa6 | ||
|
|
274fe07dae | ||
|
|
7add26fc41 | ||
|
|
d9213850f7 | ||
|
|
db9f323f8d | ||
|
|
1d0f668dc3 | ||
|
|
a97eceacf1 | ||
|
|
3d6ea6d285 | ||
|
|
99c3d8f9e9 | ||
|
|
f50adc00bc | ||
|
|
1340deee96 | ||
|
|
8da3011a7f | ||
|
|
959677f018 | ||
|
|
03529b3992 | ||
|
|
8bfd0ce143 |
26
Cargo.lock
generated
26
Cargo.lock
generated
@@ -1788,7 +1788,7 @@ checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
|
||||
|
||||
[[package]]
|
||||
name = "leptos"
|
||||
version = "0.8.6"
|
||||
version = "0.8.8"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"base64",
|
||||
@@ -1869,7 +1869,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_axum"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"axum",
|
||||
@@ -1892,7 +1892,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_config"
|
||||
version = "0.8.5"
|
||||
version = "0.8.7"
|
||||
dependencies = [
|
||||
"config",
|
||||
"regex",
|
||||
@@ -1906,7 +1906,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_dom"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"leptos",
|
||||
@@ -1952,7 +1952,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_macro"
|
||||
version = "0.8.6"
|
||||
version = "0.8.7"
|
||||
dependencies = [
|
||||
"attribute-derive",
|
||||
"cfg-if",
|
||||
@@ -1972,7 +1972,7 @@ dependencies = [
|
||||
"rustc_version",
|
||||
"serde",
|
||||
"server_fn",
|
||||
"server_fn_macro 0.8.6",
|
||||
"server_fn_macro 0.8.7",
|
||||
"syn 2.0.104",
|
||||
"tracing",
|
||||
"trybuild",
|
||||
@@ -1996,7 +1996,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_router"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"either_of",
|
||||
@@ -2746,7 +2746,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reactive_graph"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"async-lock",
|
||||
@@ -2789,7 +2789,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reactive_stores_macro"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
dependencies = [
|
||||
"convert_case 0.8.0",
|
||||
"proc-macro-error2",
|
||||
@@ -3283,7 +3283,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "server_fn"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"actix-ws",
|
||||
@@ -3346,7 +3346,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "server_fn_macro"
|
||||
version = "0.8.6"
|
||||
version = "0.8.7"
|
||||
dependencies = [
|
||||
"const_format",
|
||||
"convert_case 0.8.0",
|
||||
@@ -3361,7 +3361,7 @@ dependencies = [
|
||||
name = "server_fn_macro_default"
|
||||
version = "0.8.5"
|
||||
dependencies = [
|
||||
"server_fn_macro 0.8.6",
|
||||
"server_fn_macro 0.8.7",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
@@ -3573,7 +3573,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tachys"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"async-trait",
|
||||
|
||||
20
Cargo.toml
20
Cargo.toml
@@ -50,26 +50,26 @@ any_spawner = { path = "./any_spawner/", version = "0.3.0" }
|
||||
const_str_slice_concat = { path = "./const_str_slice_concat", version = "0.1" }
|
||||
either_of = { path = "./either_of/", version = "0.1.6" }
|
||||
hydration_context = { path = "./hydration_context", version = "0.3.0" }
|
||||
leptos = { path = "./leptos", version = "0.8.6" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.8.5" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.8.5" }
|
||||
leptos = { path = "./leptos", version = "0.8.8" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.8.7" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.8.6" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.8.5" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.8.5" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.8.6" }
|
||||
leptos_router = { path = "./router", version = "0.8.5" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.8.7" }
|
||||
leptos_router = { path = "./router", version = "0.8.6" }
|
||||
leptos_router_macro = { path = "./router_macro", version = "0.8.5" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.8.5" }
|
||||
leptos_meta = { path = "./meta", version = "0.8.5" }
|
||||
next_tuple = { path = "./next_tuple", version = "0.1.0" }
|
||||
oco_ref = { path = "./oco", version = "0.2.1" }
|
||||
or_poisoned = { path = "./or_poisoned", version = "0.1.0" }
|
||||
reactive_graph = { path = "./reactive_graph", version = "0.2.5" }
|
||||
reactive_graph = { path = "./reactive_graph", version = "0.2.6" }
|
||||
reactive_stores = { path = "./reactive_stores", version = "0.2.5" }
|
||||
reactive_stores_macro = { path = "./reactive_stores_macro", version = "0.2.5" }
|
||||
server_fn = { path = "./server_fn", version = "0.8.5" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.8.6" }
|
||||
reactive_stores_macro = { path = "./reactive_stores_macro", version = "0.2.6" }
|
||||
server_fn = { path = "./server_fn", version = "0.8.6" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.8.7" }
|
||||
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.8.5" }
|
||||
tachys = { path = "./tachys", version = "0.2.6" }
|
||||
tachys = { path = "./tachys", version = "0.2.7" }
|
||||
wasm_split_helpers = { path = "./wasm_split", version = "0.1.2" }
|
||||
wasm_split_macros = { path = "./wasm_split_macros", version = "0.1.2" }
|
||||
|
||||
|
||||
7
examples/regression/e2e/features/issue_4005.feature
Normal file
7
examples/regression/e2e/features/issue_4005.feature
Normal file
@@ -0,0 +1,7 @@
|
||||
@check_issue_4005
|
||||
Feature: Check that issue 4005 does not reappear
|
||||
|
||||
Scenario: The second item is selected.
|
||||
Given I see the app
|
||||
And I can access regression test 4005
|
||||
Then I see the value of select is 2
|
||||
9
examples/regression/e2e/features/issue_4217.feature
Normal file
9
examples/regression/e2e/features/issue_4217.feature
Normal file
@@ -0,0 +1,9 @@
|
||||
@check_issue_4217
|
||||
Feature: Check that issue 4217 does not reappear
|
||||
|
||||
Scenario: All items are selected.
|
||||
Given I see the app
|
||||
And I can access regression test 4217
|
||||
Then I see option1 is selected
|
||||
And I see option2 is selected
|
||||
And I see option3 is selected
|
||||
25
examples/regression/e2e/tests/fixtures/check.rs
vendored
25
examples/regression/e2e/tests/fixtures/check.rs
vendored
@@ -18,3 +18,28 @@ pub async fn element_exists(client: &Client, id: &str) -> Result<()> {
|
||||
.expect(&format!("could not find element with id `{id}`"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn select_option_is_selected(
|
||||
client: &Client,
|
||||
id: &str,
|
||||
) -> Result<()> {
|
||||
let el = find::element_by_id(client, id)
|
||||
.await
|
||||
.expect(&format!("could not find element with id `{id}`"));
|
||||
let selected = el.prop("selected").await?;
|
||||
assert_eq!(selected.as_deref(), Some("true"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn element_value_is(
|
||||
client: &Client,
|
||||
id: &str,
|
||||
expected: &str,
|
||||
) -> Result<()> {
|
||||
let el = find::element_by_id(client, id)
|
||||
.await
|
||||
.expect(&format!("could not find element with id `{id}`"));
|
||||
let value = el.prop("value").await?;
|
||||
assert_eq!(value.as_deref(), Some(expected));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -25,3 +25,21 @@ async fn i_see_the_navbar(world: &mut AppWorld) -> Result<()> {
|
||||
check::element_exists(client, "nav").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[then(regex = r"^I see ([\d\w]+) is selected$")]
|
||||
async fn i_see_the_select(world: &mut AppWorld, id: String) -> Result<()> {
|
||||
let client = &world.client;
|
||||
check::select_option_is_selected(client, &id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[then(regex = r"^I see the value of (\w+) is (.*)$")]
|
||||
async fn i_see_the_value(
|
||||
world: &mut AppWorld,
|
||||
id: String,
|
||||
value: String,
|
||||
) -> Result<()> {
|
||||
let client = &world.client;
|
||||
check::element_value_is(client, &id, &value).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use crate::{issue_4088::Routes4088, pr_4015::Routes4015, pr_4091::Routes4091};
|
||||
use crate::{
|
||||
issue_4005::Routes4005, issue_4088::Routes4088, issue_4217::Routes4217,
|
||||
pr_4015::Routes4015, pr_4091::Routes4091,
|
||||
};
|
||||
use leptos::prelude::*;
|
||||
use leptos_meta::{MetaTags, *};
|
||||
use leptos_router::{
|
||||
@@ -37,6 +40,8 @@ pub fn App() -> impl IntoView {
|
||||
<Routes4091/>
|
||||
<Routes4015/>
|
||||
<Routes4088/>
|
||||
<Routes4217/>
|
||||
<Routes4005/>
|
||||
</Routes>
|
||||
</main>
|
||||
</Router>
|
||||
@@ -59,6 +64,8 @@ fn HomePage() -> impl IntoView {
|
||||
<li><a href="/4091/">"4091"</a></li>
|
||||
<li><a href="/4015/">"4015"</a></li>
|
||||
<li><a href="/4088/">"4088"</a></li>
|
||||
<li><a href="/4217/">"4217"</a></li>
|
||||
<li><a href="/4005/">"4005"</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
}
|
||||
|
||||
24
examples/regression/src/issue_4005.rs
Normal file
24
examples/regression/src/issue_4005.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use leptos::prelude::*;
|
||||
#[allow(unused_imports)]
|
||||
use leptos_router::{
|
||||
components::Route, path, MatchNestedRoutes, NavigateOptions,
|
||||
};
|
||||
|
||||
#[component]
|
||||
pub fn Routes4005() -> impl MatchNestedRoutes + Clone {
|
||||
view! {
|
||||
<Route path=path!("4005") view=Issue4005/>
|
||||
}
|
||||
.into_inner()
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Issue4005() -> impl IntoView {
|
||||
view! {
|
||||
<select id="select" prop:value="2">
|
||||
<option value="1">"Option 1"</option>
|
||||
<option value="2">"Option 2"</option>
|
||||
<option value="3">"Option 3"</option>
|
||||
</select>
|
||||
}
|
||||
}
|
||||
24
examples/regression/src/issue_4217.rs
Normal file
24
examples/regression/src/issue_4217.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use leptos::prelude::*;
|
||||
#[allow(unused_imports)]
|
||||
use leptos_router::{
|
||||
components::Route, path, MatchNestedRoutes, NavigateOptions,
|
||||
};
|
||||
|
||||
#[component]
|
||||
pub fn Routes4217() -> impl MatchNestedRoutes + Clone {
|
||||
view! {
|
||||
<Route path=path!("4217") view=Issue4217/>
|
||||
}
|
||||
.into_inner()
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Issue4217() -> impl IntoView {
|
||||
view! {
|
||||
<select multiple=true>
|
||||
<option id="option1" value="1" selected>"Option 1"</option>
|
||||
<option id="option2" value="2" selected>"Option 2"</option>
|
||||
<option id="option3" value="3" selected>"Option 3"</option>
|
||||
</select>
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
pub mod app;
|
||||
mod issue_4005;
|
||||
mod issue_4088;
|
||||
mod issue_4217;
|
||||
mod pr_4015;
|
||||
mod pr_4091;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Axum integrations for the Leptos web framework."
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos"
|
||||
version = "0.8.6"
|
||||
version = "0.8.8"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
|
||||
@@ -5,7 +5,7 @@ license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Configuration for the Leptos web framework."
|
||||
readme = "../README.md"
|
||||
version = "0.8.5"
|
||||
version = "0.8.7"
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_dom"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
|
||||
@@ -258,15 +258,7 @@ pub fn request_idle_callback_with_handle(
|
||||
///
|
||||
/// <div class="warning">The task is called outside of the ownership tree, this means that if you want to access for example the context you need to reestablish the owner.</div>
|
||||
pub fn queue_microtask(task: impl FnOnce() + 'static) {
|
||||
use js_sys::{Function, Reflect};
|
||||
|
||||
let task = Closure::once_into_js(task);
|
||||
let window = web_sys::window().expect("window not available");
|
||||
let queue_microtask =
|
||||
Reflect::get(&window, &JsValue::from_str("queueMicrotask"))
|
||||
.expect("queueMicrotask not available");
|
||||
let queue_microtask = queue_microtask.unchecked_into::<Function>();
|
||||
_ = queue_microtask.call1(&JsValue::UNDEFINED, &task);
|
||||
tachys::renderer::dom::queue_microtask(task);
|
||||
}
|
||||
|
||||
/// Handle that is generated by [set_timeout_with_handle] and can be used to clear the timeout.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_macro"
|
||||
version = "0.8.6"
|
||||
version = "0.8.7"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
@@ -24,7 +24,9 @@ proc-macro-error2 = { default-features = false, workspace = true }
|
||||
proc-macro2 = { workspace = true, default-features = true }
|
||||
quote = { workspace = true, default-features = true }
|
||||
syn = { features = ["full"], workspace = true, default-features = true }
|
||||
rstml = { workspace = true, default-features = true }
|
||||
rstml = { workspace = true, default-features = true, features = [
|
||||
"rawtext-stable-hack",
|
||||
] }
|
||||
leptos_hot_reload = { workspace = true }
|
||||
server_fn_macro = { workspace = true }
|
||||
convert_case = { workspace = true, default-features = true }
|
||||
|
||||
@@ -323,7 +323,14 @@ fn view_macro_impl(tokens: TokenStream, template: bool) -> TokenStream {
|
||||
.chain(tokens)
|
||||
.collect()
|
||||
};
|
||||
let config = rstml::ParserConfig::default().recover_block(true);
|
||||
let macro_call_pattern = if let Some(class) = &global_class {
|
||||
quote!(view! { class = #class, %% })
|
||||
} else {
|
||||
quote!(view! {%%})
|
||||
};
|
||||
let config = rstml::ParserConfig::default()
|
||||
.recover_block(true)
|
||||
.macro_call_pattern(macro_call_pattern);
|
||||
let parser = rstml::Parser::new(config);
|
||||
let (mut nodes, errors) = parser.parse_recoverable(tokens).split_vec();
|
||||
let errors = errors.into_iter().map(|e| e.emit_as_expr_tokens());
|
||||
|
||||
@@ -44,7 +44,8 @@ denylist = ["tracing"]
|
||||
max_combination_size = 2
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
rustdoc-args = ["--generate-link-to-definition", "--cfg", "docsrs"]
|
||||
all-features = true
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)'] }
|
||||
|
||||
@@ -386,6 +386,7 @@ T: Send + Sync + 'static,
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-wasm-bindgen")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-wasm-bindgen")))]
|
||||
impl<T> ArcOnceResource<T, JsonSerdeWasmCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -418,6 +419,7 @@ fut: impl Future<Output = T> + Send + 'static
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "miniserde")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "miniserde")))]
|
||||
impl<T> ArcOnceResource<T, MiniserdeCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -451,6 +453,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-lite")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-lite")))]
|
||||
impl<T> ArcOnceResource<T, SerdeLite<JsonSerdeCodec>>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -484,6 +487,7 @@ fut: impl Future<Output = T> + Send + 'static
|
||||
}
|
||||
|
||||
#[cfg(feature = "rkyv")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
|
||||
impl<T> ArcOnceResource<T, RkyvCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -748,6 +752,7 @@ T: Send + Sync + 'static,
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-wasm-bindgen")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-wasm-bindgen")))]
|
||||
impl<T> OnceResource<T, JsonSerdeWasmCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -780,6 +785,7 @@ fut: impl Future<Output = T> + Send + 'static
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "miniserde")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "miniserde")))]
|
||||
impl<T> OnceResource<T, MiniserdeCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -813,6 +819,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-lite")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-lite")))]
|
||||
impl<T> OnceResource<T, SerdeLite<JsonSerdeCodec>>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -846,6 +853,7 @@ fut: impl Future<Output = T> + Send + 'static
|
||||
}
|
||||
|
||||
#[cfg(feature = "rkyv")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
|
||||
impl<T> OnceResource<T, RkyvCodec>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
|
||||
@@ -709,6 +709,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "rkyv")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
|
||||
impl<T> ArcResource<T, RkyvCodec>
|
||||
where
|
||||
RkyvCodec: Encoder<T> + Decoder<T>,
|
||||
@@ -1048,6 +1049,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-wasm-bindgen")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-wasm-bindgen")))]
|
||||
impl<T> Resource<T, JsonSerdeWasmCodec>
|
||||
where
|
||||
JsonSerdeWasmCodec: Encoder<T> + Decoder<T>,
|
||||
@@ -1105,6 +1107,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "miniserde")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "miniserde")))]
|
||||
impl<T> Resource<T, MiniserdeCodec>
|
||||
where
|
||||
MiniserdeCodec: Encoder<T> + Decoder<T>,
|
||||
@@ -1164,6 +1167,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-lite")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-lite")))]
|
||||
impl<T> Resource<T, SerdeLite<JsonSerdeCodec>>
|
||||
where
|
||||
SerdeLite<JsonSerdeCodec>: Encoder<T> + Decoder<T>,
|
||||
@@ -1222,6 +1226,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "rkyv")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
|
||||
impl<T> Resource<T, RkyvCodec>
|
||||
where
|
||||
RkyvCodec: Encoder<T> + Decoder<T>,
|
||||
|
||||
@@ -80,6 +80,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-lite")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-lite")))]
|
||||
impl<T> SharedValue<T, SerdeLite<JsonSerdeCodec>>
|
||||
where
|
||||
SerdeLite<JsonSerdeCodec>: Encoder<T> + Decoder<T>,
|
||||
@@ -102,6 +103,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde-wasm-bindgen")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde-wasm-bindgen")))]
|
||||
impl<T> SharedValue<T, JsonSerdeWasmCodec>
|
||||
where
|
||||
JsonSerdeWasmCodec: Encoder<T> + Decoder<T>,
|
||||
@@ -124,6 +126,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "miniserde")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "miniserde")))]
|
||||
impl<T> SharedValue<T, MiniserdeCodec>
|
||||
where
|
||||
MiniserdeCodec: Encoder<T> + Decoder<T>,
|
||||
@@ -146,6 +149,7 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "rkyv")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
|
||||
impl<T> SharedValue<T, RkyvCodec>
|
||||
where
|
||||
RkyvCodec: Encoder<T> + Decoder<T>,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reactive_graph"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reactive_stores_macro"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_router"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
authors = ["Greg Johnston", "Ben Wishovich"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -5,7 +5,7 @@ license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "RPC for any web framework."
|
||||
readme = "../README.md"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "RPC for any web framework."
|
||||
readme = "../README.md"
|
||||
version = "0.8.6"
|
||||
version = "0.8.7"
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tachys"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -329,6 +329,8 @@ where
|
||||
fn build(self) -> Self::State {
|
||||
let el = Rndr::create_element(self.tag.tag(), E::NAMESPACE);
|
||||
|
||||
let attrs = self.attributes.build(&el);
|
||||
|
||||
let children = if E::SELF_CLOSING {
|
||||
None
|
||||
} else {
|
||||
@@ -337,8 +339,6 @@ where
|
||||
Some(children)
|
||||
};
|
||||
|
||||
let attrs = self.attributes.build(&el);
|
||||
|
||||
ElementState {
|
||||
el,
|
||||
attrs,
|
||||
|
||||
@@ -202,7 +202,7 @@ macro_rules! prop_type {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = self.into();
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
@@ -212,14 +212,14 @@ macro_rules! prop_type {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = self.into();
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = self.into();
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ macro_rules! prop_type {
|
||||
let was_some = self.is_some();
|
||||
let value = self.into();
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -258,7 +258,7 @@ macro_rules! prop_type {
|
||||
let was_some = self.is_some();
|
||||
let value = self.into();
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -266,7 +266,7 @@ macro_rules! prop_type {
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = self.into();
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ macro_rules! prop_type_str {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from(&*self);
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
@@ -304,14 +304,14 @@ macro_rules! prop_type_str {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from(&*self);
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = JsValue::from(&*self);
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ macro_rules! prop_type_str {
|
||||
let was_some = self.is_some();
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -352,7 +352,7 @@ macro_rules! prop_type_str {
|
||||
let was_some = self.is_some();
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -360,7 +360,7 @@ macro_rules! prop_type_str {
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ impl IntoProperty for Arc<str> {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
@@ -402,14 +402,14 @@ impl IntoProperty for Arc<str> {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ impl IntoProperty for Option<Arc<str>> {
|
||||
let was_some = self.is_some();
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -448,7 +448,7 @@ impl IntoProperty for Option<Arc<str>> {
|
||||
let was_some = self.is_some();
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
if was_some {
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
}
|
||||
(el.clone(), value)
|
||||
}
|
||||
@@ -456,7 +456,7 @@ impl IntoProperty for Option<Arc<str>> {
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = JsValue::from(self.map(|n| JsValue::from_str(&n)));
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ impl IntoProperty for Oco<'static, str> {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
@@ -271,14 +271,14 @@ impl IntoProperty for Oco<'static, str> {
|
||||
key: &str,
|
||||
) -> Self::State {
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
(el.clone(), value)
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State, key: &str) {
|
||||
let (el, prev) = state;
|
||||
let value = JsValue::from_str(self.as_ref());
|
||||
Rndr::set_property(el, key, &value);
|
||||
Rndr::set_property_or_value(el, key, &value);
|
||||
*prev = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,46 @@ pub type ClassList = web_sys::DomTokenList;
|
||||
pub type CssStyleDeclaration = web_sys::CssStyleDeclaration;
|
||||
pub type TemplateElement = web_sys::HtmlTemplateElement;
|
||||
|
||||
/// A microtask is a short function which will run after the current task has
|
||||
/// completed its work and when there is no other code waiting to be run before
|
||||
/// control of the execution context is returned to the browser's event loop.
|
||||
///
|
||||
/// Microtasks are especially useful for libraries and frameworks that need
|
||||
/// to perform final cleanup or other just-before-rendering tasks.
|
||||
///
|
||||
/// [MDN queueMicrotask](https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask)
|
||||
pub fn queue_microtask(task: impl FnOnce() + 'static) {
|
||||
use js_sys::{Function, Reflect};
|
||||
|
||||
let task = Closure::once_into_js(task);
|
||||
let window = window();
|
||||
let queue_microtask =
|
||||
Reflect::get(&window, &JsValue::from_str("queueMicrotask"))
|
||||
.expect("queueMicrotask not available");
|
||||
let queue_microtask = queue_microtask.unchecked_into::<Function>();
|
||||
_ = queue_microtask.call1(&JsValue::UNDEFINED, &task);
|
||||
}
|
||||
|
||||
fn queue(fun: Box<dyn FnOnce()>) {
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
thread_local! {
|
||||
static PENDING: Cell<bool> = const { Cell::new(false) };
|
||||
static QUEUE: RefCell<Vec<Box<dyn FnOnce()>>> = RefCell::new(Vec::new());
|
||||
}
|
||||
|
||||
QUEUE.with_borrow_mut(|q| q.push(fun));
|
||||
if !PENDING.replace(true) {
|
||||
queue_microtask(|| {
|
||||
let tasks = QUEUE.take();
|
||||
for task in tasks {
|
||||
task();
|
||||
}
|
||||
PENDING.set(false);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Dom {
|
||||
pub fn intern(text: &str) -> &str {
|
||||
intern(text)
|
||||
@@ -211,6 +251,20 @@ impl Dom {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_property_or_value(el: &Element, key: &str, value: &JsValue) {
|
||||
if key == "value" {
|
||||
queue(Box::new({
|
||||
let el = el.clone();
|
||||
let value = value.clone();
|
||||
move || {
|
||||
Self::set_property(&el, "value", &value);
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
Self::set_property(el, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_property(el: &Element, key: &str, value: &JsValue) {
|
||||
or_debug!(
|
||||
js_sys::Reflect::set(
|
||||
|
||||
Reference in New Issue
Block a user