mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-28 18:22:34 -05:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a76b9d71f0 | ||
|
|
e768617dbb |
174
Cargo.lock
generated
174
Cargo.lock
generated
@@ -88,7 +88,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -205,7 +205,7 @@ dependencies = [
|
||||
"actix-router",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -273,7 +273,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "any_spawner"
|
||||
version = "0.2.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"async-executor",
|
||||
"futures",
|
||||
@@ -333,7 +333,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -350,7 +350,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -364,23 +364,23 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "attribute-derive"
|
||||
version = "0.10.3"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0053e96dd3bec5b4879c23a138d6ef26f2cb936c9cdc96274ac2b9ed44b5bb54"
|
||||
checksum = "f1800e974930e9079c965b9ffbcb6667a40401063a26396c7b4f15edc92da690"
|
||||
dependencies = [
|
||||
"attribute-derive-macro",
|
||||
"derive-where",
|
||||
"manyhow",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "attribute-derive-macro"
|
||||
version = "0.10.3"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "463b53ad0fd5b460af4b1915fe045ff4d946d025fb6c4dc3337752eaa980f71b"
|
||||
checksum = "5d908eb786ef94296bff86f90130b3b748b49401dc81fd2bb8b3dccd44cfacbd"
|
||||
dependencies = [
|
||||
"collection_literals",
|
||||
"interpolator",
|
||||
@@ -389,7 +389,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"quote-use",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -400,9 +400,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.7.9"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
|
||||
checksum = "49c41b948da08fb481a94546cd874843adc1142278b0af4badf9b1b78599d68d"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum-core",
|
||||
@@ -571,7 +571,7 @@ checksum = "523363cbe1df49b68215efdf500b103ac3b0fb4836aed6d15689a076eadb8fff"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -867,7 +867,7 @@ checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -880,7 +880,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -901,7 +901,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1109,7 +1109,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1213,7 +1213,7 @@ dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1448,7 +1448,7 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "hydration_context"
|
||||
version = "0.2.0"
|
||||
version = "0.2.0-rc1"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"js-sys",
|
||||
@@ -1648,7 +1648,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1765,7 +1765,7 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "leptos"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"base64",
|
||||
@@ -1810,12 +1810,12 @@ dependencies = [
|
||||
"http 1.1.0",
|
||||
"proc-macro-error",
|
||||
"server_fn_macro 0.6.15",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leptos_actix"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"actix-files",
|
||||
"actix-http",
|
||||
@@ -1840,7 +1840,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_axum"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"axum",
|
||||
@@ -1863,7 +1863,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_config"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"config",
|
||||
"regex",
|
||||
@@ -1877,7 +1877,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_dom"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"leptos",
|
||||
@@ -1894,7 +1894,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_hot_reload"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"camino",
|
||||
@@ -1904,13 +1904,13 @@ dependencies = [
|
||||
"quote",
|
||||
"rstml",
|
||||
"serde",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leptos_integration_utils"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"hydration_context",
|
||||
@@ -1923,7 +1923,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_macro"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"attribute-derive",
|
||||
"cfg-if",
|
||||
@@ -1941,8 +1941,8 @@ dependencies = [
|
||||
"rstml",
|
||||
"serde",
|
||||
"server_fn",
|
||||
"server_fn_macro 0.7.0",
|
||||
"syn 2.0.89",
|
||||
"server_fn_macro 0.7.0-rc1",
|
||||
"syn 2.0.87",
|
||||
"tracing",
|
||||
"trybuild",
|
||||
"typed-builder",
|
||||
@@ -1951,7 +1951,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_meta"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"indexmap",
|
||||
@@ -1966,7 +1966,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_router"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"either_of",
|
||||
@@ -1990,7 +1990,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_router_macro"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"leptos_router",
|
||||
"proc-macro-error2",
|
||||
@@ -2000,7 +2000,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_server"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"base64",
|
||||
@@ -2091,7 +2091,7 @@ dependencies = [
|
||||
"manyhow-macros",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2141,7 +2141,7 @@ checksum = "f3cd9f9bbedc1b92683a9847b8db12f3203cf32af6a11db085fa007708dc9555"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2217,7 +2217,7 @@ checksum = "1bb5c1d8184f13f7d0ccbeeca0def2f9a181bce2624302793005f5ca8aa62e5e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2239,7 +2239,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "next_tuple"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-rc1"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
@@ -2323,7 +2323,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2412,7 +2412,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2468,7 +2468,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2523,7 +2523,7 @@ dependencies = [
|
||||
"proc-macro-error-attr2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2539,9 +2539,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -2554,7 +2554,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
"version_check",
|
||||
"yansi",
|
||||
]
|
||||
@@ -2596,7 +2596,7 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2676,7 +2676,7 @@ dependencies = [
|
||||
"proc-macro-utils",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2726,7 +2726,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reactive_graph"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-rc1"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"async-lock",
|
||||
@@ -2748,7 +2748,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reactive_stores"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-rc1"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"guardian",
|
||||
@@ -2764,13 +2764,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reactive_stores_macro"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-rc1"
|
||||
dependencies = [
|
||||
"convert_case 0.6.0",
|
||||
"proc-macro-error2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2954,7 +2954,7 @@ checksum = "09cb82b74b4810f07e460852c32f522e979787691b0b7b7439fe473e49d49b2f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2989,7 +2989,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2-diagnostics",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
"syn_derive",
|
||||
"thiserror 1.0.68",
|
||||
]
|
||||
@@ -3181,7 +3181,7 @@ checksum = "7ce26a84e3d8d10853301cf6a75c58132b8f5d5e8fee65949ea8dd7758d6760b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3203,14 +3203,14 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.133"
|
||||
version = "1.0.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
|
||||
checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -3262,7 +3262,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "server_fn"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"axum",
|
||||
@@ -3312,28 +3312,28 @@ dependencies = [
|
||||
"convert_case 0.6.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
"xxhash-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "server_fn_macro"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"const_format",
|
||||
"convert_case 0.6.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
"xxhash-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "server_fn_macro_default"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
dependencies = [
|
||||
"server_fn_macro 0.7.0",
|
||||
"syn 2.0.89",
|
||||
"server_fn_macro 0.7.0-rc1",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3400,7 +3400,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33a1b4f13e2bbf2f5b29d09dfebc9de69229ffee245aed80e3b70f9b5fd28c06"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3471,9 +3471,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.89"
|
||||
version = "2.0.87"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
|
||||
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3489,7 +3489,7 @@ dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3515,7 +3515,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3533,7 +3533,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tachys"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-rc1"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"const_str_slice_concat",
|
||||
@@ -3642,7 +3642,7 @@ checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3653,12 +3653,12 @@ checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "throw_error"
|
||||
version = "0.2.0"
|
||||
version = "0.2.0-rc1"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
@@ -3745,7 +3745,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3858,9 +3858,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.6.2"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697"
|
||||
checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bytes",
|
||||
@@ -3913,7 +3913,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3963,7 +3963,7 @@ checksum = "560b82d656506509d43abe30e0ba64c56b1953ab3d4fe7ba5902747a7a3cedd5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4111,7 +4111,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@@ -4145,7 +4145,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@@ -4371,7 +4371,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -4393,7 +4393,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4413,7 +4413,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
@@ -4442,7 +4442,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.89",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
44
Cargo.toml
44
Cargo.toml
@@ -40,36 +40,36 @@ members = [
|
||||
exclude = ["benchmarks", "examples", "projects"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
edition = "2021"
|
||||
rust-version = "1.76"
|
||||
|
||||
[workspace.dependencies]
|
||||
throw_error = { path = "./any_error/", version = "0.2.0" }
|
||||
any_spawner = { path = "./any_spawner/", version = "0.2.0" }
|
||||
throw_error = { path = "./any_error/", version = "0.2.0-rc1" }
|
||||
any_spawner = { path = "./any_spawner/", version = "0.1.0" }
|
||||
const_str_slice_concat = { path = "./const_str_slice_concat", version = "0.1.0" }
|
||||
either_of = { path = "./either_of/", version = "0.1.0" }
|
||||
hydration_context = { path = "./hydration_context", version = "0.2.0" }
|
||||
leptos = { path = "./leptos", version = "0.7.0" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.7.0" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.7.0" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.7.0" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.7.0" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.7.0" }
|
||||
leptos_router = { path = "./router", version = "0.7.0" }
|
||||
leptos_router_macro = { path = "./router_macro", version = "0.7.0" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.7.0" }
|
||||
leptos_meta = { path = "./meta", version = "0.7.0" }
|
||||
next_tuple = { path = "./next_tuple", version = "0.1.0" }
|
||||
hydration_context = { path = "./hydration_context", version = "0.2.0-rc1" }
|
||||
leptos = { path = "./leptos", version = "0.7.0-rc1" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.7.0-rc1" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.7.0-rc1" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.7.0-rc1" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.7.0-rc1" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.7.0-rc1" }
|
||||
leptos_router = { path = "./router", version = "0.7.0-rc1" }
|
||||
leptos_router_macro = { path = "./router_macro", version = "0.7.0-rc1" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.7.0-rc1" }
|
||||
leptos_meta = { path = "./meta", version = "0.7.0-rc1" }
|
||||
next_tuple = { path = "./next_tuple", version = "0.1.0-rc1" }
|
||||
oco_ref = { path = "./oco", version = "0.2.0" }
|
||||
or_poisoned = { path = "./or_poisoned", version = "0.1.0" }
|
||||
reactive_graph = { path = "./reactive_graph", version = "0.1.0" }
|
||||
reactive_stores = { path = "./reactive_stores", version = "0.1.0" }
|
||||
reactive_stores_macro = { path = "./reactive_stores_macro", version = "0.1.0" }
|
||||
server_fn = { path = "./server_fn", version = "0.7.0" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.7.0" }
|
||||
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.7.0" }
|
||||
tachys = { path = "./tachys", version = "0.1.0" }
|
||||
reactive_graph = { path = "./reactive_graph", version = "0.1.0-rc1" }
|
||||
reactive_stores = { path = "./reactive_stores", version = "0.1.0-rc1" }
|
||||
reactive_stores_macro = { path = "./reactive_stores_macro", version = "0.1.0-rc1" }
|
||||
server_fn = { path = "./server_fn", version = "0.7.0-rc1" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.7.0-rc1" }
|
||||
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.7.0-rc1" }
|
||||
tachys = { path = "./tachys", version = "0.1.0-rc1" }
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
You can find a list of useful libraries and example projects at [`awesome-leptos`](https://github.com/leptos-rs/awesome-leptos).
|
||||
|
||||
# The `main` branch is currently undergoing major changes in preparation for the [0.7](https://github.com/leptos-rs/leptos/milestone/4) release. For a stable version, please use the [v0.6.13 tag](https://github.com/leptos-rs/leptos/tree/v0.6.13)
|
||||
|
||||
# Leptos
|
||||
|
||||
```rust
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "throw_error"
|
||||
version = "0.2.0"
|
||||
version = "0.2.0-rc1"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "any_spawner"
|
||||
version = "0.2.0"
|
||||
version = "0.1.1"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -6,7 +6,9 @@ use leptos_axum::ResponseOptions;
|
||||
// A basic function to display errors served by the error boundaries.
|
||||
// Feel free to do more complicated things here than just displaying them.
|
||||
#[component]
|
||||
pub fn ErrorTemplate(#[prop(into)] errors: Signal<Errors>) -> impl IntoView {
|
||||
pub fn ErrorTemplate(
|
||||
#[prop(into)] errors: MaybeSignal<Errors>,
|
||||
) -> impl IntoView {
|
||||
// Get Errors from Signal
|
||||
// Downcast lets us take a type that implements `std::error::Error`
|
||||
let errors = Memo::new(move |_| {
|
||||
|
||||
@@ -10,7 +10,7 @@ struct Then {
|
||||
// the type with Option<...> and marking the option as #[prop(optional)].
|
||||
#[slot]
|
||||
struct ElseIf {
|
||||
cond: Signal<bool>,
|
||||
cond: MaybeSignal<bool>,
|
||||
children: ChildrenFn,
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ struct Fallback {
|
||||
// Slots are added to components like any other prop.
|
||||
#[component]
|
||||
fn SlotIf(
|
||||
cond: Signal<bool>,
|
||||
cond: MaybeSignal<bool>,
|
||||
then: Then,
|
||||
#[prop(default=vec![])] else_if: Vec<ElseIf>,
|
||||
#[prop(optional)] fallback: Option<Fallback>,
|
||||
@@ -43,9 +43,9 @@ fn SlotIf(
|
||||
#[component]
|
||||
pub fn App() -> impl IntoView {
|
||||
let (count, set_count) = signal(0);
|
||||
let is_even = Signal::derive(move || count.get() % 2 == 0);
|
||||
let is_div5 = Signal::derive(move || count.get() % 5 == 0);
|
||||
let is_div7 = Signal::derive(move || count.get() % 7 == 0);
|
||||
let is_even = MaybeSignal::derive(move || count.get() % 2 == 0);
|
||||
let is_div5 = MaybeSignal::derive(move || count.get() % 5 == 0);
|
||||
let is_div7 = MaybeSignal::derive(move || count.get() % 7 == 0);
|
||||
|
||||
view! {
|
||||
<button on:click=move |_| set_count.update(|value| *value += 1)>"+1"</button>
|
||||
|
||||
@@ -38,7 +38,7 @@ pub fn TimerDemo() -> impl IntoView {
|
||||
pub fn use_interval<T, F>(interval_millis: T, f: F)
|
||||
where
|
||||
F: Fn() + Clone + 'static,
|
||||
T: Into<Signal<u64>> + 'static,
|
||||
T: Into<MaybeSignal<u64>> + 'static,
|
||||
{
|
||||
let interval_millis = interval_millis.into();
|
||||
Effect::new(move |prev_handle: Option<IntervalHandle>| {
|
||||
|
||||
@@ -4,6 +4,25 @@ use leptos::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use server_fn::ServerFnError;
|
||||
|
||||
pub fn shell(leptos_options: &LeptosOptions) -> impl IntoView {
|
||||
view! {
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<AutoReload options=leptos_options.clone() />
|
||||
<HydrationScripts options=leptos_options.clone()/>
|
||||
<link rel="stylesheet" id="leptos" href="/pkg/todo_app_sqlite_csr.css"/>
|
||||
<link rel="shortcut icon" type="image/ico" href="/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<TodoApp/>
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))]
|
||||
pub struct Todo {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "hydration_context"
|
||||
version = "0.2.0"
|
||||
version = "0.2.0-rc1"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
// #[wasm_bindgen(thread_local)] is deprecated in wasm-bindgen 0.2.96
|
||||
// but the replacement is also only shipped in that version
|
||||
// as a result, we'll just allow deprecated for now
|
||||
#![allow(deprecated)]
|
||||
|
||||
use super::{SerializedDataId, SharedContext};
|
||||
use crate::{PinnedFuture, PinnedStream};
|
||||
use core::fmt::Debug;
|
||||
|
||||
@@ -83,14 +83,15 @@ pub trait SharedContext: Debug {
|
||||
|
||||
/// Reads the current value of some data from the shared context, if it has been
|
||||
/// sent from the server. This returns the serialized data as a `String` that should
|
||||
/// be deserialized.
|
||||
/// be deserialized using [`Serializable::de`].
|
||||
///
|
||||
/// On the server and in client-side rendered implementations, this should
|
||||
/// always return [`None`].
|
||||
fn read_data(&self, id: &SerializedDataId) -> Option<String>;
|
||||
|
||||
/// Returns a [`Future`] that resolves with a `String` that should
|
||||
/// be deserialized once the given piece of server data has resolved.
|
||||
/// be deserialized using [`Serializable::de`] once the given piece of server
|
||||
/// data has resolved.
|
||||
///
|
||||
/// On the server and in client-side rendered implementations, this should
|
||||
/// return a [`Future`] that is immediately ready with [`None`].
|
||||
@@ -147,8 +148,8 @@ pub trait SharedContext: Debug {
|
||||
|
||||
/// Adds a `Future` to the set of “blocking resources” that should prevent the server’s
|
||||
/// response stream from beginning until all are resolved. The `Future` returned by
|
||||
/// blocking resources will not resolve until every `Future` added by this method
|
||||
/// has resolved.
|
||||
/// [`blocking_resources`](Self::blocking_resources) will not resolve until every `Future`
|
||||
/// added by this method has resolved.
|
||||
///
|
||||
/// In browser implementations, this should be a no-op.
|
||||
fn defer_stream(&self, wait_for: PinnedFuture<()>);
|
||||
|
||||
@@ -82,7 +82,7 @@ impl ResponseParts {
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper for an Actix [`HttpRequest`] that allows it to be used in an
|
||||
/// A wrapper for an Actix [`HttpRequest`](actix_web::HttpRequest) that allows it to be used in an
|
||||
/// `Send`/`Sync` setting like Leptos's Context API.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Request(SendWrapper<HttpRequest>);
|
||||
@@ -419,6 +419,12 @@ pub fn handle_server_fns_with_context(
|
||||
/// will include fallback content for any `<Suspense/>` nodes, and be immediately interactive,
|
||||
/// but requires some client-side JavaScript.
|
||||
///
|
||||
/// The provides a [MetaContext] and a [RouterIntegrationContext] to app’s context before
|
||||
/// rendering it, and includes any meta tags injected using [leptos_meta].
|
||||
///
|
||||
/// The HTML stream is rendered using [render_to_stream](leptos::ssr::render_to_stream), and
|
||||
/// includes everything described in the documentation for that function.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// use actix_web::{App, HttpServer};
|
||||
@@ -459,6 +465,7 @@ pub fn handle_server_fns_with_context(
|
||||
/// - [ResponseOptions]
|
||||
/// - [Request]
|
||||
/// - [MetaContext](leptos_meta::MetaContext)
|
||||
/// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext)
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(level = "trace", fields(error), skip_all)
|
||||
@@ -478,6 +485,13 @@ where
|
||||
/// This stream will pause at each `<Suspense/>` node and wait for it to resolve before
|
||||
/// sending down its HTML. The app will become interactive once it has fully loaded.
|
||||
///
|
||||
/// The provides a [MetaContext] and a [RouterIntegrationContext] to app’s context before
|
||||
/// rendering it, and includes any meta tags injected using [leptos_meta].
|
||||
///
|
||||
/// The HTML stream is rendered using
|
||||
/// [render_to_stream_in_order](leptos::ssr::render_to_stream_in_order),
|
||||
/// and includes everything described in the documentation for that function.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// use actix_web::{App, HttpServer};
|
||||
@@ -520,6 +534,7 @@ where
|
||||
/// This function always provides context values including the following types:
|
||||
/// - [ResponseOptions]
|
||||
/// - [Request]
|
||||
/// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext)
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(level = "trace", fields(error), skip_all)
|
||||
@@ -536,7 +551,13 @@ where
|
||||
|
||||
/// Returns an Actix [struct@Route](actix_web::Route) that listens for a `GET` request and tries
|
||||
/// to route it using [leptos_router], asynchronously rendering an HTML page after all
|
||||
/// `async` resources have loaded.
|
||||
/// `async` [Resource](leptos::Resource)s have loaded.
|
||||
///
|
||||
/// The provides a [MetaContext] and a [RouterIntegrationContext] to the app’s context before
|
||||
/// rendering it, and includes any meta tags injected using [leptos_meta].
|
||||
///
|
||||
/// The HTML stream is rendered using [render_to_string_async](leptos::ssr::render_to_string_async), and
|
||||
/// includes everything described in the documentation for that function.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
@@ -669,6 +690,7 @@ where
|
||||
/// - [ResponseOptions]
|
||||
/// - [Request]
|
||||
/// - [MetaContext](leptos_meta::MetaContext)
|
||||
/// - [RouterIntegrationContext](leptos_router::RouterIntegrationContext)
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(level = "trace", fields(error), skip_all)
|
||||
@@ -691,7 +713,7 @@ where
|
||||
|
||||
/// Returns an Actix [struct@Route](actix_web::Route) that listens for a `GET` request and tries
|
||||
/// to route it using [leptos_router], asynchronously serving the page once all `async`
|
||||
/// resources have loaded.
|
||||
/// [Resource](leptos::Resource)s have loaded.
|
||||
///
|
||||
/// This function allows you to provide additional information to Leptos for your route.
|
||||
/// It could be used to pass in Path Info, Connection Info, or anything your heart desires.
|
||||
|
||||
@@ -11,7 +11,7 @@ edition.workspace = true
|
||||
[dependencies]
|
||||
any_spawner = { workspace = true, features = ["tokio"] }
|
||||
hydration_context = { workspace = true }
|
||||
axum = { version = "0.7.9", default-features = false, features = [
|
||||
axum = { version = "0.7.8", default-features = false, features = [
|
||||
"matched-path",
|
||||
] }
|
||||
dashmap = "6"
|
||||
@@ -26,11 +26,11 @@ once_cell = "1"
|
||||
parking_lot = "0.12.3"
|
||||
tokio = { version = "1.41", default-features = false }
|
||||
tower = { version = "0.5.1", features = ["util"] }
|
||||
tower-http = "0.6.2"
|
||||
tower-http = "0.6.1"
|
||||
tracing = { version = "0.1.40", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
axum = "0.7.9"
|
||||
axum = "0.7.8"
|
||||
tokio = { version = "1.41", features = ["net", "rt-multi-thread"] }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -197,9 +197,9 @@ impl ExtendResponse for AxumResponse {
|
||||
/// 2. A server function that is called from WASM running in the client (e.g., a dispatched action
|
||||
/// or a spawned `Future`).
|
||||
/// 3. A `<form>` submitted to the server function endpoint using default browser APIs (often due
|
||||
/// to using [`ActionForm`] without JS/WASM present.)
|
||||
/// to using [`ActionForm`](leptos::form::ActionForm) without JS/WASM present.)
|
||||
///
|
||||
/// Using it with a non-blocking [`Resource`] will not work if you are using streaming rendering,
|
||||
/// Using it with a non-blocking [`Resource`](leptos::server::Resource) will not work if you are using streaming rendering,
|
||||
/// as the response's headers will already have been sent by the time the server function calls `redirect()`.
|
||||
///
|
||||
/// ### Implementation
|
||||
@@ -442,6 +442,12 @@ pub type PinnedHtmlStream =
|
||||
/// Returns an Axum [Handler](axum::handler::Handler) that listens for a `GET` request and tries
|
||||
/// to route it using [leptos_router], serving an HTML stream of your application.
|
||||
///
|
||||
/// The provides a [MetaContext] and a [RouterIntegrationContext] to app’s context before
|
||||
/// rendering it, and includes any meta tags injected using [leptos_meta].
|
||||
///
|
||||
/// The HTML stream is rendered using [render_to_stream](leptos::ssr::render_to_stream), and
|
||||
/// includes everything described in the documentation for that function.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// use axum::{handler::Handler, Router};
|
||||
@@ -479,7 +485,8 @@ pub type PinnedHtmlStream =
|
||||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`ServerMetaContext`]
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(level = "trace", fields(error), skip_all)
|
||||
@@ -530,6 +537,12 @@ where
|
||||
/// This stream will pause at each `<Suspense/>` node and wait for it to resolve before
|
||||
/// sending down its HTML. The app will become interactive once it has fully loaded.
|
||||
///
|
||||
/// The provides a [MetaContext] and a [RouterIntegrationContext] to app’s context before
|
||||
/// rendering it, and includes any meta tags injected using [leptos_meta].
|
||||
///
|
||||
/// The HTML stream is rendered using [render_to_stream_in_order], and includes everything described in
|
||||
/// the documentation for that function.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// use axum::{handler::Handler, Router};
|
||||
@@ -567,7 +580,8 @@ where
|
||||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`ServerMetaContext`]
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(level = "trace", fields(error), skip_all)
|
||||
@@ -620,7 +634,8 @@ where
|
||||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`ServerMetaContext`]
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(level = "trace", fields(error), skip_all)
|
||||
@@ -751,7 +766,8 @@ where
|
||||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`ServerMetaContext`]
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(level = "trace", fields(error), skip_all)
|
||||
@@ -818,7 +834,8 @@ where
|
||||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`ServerMetaContext`]
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(level = "trace", fields(error), skip_all)
|
||||
@@ -935,7 +952,13 @@ fn provide_contexts(
|
||||
|
||||
/// Returns an Axum [Handler](axum::handler::Handler) that listens for a `GET` request and tries
|
||||
/// to route it using [leptos_router], asynchronously rendering an HTML page after all
|
||||
/// `async` resources have loaded.
|
||||
/// `async` [Resource](leptos::Resource)s have loaded.
|
||||
///
|
||||
/// The provides a [MetaContext] and a [RouterIntegrationContext] to app’s context before
|
||||
/// rendering it, and includes any meta tags injected using [leptos_meta].
|
||||
///
|
||||
/// The HTML stream is rendered using [render_to_string_async], and includes everything described in
|
||||
/// the documentation for that function.
|
||||
///
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
@@ -975,7 +998,8 @@ fn provide_contexts(
|
||||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`ServerMetaContext`]
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(level = "trace", fields(error), skip_all)
|
||||
@@ -996,7 +1020,7 @@ where
|
||||
|
||||
/// Returns an Axum [Handler](axum::handler::Handler) that listens for a `GET` request and tries
|
||||
/// to route it using [leptos_router], asynchronously rendering an HTML page after all
|
||||
/// `async` resources have loaded.
|
||||
/// `async` [Resource](leptos::Resource)s have loaded.
|
||||
///
|
||||
/// This version allows us to pass Axum State/Extension/Extractor or other infro from Axum or network
|
||||
/// layers above Leptos itself. To use it, you'll need to write your own handler function that provides
|
||||
@@ -1029,7 +1053,8 @@ where
|
||||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`ServerMetaContext`]
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(level = "trace", fields(error), skip_all)
|
||||
@@ -1063,7 +1088,7 @@ where
|
||||
|
||||
/// Returns an Axum [Handler](axum::handler::Handler) that listens for a `GET` request and tries
|
||||
/// to route it using [leptos_router], asynchronously rendering an HTML page after all
|
||||
/// `async` resources have loaded.
|
||||
/// `async` [Resource](leptos::Resource)s have loaded.
|
||||
///
|
||||
/// This version allows us to pass Axum State/Extension/Extractor or other infro from Axum or network
|
||||
/// layers above Leptos itself. To use it, you'll need to write your own handler function that provides
|
||||
@@ -1096,7 +1121,8 @@ where
|
||||
/// This function always provides context values including the following types:
|
||||
/// - [`Parts`]
|
||||
/// - [`ResponseOptions`]
|
||||
/// - [`ServerMetaContext`]
|
||||
/// - [`ServerMetaContext`](leptos_meta::ServerMetaContext)
|
||||
/// - [`RouterIntegrationContext`](leptos_router::RouterIntegrationContext)
|
||||
#[cfg_attr(
|
||||
feature = "tracing",
|
||||
tracing::instrument(level = "trace", fields(error), skip_all)
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
//! *Notes*:
|
||||
//! - The `render_number` prop can receive any type that implements `Fn(i32) -> String`.
|
||||
//! - Callbacks are most useful when you want optional generic props.
|
||||
//! - All callbacks implement the [`Callable`](leptos::callback::Callable) trait, and can be invoked with `my_callback.run(input)`.
|
||||
//! - All callbacks implement the [`Callable`] trait, and can be invoked with `my_callback.run(input)`.
|
||||
//! - The callback types implement [`Copy`], so they can easily be moved into and out of other closures, just like signals.
|
||||
//!
|
||||
//! # Types
|
||||
//! This modules implements 2 callback types:
|
||||
//! - [`Callback`](leptos::callback::Callback)
|
||||
//! - [`UnsyncCallback`](leptos::callback::UnsyncCallback)
|
||||
//! - [`Callback`]
|
||||
//! - [`UnsyncCallback`]
|
||||
//!
|
||||
//! Use `SyncCallback` if the function is not `Sync` and `Send`.
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// A typed equivalent to [`ChildrenFnMut`], which takes a generic but preserves type information to
|
||||
/// A typed equivalent to [`ChildrenMut`], which takes a generic but preserves type information to
|
||||
/// allow the compiler to optimize the view more effectively.
|
||||
pub struct TypedChildrenMut<T>(Box<dyn FnMut() -> View<T> + Send>);
|
||||
|
||||
|
||||
@@ -72,7 +72,9 @@ use web_sys::{
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
|
||||
#[component]
|
||||
pub fn ActionForm<ServFn>(
|
||||
/// The action from which to build the form.
|
||||
/// The action from which to build the form. This should include a URL, which can be generated
|
||||
/// by default using [`create_server_action`](leptos_server::create_server_action) or added
|
||||
/// manually using [`using_server_fn`](leptos_server::Action::using_server_fn).
|
||||
action: ServerAction<ServFn>,
|
||||
/// A [`NodeRef`] in which the `<form>` element should be stored.
|
||||
#[prop(optional)]
|
||||
@@ -147,7 +149,9 @@ where
|
||||
/// progressively enhanced to use client-side routing.
|
||||
#[component]
|
||||
pub fn MultiActionForm<ServFn>(
|
||||
/// The action from which to build the form.
|
||||
/// The action from which to build the form. This should include a URL, which can be generated
|
||||
/// by default using [create_server_action](leptos_server::create_server_action) or added
|
||||
/// manually using [leptos_server::Action::using_server_fn].
|
||||
action: ServerMultiAction<ServFn>,
|
||||
/// A [`NodeRef`] in which the `<form>` element should be stored.
|
||||
#[prop(optional)]
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
//! server actions, forms, and server-sent events (SSE).
|
||||
//! - **[`todomvc`]** shows the basics of building an isomorphic web app. Both the server and the client import the same app code.
|
||||
//! The server renders the app directly to an HTML string, and the client hydrates that HTML to make it interactive.
|
||||
//! You might also want to see how we use [`Effect::new`](leptos::prelude::Effect) to
|
||||
//! You might also want to see how we use [`Effect::new`](leptos::prelude::Effect::new) to
|
||||
//! [serialize JSON to `localStorage`](https://github.com/leptos-rs/leptos/blob/20af4928b2fffe017408d3f4e7330db22cf68277/examples/todomvc/src/lib.rs#L191-L209)
|
||||
//! and [reactively call DOM methods](https://github.com/leptos-rs/leptos/blob/16f084a71268ac325fbc4a5e50c260df185eadb6/examples/todomvc/src/lib.rs#L292-L296)
|
||||
//! on [references to elements](https://github.com/leptos-rs/leptos/blob/20af4928b2fffe017408d3f4e7330db22cf68277/examples/todomvc/src/lib.rs#L228).
|
||||
@@ -78,7 +78,7 @@
|
||||
//! + `async` interop: [`Resource`](leptos::prelude::Resource) for loading data using `async` functions
|
||||
//! and [`Action`](leptos::prelude::Action) to mutate data or imperatively call `async` functions.
|
||||
//! + reactions: [`Effect`](leptos::prelude::Effect) and [`RenderEffect`](leptos::prelude::RenderEffect).
|
||||
//! - **Templating/Views**: the [`view`] macro and [`IntoView`] trait.
|
||||
//! - **Templating/Views**: the [`view`] macro and [`IntoView`](leptos::IntoView) trait.
|
||||
//! - **Routing**: the [`leptos_router`](https://docs.rs/leptos_router/latest/leptos_router/) crate
|
||||
//! - **Server Functions**: the [`server`](macro@leptos::prelude::server) macro and [`ServerAction`](leptos::prelude::ServerAction).
|
||||
//!
|
||||
@@ -290,7 +290,7 @@ pub mod logging {
|
||||
|
||||
/// Utilities for working with asynchronous tasks.
|
||||
pub mod task {
|
||||
pub use any_spawner::{self, CustomExecutor, Executor};
|
||||
pub use any_spawner::Executor;
|
||||
use std::future::Future;
|
||||
|
||||
/// Spawns a thread-safe [`Future`].
|
||||
|
||||
22
leptos/tests/generic_component.rs
Normal file
22
leptos/tests/generic_component.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
#[test]
|
||||
fn generic_component_signal_inference() {
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn SimpleCounter(#[prop(into)] step: Signal<i32>) -> impl IntoView {
|
||||
_ = step;
|
||||
view! {
|
||||
<div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
let a = RwSignal::new(1);
|
||||
let (b, _) = signal(1);
|
||||
|
||||
view! {
|
||||
<SimpleCounter step=a/>
|
||||
<SimpleCounter step=b/>
|
||||
<SimpleCounter step=Signal::stored(1)/>
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_macro"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
@@ -13,7 +13,7 @@ edition.workspace = true
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
attribute-derive = { version = "0.10.3", features = ["syn-full"] }
|
||||
attribute-derive = { version = "0.10.2", features = ["syn-full"] }
|
||||
cfg-if = "1.0"
|
||||
html-escape = "0.2.13"
|
||||
itertools = "0.13.0"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Macros for use with the Leptos framework.
|
||||
//! Macros for use with the [`leptos`] framework.
|
||||
|
||||
#![cfg_attr(feature = "nightly", feature(proc_macro_span))]
|
||||
#![forbid(unsafe_code)]
|
||||
@@ -272,8 +272,8 @@ pub fn view(tokens: TokenStream) -> TokenStream {
|
||||
view_macro_impl(tokens, false)
|
||||
}
|
||||
|
||||
/// The `template` macro behaves like [`view`](view!), except that it wraps the entire tree in a
|
||||
/// [`ViewTemplate`](https://docs.rs/leptos/0.7.0-gamma3/leptos/prelude/struct.ViewTemplate.html). This optimizes creation speed by rendering
|
||||
/// The `template` macro behaves like [`view`], except that it wraps the entire tree in a
|
||||
/// [`ViewTemplate`](leptos::prelude::ViewTemplate). This optimizes creation speed by rendering
|
||||
/// most of the view into a `<template>` tag with HTML rendered at compile time, then hydrating it.
|
||||
/// In exchange, there is a small binary size overhead.
|
||||
#[proc_macro_error2::proc_macro_error]
|
||||
@@ -366,7 +366,7 @@ fn normalized_call_site(site: proc_macro::Span) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
/// This behaves like the [`view`](view!) macro, but loads the view from an external file instead of
|
||||
/// This behaves like the [`view`] macro, but loads the view from an external file instead of
|
||||
/// parsing it inline.
|
||||
///
|
||||
/// This is designed to allow editing views in a separate file, if this improves a user's workflow.
|
||||
@@ -639,7 +639,7 @@ pub fn island(args: proc_macro::TokenStream, s: TokenStream) -> TokenStream {
|
||||
abort!(
|
||||
transparent,
|
||||
"only `transparent` is supported";
|
||||
help = "try `#[island(transparent)]` or `#[island]`"
|
||||
help = "try `#[component(transparent)]` or `#[component]`"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -652,18 +652,6 @@ pub(crate) fn element_to_tokens(
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let NodeAttribute::Attribute(a) = a {
|
||||
if let Some(Tuple(_)) = a.value() {
|
||||
return Ordering::Greater;
|
||||
}
|
||||
}
|
||||
if let NodeAttribute::Attribute(b) = b {
|
||||
if let Some(Tuple(_)) = b.value() {
|
||||
return Ordering::Less;
|
||||
}
|
||||
}
|
||||
|
||||
match (key_a.as_deref(), key_b.as_deref()) {
|
||||
(Some("class"), Some("class")) | (Some("style"), Some("style")) => {
|
||||
Ordering::Equal
|
||||
@@ -767,7 +755,7 @@ pub(crate) fn element_to_tokens(
|
||||
let name = node.name().to_string();
|
||||
// link custom ident to name span for IDE docs
|
||||
let custom = Ident::new("custom", name.span());
|
||||
quote_spanned! { node.name().span() => ::leptos::tachys::html::element::#custom(#name) }
|
||||
quote! { ::leptos::tachys::html::element::#custom(#name) }
|
||||
} else if is_svg_element(&tag) {
|
||||
parent_type = TagType::Svg;
|
||||
let name = if tag == "use" || tag == "use_" {
|
||||
@@ -775,33 +763,33 @@ pub(crate) fn element_to_tokens(
|
||||
} else {
|
||||
name.to_token_stream()
|
||||
};
|
||||
quote_spanned! { node.name().span() => ::leptos::tachys::svg::#name() }
|
||||
quote! { ::leptos::tachys::svg::#name() }
|
||||
} else if is_math_ml_element(&tag) {
|
||||
parent_type = TagType::Math;
|
||||
quote_spanned! { node.name().span() => ::leptos::tachys::mathml::#name() }
|
||||
quote! { ::leptos::tachys::mathml::#name() }
|
||||
} else if is_ambiguous_element(&tag) {
|
||||
match parent_type {
|
||||
TagType::Unknown => {
|
||||
// We decided this warning was too aggressive, but I'll leave it here in case we want it later
|
||||
/* proc_macro_error2::emit_warning!(name.span(), "The view macro is assuming this is an HTML element, \
|
||||
but it is ambiguous; if it is an SVG or MathML element, prefix with svg:: or math::"); */
|
||||
quote_spanned! { node.name().span() =>
|
||||
quote! {
|
||||
::leptos::tachys::html::element::#name()
|
||||
}
|
||||
}
|
||||
TagType::Html => {
|
||||
quote_spanned! { node.name().span() => ::leptos::tachys::html::element::#name() }
|
||||
quote! { ::leptos::tachys::html::element::#name() }
|
||||
}
|
||||
TagType::Svg => {
|
||||
quote_spanned! { node.name().span() => ::leptos::tachys::svg::#name() }
|
||||
quote! { ::leptos::tachys::svg::#name() }
|
||||
}
|
||||
TagType::Math => {
|
||||
quote_spanned! { node.name().span() => ::leptos::tachys::math::#name() }
|
||||
quote! { ::leptos::tachys::math::#name() }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
parent_type = TagType::Html;
|
||||
quote_spanned! { name.span() => ::leptos::tachys::html::element::#name() }
|
||||
quote! { ::leptos::tachys::html::element::#name() }
|
||||
};
|
||||
|
||||
/* TODO restore this
|
||||
@@ -1722,7 +1710,7 @@ fn tuple_name(name: &str, node: &KeyedAttribute) -> TupleName {
|
||||
TupleName::None
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[derive(Debug)]
|
||||
enum TupleName {
|
||||
None,
|
||||
Str(String),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Utilities for communicating between the server and the client with Leptos.
|
||||
//! Utilities for communicating between the server and the client with [`leptos`].
|
||||
|
||||
#![deny(missing_docs)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
@@ -253,8 +253,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`Future`] that is ready when an
|
||||
/// [`ArcAsyncDerived`](reactive_graph::computed::ArcAsyncDerived) is finished loading or reloading,
|
||||
/// A [`Future`] that is ready when an [`ArcAsyncDerived`] is finished loading or reloading,
|
||||
/// and contains its value. `.await`ing this clones the value `T`.
|
||||
pub struct OnceResourceFuture<T> {
|
||||
source: AnySource,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_meta"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
//! using the [`Leptos`](https://github.com/leptos-rs/leptos) web framework.
|
||||
//!
|
||||
//! Document metadata is updated automatically when running in the browser. For server-side
|
||||
//! rendering, after the component tree is rendered to HTML, [`ServerMetaContextOutput::inject_meta_context`] will inject meta tags into a stream of HTML inside the `<head>`.
|
||||
//! rendering, after the component tree is rendered to HTML, [`MetaContext::dehydrate`] can generate
|
||||
//! HTML that should be injected into the `<head>` of the HTML document being rendered.
|
||||
//!
|
||||
//! ```
|
||||
//! use leptos::prelude::*;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "next_tuple"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-rc1"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reactive_graph"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-rc1"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -19,7 +19,7 @@ pub(crate) use inner::MemoInner;
|
||||
pub use memo::*;
|
||||
pub use selector::*;
|
||||
|
||||
/// Derives a reactive slice of an [`RwSignal`].
|
||||
/// Derives a reactive slice of an [`RwSignal`](crate::signal::RwSignal).
|
||||
///
|
||||
/// Slices have the same guarantees as [`Memo`s](crate::computed::Memo):
|
||||
/// they only emit their value when it has actually been changed.
|
||||
|
||||
@@ -117,7 +117,6 @@ pub struct ArcAsyncDerived<T> {
|
||||
pub(crate) loading: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) trait BlockingLock<T> {
|
||||
fn blocking_read_arc(self: &Arc<Self>)
|
||||
-> async_lock::RwLockReadGuardArc<T>;
|
||||
@@ -584,17 +583,19 @@ impl<T: 'static> ReadUntracked for ArcAsyncDerived<T> {
|
||||
|
||||
fn try_read_untracked(&self) -> Option<Self::Value> {
|
||||
if let Some(suspense_context) = use_context::<SuspenseContext>() {
|
||||
let handle = suspense_context.task_id();
|
||||
let ready = SpecialNonReactiveFuture::new(self.ready());
|
||||
crate::spawn(async move {
|
||||
ready.await;
|
||||
drop(handle);
|
||||
});
|
||||
self.inner
|
||||
.write()
|
||||
.or_poisoned()
|
||||
.suspenses
|
||||
.push(suspense_context);
|
||||
if self.value.blocking_read().is_none() {
|
||||
let handle = suspense_context.task_id();
|
||||
let ready = SpecialNonReactiveFuture::new(self.ready());
|
||||
crate::spawn(async move {
|
||||
ready.await;
|
||||
drop(handle);
|
||||
});
|
||||
self.inner
|
||||
.write()
|
||||
.or_poisoned()
|
||||
.suspenses
|
||||
.push(suspense_context);
|
||||
}
|
||||
}
|
||||
AsyncPlain::try_new(&self.value).map(ReadGuard::new)
|
||||
}
|
||||
|
||||
@@ -84,7 +84,6 @@ pub mod owner;
|
||||
#[cfg(feature = "serde")]
|
||||
mod serde;
|
||||
pub mod signal;
|
||||
mod trait_options;
|
||||
pub mod traits;
|
||||
pub mod transition;
|
||||
pub mod wrappers;
|
||||
@@ -124,7 +123,7 @@ pub fn log_warning(text: Arguments) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls [`Executor::spawn`](any_spawner::Executor), but ensures that the task also runs in the current arena, if
|
||||
/// Calls [`Executor::spawn`], but ensures that the task also runs in the current arena, if
|
||||
/// multithreaded arena sandboxing is enabled.
|
||||
pub fn spawn(task: impl Future<Output = ()> + Send + 'static) {
|
||||
#[cfg(feature = "sandboxed-arenas")]
|
||||
@@ -133,9 +132,8 @@ pub fn spawn(task: impl Future<Output = ()> + Send + 'static) {
|
||||
any_spawner::Executor::spawn(task);
|
||||
}
|
||||
|
||||
/// Calls [`Executor::spawn_local`](any_spawner::Executor), but ensures that the task runs under the current reactive [`Owner`](crate::owner::Owner) and observer.
|
||||
///
|
||||
/// Does not cancel the task if the owner is cleaned up.
|
||||
/// Calls [`Executor::spawn_local`], but ensures that the task runs under the current reactive [`Owner`]
|
||||
/// and [`Observed`]. Does not cancel the task if the owner is cleaned up.
|
||||
pub fn spawn_local_scoped(task: impl Future<Output = ()> + 'static) {
|
||||
let task = ScopedFuture::new(task);
|
||||
|
||||
@@ -145,9 +143,8 @@ pub fn spawn_local_scoped(task: impl Future<Output = ()> + 'static) {
|
||||
any_spawner::Executor::spawn_local(task);
|
||||
}
|
||||
|
||||
/// Calls [`Executor::spawn_local`](any_spawner::Executor), but ensures that the task runs under the current reactive [`Owner`](crate::owner::Owner) and observer.
|
||||
///
|
||||
/// Cancels the task if the owner is cleaned up.
|
||||
/// Calls [`Executor::spawn_local`], but ensures that the task runs under the current reactive [`Owner`]
|
||||
/// and [`Observed`]. Cancels the task if the owner is cleaned up.
|
||||
pub fn spawn_local_scoped_with_cancellation(
|
||||
task: impl Future<Output = ()> + 'static,
|
||||
) {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#[allow(deprecated)]
|
||||
use crate::wrappers::read::{MaybeProp, MaybeSignal};
|
||||
use crate::{
|
||||
computed::{ArcMemo, Memo},
|
||||
owner::Storage,
|
||||
@@ -9,7 +7,7 @@ use crate::{
|
||||
},
|
||||
traits::{Get, Set},
|
||||
wrappers::{
|
||||
read::{ArcSignal, Signal, SignalTypes},
|
||||
read::{ArcSignal, MaybeProp, MaybeSignal, Signal},
|
||||
write::SignalSetter,
|
||||
},
|
||||
};
|
||||
@@ -114,8 +112,7 @@ macro_rules! impl_get_fn_traits_get_arena {
|
||||
($($ty:ident),*) => {
|
||||
$(
|
||||
#[cfg(feature = "nightly")]
|
||||
#[allow(deprecated)]
|
||||
impl<T, S> FnOnce<()> for $ty<T, S> where $ty<T, S>: Get, S: Storage<T> + Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>> {
|
||||
impl<T, S> FnOnce<()> for $ty<T, S> where $ty<T, S>: Get, S: Storage<T> + Storage<Option<T>> {
|
||||
type Output = <Self as Get>::Value;
|
||||
|
||||
#[inline(always)]
|
||||
@@ -125,8 +122,7 @@ macro_rules! impl_get_fn_traits_get_arena {
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
#[allow(deprecated)]
|
||||
impl<T, S> FnMut<()> for $ty<T, S> where $ty<T, S>: Get, S: Storage<T> + Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>> {
|
||||
impl<T, S> FnMut<()> for $ty<T, S> where $ty<T, S>: Get, S: Storage<T> + Storage<Option<T>> {
|
||||
#[inline(always)]
|
||||
extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output {
|
||||
self.get()
|
||||
@@ -134,8 +130,7 @@ macro_rules! impl_get_fn_traits_get_arena {
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
#[allow(deprecated)]
|
||||
impl<T, S> Fn<()> for $ty<T, S> where $ty<T, S>: Get, S: Storage<T> + Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>> {
|
||||
impl<T, S> Fn<()> for $ty<T, S> where $ty<T, S>: Get, S: Storage<T> + Storage<Option<T>> {
|
||||
#[inline(always)]
|
||||
extern "rust-call" fn call(&self, _args: ()) -> Self::Output {
|
||||
self.get()
|
||||
|
||||
@@ -30,7 +30,7 @@ impl<T> StorageAccess<T> for SendWrapper<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A way of storing an [`ArenaItem`](super::arena_item::ArenaItem), either as itself or with a wrapper to make it threadsafe.
|
||||
/// A way of storing a [`ArenaItem`], either as itself or with a wrapper to make it threadsafe.
|
||||
///
|
||||
/// This exists because all items stored in the arena must be `Send + Sync`, but in single-threaded
|
||||
/// environments you might want or need to use thread-unsafe types.
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
#[allow(deprecated)]
|
||||
use crate::wrappers::read::{MaybeProp, MaybeSignal};
|
||||
use crate::{
|
||||
computed::{ArcMemo, Memo},
|
||||
owner::Storage,
|
||||
signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
|
||||
traits::With,
|
||||
wrappers::read::{Signal, SignalTypes},
|
||||
wrappers::read::{MaybeProp, MaybeSignal, Signal, SignalTypes},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@@ -75,7 +73,6 @@ impl<T: Serialize + 'static, St: Storage<T>> Serialize for ArcMemo<T, St> {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T, St> Serialize for MaybeSignal<T, St>
|
||||
where
|
||||
T: Clone + Send + Sync + Serialize,
|
||||
@@ -99,8 +96,15 @@ where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
match &self.0 {
|
||||
None => None::<T>.serialize(serializer),
|
||||
Some(signal) => signal.with(|value| value.serialize(serializer)),
|
||||
None | Some(MaybeSignal::Static(None)) => {
|
||||
None::<T>.serialize(serializer)
|
||||
}
|
||||
Some(MaybeSignal::Static(Some(value))) => {
|
||||
value.serialize(serializer)
|
||||
}
|
||||
Some(MaybeSignal::Dynamic(signal)) => {
|
||||
signal.with(|value| value.serialize(serializer))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -142,7 +146,6 @@ impl<'de, T: Deserialize<'de>> Deserialize<'de> for ArcRwSignal<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<'de, T: Deserialize<'de>, St> Deserialize<'de> for MaybeSignal<T, St>
|
||||
where
|
||||
St: Storage<T>,
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
use crate::{
|
||||
traits::{
|
||||
DefinedAt, Get, GetUntracked, Read, ReadUntracked, Track, With,
|
||||
WithUntracked,
|
||||
},
|
||||
unwrap_signal,
|
||||
};
|
||||
use std::panic::Location;
|
||||
|
||||
impl<T> DefinedAt for Option<T>
|
||||
where
|
||||
T: DefinedAt,
|
||||
{
|
||||
fn defined_at(&self) -> Option<&'static Location<'static>> {
|
||||
self.as_ref().map(DefinedAt::defined_at).unwrap_or(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Track for Option<T>
|
||||
where
|
||||
T: Track,
|
||||
{
|
||||
fn track(&self) {
|
||||
if let Some(signal) = self {
|
||||
signal.track();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An alternative [`ReadUntracked`](crate) trait that works with `Option<Readable>` types.
|
||||
pub trait ReadUntrackedOptional: Sized + DefinedAt {
|
||||
/// The guard type that will be returned, which can be dereferenced to the value.
|
||||
type Value;
|
||||
|
||||
/// Returns the guard, or `None` if the signal has already been disposed.
|
||||
#[track_caller]
|
||||
fn try_read_untracked(&self) -> Option<Self::Value>;
|
||||
|
||||
/// Returns the guard.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if you try to access a signal that has been disposed.
|
||||
#[track_caller]
|
||||
fn read_untracked(&self) -> Self::Value {
|
||||
self.try_read_untracked()
|
||||
.unwrap_or_else(unwrap_signal!(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ReadUntrackedOptional for Option<T>
|
||||
where
|
||||
Self: DefinedAt,
|
||||
T: ReadUntracked,
|
||||
{
|
||||
type Value = Option<<T as ReadUntracked>::Value>;
|
||||
|
||||
fn try_read_untracked(&self) -> Option<Self::Value> {
|
||||
Some(if let Some(signal) = self {
|
||||
Some(signal.try_read_untracked()?)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// An alternative [`Read`](crate) trait that works with `Option<Readable>` types.
|
||||
pub trait ReadOptional: DefinedAt {
|
||||
/// The guard type that will be returned, which can be dereferenced to the value.
|
||||
type Value;
|
||||
|
||||
/// Subscribes to the signal, and returns the guard, or `None` if the signal has already been disposed.
|
||||
#[track_caller]
|
||||
fn try_read(&self) -> Option<Self::Value>;
|
||||
|
||||
/// Subscribes to the signal, and returns the guard.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if you try to access a signal that has been disposed.
|
||||
#[track_caller]
|
||||
fn read(&self) -> Self::Value {
|
||||
self.try_read().unwrap_or_else(unwrap_signal!(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ReadOptional for Option<T>
|
||||
where
|
||||
Self: DefinedAt,
|
||||
T: Read,
|
||||
{
|
||||
type Value = Option<<T as Read>::Value>;
|
||||
|
||||
fn try_read(&self) -> Option<Self::Value> {
|
||||
Some(if let Some(readable) = self {
|
||||
Some(readable.try_read()?)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// An alternative [`WithUntracked`](crate) trait that works with `Option<Withable>` types.
|
||||
pub trait WithUntrackedOptional: DefinedAt {
|
||||
/// The type of the value contained in the signal.
|
||||
type Value: ?Sized;
|
||||
|
||||
/// Applies the closure to the value, and returns the result,
|
||||
/// or `None` if the signal has already been disposed.
|
||||
#[track_caller]
|
||||
fn try_with_untracked<U>(
|
||||
&self,
|
||||
fun: impl FnOnce(Option<&Self::Value>) -> U,
|
||||
) -> Option<U>;
|
||||
|
||||
/// Applies the closure to the value, and returns the result.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if you try to access a signal that has been disposed.
|
||||
#[track_caller]
|
||||
fn with_untracked<U>(
|
||||
&self,
|
||||
fun: impl FnOnce(Option<&Self::Value>) -> U,
|
||||
) -> U {
|
||||
self.try_with_untracked(fun)
|
||||
.unwrap_or_else(unwrap_signal!(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WithUntrackedOptional for Option<T>
|
||||
where
|
||||
Self: DefinedAt,
|
||||
T: WithUntracked,
|
||||
<T as WithUntracked>::Value: Sized,
|
||||
{
|
||||
type Value = <T as WithUntracked>::Value;
|
||||
|
||||
fn try_with_untracked<U>(
|
||||
&self,
|
||||
fun: impl FnOnce(Option<&Self::Value>) -> U,
|
||||
) -> Option<U> {
|
||||
if let Some(signal) = self {
|
||||
Some(signal.try_with_untracked(|val| fun(Some(val)))?)
|
||||
} else {
|
||||
Some(fun(None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An alternative [`With`](crate) trait that works with `Option<Withable>` types.
|
||||
pub trait WithOptional: DefinedAt {
|
||||
/// The type of the value contained in the signal.
|
||||
type Value: ?Sized;
|
||||
|
||||
/// Subscribes to the signal, applies the closure to the value, and returns the result,
|
||||
/// or `None` if the signal has already been disposed.
|
||||
#[track_caller]
|
||||
fn try_with<U>(
|
||||
&self,
|
||||
fun: impl FnOnce(Option<&Self::Value>) -> U,
|
||||
) -> Option<U>;
|
||||
|
||||
/// Subscribes to the signal, applies the closure to the value, and returns the result.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if you try to access a signal that has been disposed.
|
||||
#[track_caller]
|
||||
fn with<U>(&self, fun: impl FnOnce(Option<&Self::Value>) -> U) -> U {
|
||||
self.try_with(fun).unwrap_or_else(unwrap_signal!(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WithOptional for Option<T>
|
||||
where
|
||||
Self: DefinedAt,
|
||||
T: With,
|
||||
<T as With>::Value: Sized,
|
||||
{
|
||||
type Value = <T as With>::Value;
|
||||
|
||||
fn try_with<U>(
|
||||
&self,
|
||||
fun: impl FnOnce(Option<&Self::Value>) -> U,
|
||||
) -> Option<U> {
|
||||
if let Some(signal) = self {
|
||||
Some(signal.try_with(|val| fun(Some(val)))?)
|
||||
} else {
|
||||
Some(fun(None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> GetUntracked for Option<T>
|
||||
where
|
||||
Self: DefinedAt,
|
||||
T: GetUntracked,
|
||||
{
|
||||
type Value = Option<<T as GetUntracked>::Value>;
|
||||
|
||||
fn try_get_untracked(&self) -> Option<Self::Value> {
|
||||
Some(if let Some(signal) = self {
|
||||
Some(signal.try_get_untracked()?)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Get for Option<T>
|
||||
where
|
||||
Self: DefinedAt,
|
||||
T: Get,
|
||||
{
|
||||
type Value = Option<<T as Get>::Value>;
|
||||
|
||||
fn try_get(&self) -> Option<Self::Value> {
|
||||
Some(if let Some(signal) = self {
|
||||
Some(signal.try_get()?)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper trait to implement flatten() on `Option<&Option<T>>`.
|
||||
pub trait FlattenOptionRefOption {
|
||||
/// The type of the value contained in the double option.
|
||||
type Value;
|
||||
|
||||
/// Converts from `Option<&Option<T>>` to `Option<&T>`.
|
||||
fn flatten(&self) -> Option<&Self::Value>;
|
||||
}
|
||||
|
||||
impl<'a, T> FlattenOptionRefOption for Option<&'a Option<T>> {
|
||||
type Value = T;
|
||||
|
||||
fn flatten(&self) -> Option<&'a T> {
|
||||
self.map(Option::as_ref).flatten()
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
//! | Trait | Mode | Description |
|
||||
//! |-------------------|-------|---------------------------------------------------------------------------------------|
|
||||
//! | [`Track`] | — | Tracks changes to this value, adding it as a source of the current reactive observer. |
|
||||
//! | [`Notify`] | — | Notifies subscribers that this value has changed. |
|
||||
//! | [`Trigger`] | — | Notifies subscribers that this value has changed. |
|
||||
//! | [`ReadUntracked`] | Guard | Gives immutable access to the value of this signal. |
|
||||
//! | [`Write`] | Guard | Gives mutable access to the value of this signal.
|
||||
//!
|
||||
@@ -34,7 +34,7 @@
|
||||
//! | Trait | Mode | Composition | Description
|
||||
//! |---------------------|---------------|-----------------------------------|------------
|
||||
//! | [`UpdateUntracked`] | `fn(&mut T)` | [`Write`] | Applies closure to the current value to update it, but doesn't notify subscribers.
|
||||
//! | [`Update`] | `fn(&mut T)` | [`UpdateUntracked`] + [`Notify`] | Applies closure to the current value to update it, and notifies subscribers.
|
||||
//! | [`Update`] | `fn(&mut T)` | [`UpdateUntracked`] + [`Trigger`] | Applies closure to the current value to update it, and notifies subscribers.
|
||||
//! | [`Set`] | `T` | [`Update`] | Sets the value to a new value, and notifies subscribers.
|
||||
//!
|
||||
//! ## Using the Traits
|
||||
@@ -48,7 +48,6 @@
|
||||
//! there isn't an `RwLock` so you can't wrap in a [`ReadGuard`](crate::signal::guards::ReadGuard),
|
||||
//! but you can still implement [`WithUntracked`] and [`Track`], the same traits will still be implemented.
|
||||
|
||||
pub use crate::trait_options::*;
|
||||
use crate::{
|
||||
effect::Effect,
|
||||
graph::{Observer, Source, Subscriber, ToAnySource},
|
||||
|
||||
@@ -606,33 +606,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync + 'static> From<T> for ArcSignal<T, SyncStorage> {
|
||||
#[track_caller]
|
||||
fn from(value: T) -> Self {
|
||||
ArcSignal::stored(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Signal<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: T) -> Self {
|
||||
Self::stored(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Signal<T, LocalStorage>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: T) -> Self {
|
||||
Self::stored_local(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ArcSignal<T, SyncStorage>> for Signal<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -708,34 +681,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ArcReadSignal<T>> for Signal<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: ArcReadSignal<T>) -> Self {
|
||||
Self {
|
||||
inner: ArenaItem::new(SignalTypes::ReadSignal(value)),
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ArcReadSignal<T>> for Signal<T, LocalStorage>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: ArcReadSignal<T>) -> Self {
|
||||
Self {
|
||||
inner: ArenaItem::new_local(SignalTypes::ReadSignal(value)),
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<RwSignal<T>> for Signal<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -768,38 +713,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ArcRwSignal<T>> for Signal<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: ArcRwSignal<T>) -> Self {
|
||||
Self {
|
||||
inner: ArenaItem::new(SignalTypes::ReadSignal(
|
||||
value.read_only(),
|
||||
)),
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ArcRwSignal<T>> for Signal<T, LocalStorage>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: ArcRwSignal<T>) -> Self {
|
||||
Self {
|
||||
inner: ArenaItem::new_local(SignalTypes::ReadSignal(
|
||||
value.read_only(),
|
||||
)),
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Memo<T>> for Signal<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -828,74 +741,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ArcMemo<T>> for Signal<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: ArcMemo<T>) -> Self {
|
||||
Self {
|
||||
inner: ArenaItem::new(SignalTypes::Memo(value)),
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<ArcMemo<T, LocalStorage>> for Signal<T, LocalStorage>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: ArcMemo<T, LocalStorage>) -> Self {
|
||||
Self {
|
||||
inner: ArenaItem::new_local(SignalTypes::Memo(value)),
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Signal<Option<T>>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: T) -> Self {
|
||||
Signal::stored(Some(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for Signal<Option<T>, LocalStorage>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: T) -> Self {
|
||||
Signal::stored_local(Some(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Signal<T>> for Signal<Option<T>>
|
||||
where
|
||||
T: Clone + Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: Signal<T>) -> Self {
|
||||
Signal::derive(move || Some(value.get()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Signal<T, LocalStorage>> for Signal<Option<T>, LocalStorage>
|
||||
where
|
||||
T: Clone + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: Signal<T, LocalStorage>) -> Self {
|
||||
Signal::derive_local(move || Some(value.get()))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Signal<String> {
|
||||
#[track_caller]
|
||||
fn from(value: &str) -> Self {
|
||||
@@ -968,7 +813,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<MaybeSignal<T>> for Signal<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -982,7 +826,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<MaybeSignal<T, LocalStorage>> for Signal<T, LocalStorage>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -996,7 +839,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<MaybeSignal<T>> for Signal<Option<T>>
|
||||
where
|
||||
T: Clone + Send + Sync + 'static,
|
||||
@@ -1012,7 +854,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<MaybeSignal<T, LocalStorage>> for Signal<Option<T>, LocalStorage>
|
||||
where
|
||||
T: Clone + Send + Sync + 'static,
|
||||
@@ -1028,27 +869,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<MaybeProp<T>> for Option<Signal<Option<T>>>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: MaybeProp<T>) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<MaybeProp<T, LocalStorage>>
|
||||
for Option<Signal<Option<T>, LocalStorage>>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn from(value: MaybeProp<T, LocalStorage>) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper for a value that is *either* `T` or [`Signal<T>`].
|
||||
///
|
||||
/// This allows you to create APIs that take either a reactive or a non-reactive value
|
||||
@@ -1077,12 +897,6 @@ pub mod read {
|
||||
/// assert_eq!(above_3(&memoized_double_count.into()), true);
|
||||
/// ```
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[deprecated(
|
||||
since = "0.7.0-rc1",
|
||||
note = "`MaybeSignal<T>` is deprecated in favour of `Signal<T>` which \
|
||||
is `Copy`, now has a more efficient From<T> implementation \
|
||||
and other benefits in 0.7."
|
||||
)]
|
||||
pub enum MaybeSignal<T, S = SyncStorage>
|
||||
where
|
||||
T: 'static,
|
||||
@@ -1094,7 +908,6 @@ pub mod read {
|
||||
Dynamic(Signal<T, S>),
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T: Clone, S> Clone for MaybeSignal<T, S>
|
||||
where
|
||||
S: Storage<T>,
|
||||
@@ -1107,10 +920,8 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T: Copy, S> Copy for MaybeSignal<T, S> where S: Storage<T> {}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T: Default, S> Default for MaybeSignal<T, S>
|
||||
where
|
||||
S: Storage<T>,
|
||||
@@ -1120,7 +931,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T, S> DefinedAt for MaybeSignal<T, S>
|
||||
where
|
||||
S: Storage<T>,
|
||||
@@ -1132,7 +942,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T, S> Track for MaybeSignal<T, S>
|
||||
where
|
||||
S: Storage<T> + Storage<SignalTypes<T, S>>,
|
||||
@@ -1145,7 +954,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T, S> ReadUntracked for MaybeSignal<T, S>
|
||||
where
|
||||
T: Clone,
|
||||
@@ -1170,7 +978,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> MaybeSignal<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
@@ -1184,7 +991,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> MaybeSignal<T, LocalStorage> {
|
||||
/// Wraps a derived signal, i.e., any computation that accesses one or more
|
||||
/// reactive signals.
|
||||
@@ -1193,7 +999,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<T> for MaybeSignal<T, SyncStorage>
|
||||
where
|
||||
SyncStorage: Storage<T>,
|
||||
@@ -1203,7 +1008,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> FromLocal<T> for MaybeSignal<T, LocalStorage>
|
||||
where
|
||||
LocalStorage: Storage<T>,
|
||||
@@ -1213,7 +1017,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<ReadSignal<T>> for MaybeSignal<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
@@ -1223,14 +1026,12 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<ReadSignal<T, LocalStorage>> for MaybeSignal<T, LocalStorage> {
|
||||
fn from(value: ReadSignal<T, LocalStorage>) -> Self {
|
||||
Self::Dynamic(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<RwSignal<T>> for MaybeSignal<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
@@ -1240,14 +1041,12 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<RwSignal<T, LocalStorage>> for MaybeSignal<T, LocalStorage> {
|
||||
fn from(value: RwSignal<T, LocalStorage>) -> Self {
|
||||
Self::Dynamic(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<Memo<T>> for MaybeSignal<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
@@ -1257,14 +1056,12 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<Memo<T, LocalStorage>> for MaybeSignal<T, LocalStorage> {
|
||||
fn from(value: Memo<T, LocalStorage>) -> Self {
|
||||
Self::Dynamic(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<ArcReadSignal<T>> for MaybeSignal<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
@@ -1274,14 +1071,12 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> FromLocal<ArcReadSignal<T>> for MaybeSignal<T, LocalStorage> {
|
||||
fn from_local(value: ArcReadSignal<T>) -> Self {
|
||||
ReadSignal::from_local(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<ArcRwSignal<T>> for MaybeSignal<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
@@ -1291,7 +1086,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> FromLocal<ArcRwSignal<T>> for MaybeSignal<T, LocalStorage>
|
||||
where
|
||||
T: 'static,
|
||||
@@ -1301,7 +1095,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<ArcMemo<T>> for MaybeSignal<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
@@ -1311,14 +1104,12 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> FromLocal<ArcMemo<T, LocalStorage>> for MaybeSignal<T, LocalStorage> {
|
||||
fn from_local(value: ArcMemo<T, LocalStorage>) -> Self {
|
||||
Memo::from_local(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T, S> From<Signal<T, S>> for MaybeSignal<T, S>
|
||||
where
|
||||
S: Storage<T>,
|
||||
@@ -1328,7 +1119,6 @@ pub mod read {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<S> From<&str> for MaybeSignal<String, S>
|
||||
where
|
||||
S: Storage<String> + Storage<Arc<RwLock<String>>>,
|
||||
@@ -1372,28 +1162,25 @@ pub mod read {
|
||||
/// ```
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct MaybeProp<T: 'static, S = SyncStorage>(
|
||||
pub(crate) Option<Signal<Option<T>, S>>,
|
||||
pub(crate) Option<MaybeSignal<Option<T>, S>>,
|
||||
)
|
||||
where
|
||||
S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>;
|
||||
S: Storage<Option<T>>;
|
||||
|
||||
impl<T, S> Clone for MaybeProp<T, S>
|
||||
impl<T: Clone, S> Clone for MaybeProp<T, S>
|
||||
where
|
||||
S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>,
|
||||
S: Storage<Option<T>>,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> Copy for MaybeProp<T, S> where
|
||||
S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>
|
||||
{
|
||||
}
|
||||
impl<T: Copy, S> Copy for MaybeProp<T, S> where S: Storage<Option<T>> {}
|
||||
|
||||
impl<T, S> Default for MaybeProp<T, S>
|
||||
where
|
||||
S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>,
|
||||
S: Storage<Option<T>>,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self(None)
|
||||
@@ -1402,7 +1189,7 @@ pub mod read {
|
||||
|
||||
impl<T, S> DefinedAt for MaybeProp<T, S>
|
||||
where
|
||||
S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>,
|
||||
S: Storage<Option<T>>,
|
||||
{
|
||||
fn defined_at(&self) -> Option<&'static Location<'static>> {
|
||||
// TODO this can be improved by adding a defined_at field
|
||||
@@ -1425,7 +1212,7 @@ pub mod read {
|
||||
impl<T, S> ReadUntracked for MaybeProp<T, S>
|
||||
where
|
||||
T: Clone,
|
||||
S: Storage<Option<T>> + Storage<SignalTypes<Option<T>, S>>,
|
||||
S: Storage<SignalTypes<Option<T>, S>> + Storage<Option<T>>,
|
||||
{
|
||||
type Value = ReadGuard<Option<T>, SignalReadGuard<Option<T>, S>>;
|
||||
|
||||
@@ -1453,49 +1240,43 @@ pub mod read {
|
||||
pub fn derive(
|
||||
derived_signal: impl Fn() -> Option<T> + Send + Sync + 'static,
|
||||
) -> Self {
|
||||
Self(Some(Signal::derive(derived_signal)))
|
||||
Self(Some(MaybeSignal::derive(derived_signal)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for MaybeProp<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
SyncStorage: Storage<Option<T>>,
|
||||
{
|
||||
fn from(value: T) -> Self {
|
||||
Self(Some(Signal::stored(Some(value))))
|
||||
Self(Some(MaybeSignal::from(Some(value))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Option<T>> for MaybeProp<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
SyncStorage: Storage<Option<T>>,
|
||||
{
|
||||
fn from(value: Option<T>) -> Self {
|
||||
Self(Some(Signal::stored(value)))
|
||||
Self(Some(MaybeSignal::from(value)))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<MaybeSignal<Option<T>>> for MaybeProp<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
SyncStorage: Storage<Option<T>>,
|
||||
{
|
||||
fn from(value: MaybeSignal<Option<T>>) -> Self {
|
||||
Self(Some(value.into()))
|
||||
Self(Some(value))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<Option<MaybeSignal<Option<T>>>> for MaybeProp<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
SyncStorage: Storage<Option<T>>,
|
||||
{
|
||||
fn from(value: Option<MaybeSignal<Option<T>>>) -> Self {
|
||||
Self(value.map(Into::into))
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1528,11 +1309,10 @@ pub mod read {
|
||||
|
||||
impl<T> From<Signal<Option<T>>> for MaybeProp<T>
|
||||
where
|
||||
T: Send + Sync,
|
||||
SyncStorage: Storage<Option<T>>,
|
||||
{
|
||||
fn from(value: Signal<Option<T>>) -> Self {
|
||||
Self(Some(value))
|
||||
Self(Some(value.into()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1541,7 +1321,7 @@ pub mod read {
|
||||
T: Send + Sync + Clone,
|
||||
{
|
||||
fn from(value: ReadSignal<T>) -> Self {
|
||||
Self(Some(Signal::derive(move || Some(value.get()))))
|
||||
Self(Some(MaybeSignal::derive(move || Some(value.get()))))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1550,7 +1330,7 @@ pub mod read {
|
||||
T: Send + Sync + Clone,
|
||||
{
|
||||
fn from(value: RwSignal<T>) -> Self {
|
||||
Self(Some(Signal::derive(move || Some(value.get()))))
|
||||
Self(Some(MaybeSignal::derive(move || Some(value.get()))))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1559,7 +1339,7 @@ pub mod read {
|
||||
T: Send + Sync + Clone,
|
||||
{
|
||||
fn from(value: Memo<T>) -> Self {
|
||||
Self(Some(Signal::derive(move || Some(value.get()))))
|
||||
Self(Some(MaybeSignal::derive(move || Some(value.get()))))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1568,13 +1348,13 @@ pub mod read {
|
||||
T: Send + Sync + Clone,
|
||||
{
|
||||
fn from(value: Signal<T>) -> Self {
|
||||
Self(Some(Signal::derive(move || Some(value.get()))))
|
||||
Self(Some(MaybeSignal::derive(move || Some(value.get()))))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for MaybeProp<String> {
|
||||
fn from(value: &str) -> Self {
|
||||
Self(Some(Signal::from(Some(value.to_string()))))
|
||||
Self(Some(MaybeSignal::from(Some(value.to_string()))))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1584,41 +1364,35 @@ pub mod read {
|
||||
pub fn derive_local(
|
||||
derived_signal: impl Fn() -> Option<T> + 'static,
|
||||
) -> Self {
|
||||
Self(Some(Signal::derive_local(derived_signal)))
|
||||
Self(Some(MaybeSignal::derive_local(derived_signal)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> FromLocal<T> for MaybeProp<T, LocalStorage> {
|
||||
fn from_local(value: T) -> Self {
|
||||
Self(Some(Signal::stored_local(Some(value))))
|
||||
Self(Some(MaybeSignal::from_local(Some(value))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> FromLocal<Option<T>> for MaybeProp<T, LocalStorage> {
|
||||
fn from_local(value: Option<T>) -> Self {
|
||||
Self(Some(Signal::stored_local(value)))
|
||||
Self(Some(MaybeSignal::from_local(value)))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<MaybeSignal<Option<T>, LocalStorage>>
|
||||
for MaybeProp<T, LocalStorage>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
fn from(value: MaybeSignal<Option<T>, LocalStorage>) -> Self {
|
||||
Self(Some(value.into()))
|
||||
Self(Some(value))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T> From<Option<MaybeSignal<Option<T>, LocalStorage>>>
|
||||
for MaybeProp<T, LocalStorage>
|
||||
where
|
||||
T: Send + Sync,
|
||||
{
|
||||
fn from(value: Option<MaybeSignal<Option<T>, LocalStorage>>) -> Self {
|
||||
Self(value.map(Into::into))
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1651,7 +1425,7 @@ pub mod read {
|
||||
|
||||
impl<T> From<Signal<Option<T>, LocalStorage>> for MaybeProp<T, LocalStorage> {
|
||||
fn from(value: Signal<Option<T>, LocalStorage>) -> Self {
|
||||
Self(Some(value))
|
||||
Self(Some(value.into()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1660,7 +1434,7 @@ pub mod read {
|
||||
T: Send + Sync + Clone,
|
||||
{
|
||||
fn from(value: ReadSignal<T, LocalStorage>) -> Self {
|
||||
Self(Some(Signal::derive_local(move || Some(value.get()))))
|
||||
Self(Some(MaybeSignal::derive_local(move || Some(value.get()))))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1669,7 +1443,7 @@ pub mod read {
|
||||
T: Send + Sync + Clone,
|
||||
{
|
||||
fn from(value: RwSignal<T, LocalStorage>) -> Self {
|
||||
Self(Some(Signal::derive_local(move || Some(value.get()))))
|
||||
Self(Some(MaybeSignal::derive_local(move || Some(value.get()))))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1678,7 +1452,7 @@ pub mod read {
|
||||
T: Send + Sync + Clone,
|
||||
{
|
||||
fn from(value: Memo<T, LocalStorage>) -> Self {
|
||||
Self(Some(Signal::derive_local(move || Some(value.get()))))
|
||||
Self(Some(MaybeSignal::derive_local(move || Some(value.get()))))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1687,13 +1461,13 @@ pub mod read {
|
||||
T: Send + Sync + Clone,
|
||||
{
|
||||
fn from(value: Signal<T, LocalStorage>) -> Self {
|
||||
Self(Some(Signal::derive_local(move || Some(value.get()))))
|
||||
Self(Some(MaybeSignal::derive_local(move || Some(value.get()))))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for MaybeProp<String, LocalStorage> {
|
||||
fn from(value: &str) -> Self {
|
||||
Self(Some(Signal::stored_local(Some(value.to_string()))))
|
||||
Self(Some(MaybeSignal::from_local(Some(value.to_string()))))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reactive_stores"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-rc1"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -7,7 +7,6 @@ use reactive_graph::{
|
||||
owner::Storage,
|
||||
traits::{
|
||||
DefinedAt, IsDisposed, Notify, ReadUntracked, Track, UntrackableGuard,
|
||||
Write,
|
||||
},
|
||||
};
|
||||
use std::{
|
||||
@@ -32,8 +31,7 @@ where
|
||||
trigger: StoreFieldTrigger,
|
||||
get_trigger: Arc<dyn Fn(StorePath) -> StoreFieldTrigger + Send + Sync>,
|
||||
read: Arc<dyn Fn() -> Option<StoreFieldReader<T>> + Send + Sync>,
|
||||
pub(crate) write:
|
||||
Arc<dyn Fn() -> Option<StoreFieldWriter<T>> + Send + Sync>,
|
||||
write: Arc<dyn Fn() -> Option<StoreFieldWriter<T>> + Send + Sync>,
|
||||
keys: Arc<dyn Fn() -> Option<KeyMap> + Send + Sync>,
|
||||
track_field: Arc<dyn Fn() + Send + Sync>,
|
||||
}
|
||||
@@ -331,22 +329,6 @@ impl<T> ReadUntracked for ArcField<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Write for ArcField<T> {
|
||||
type Value = T;
|
||||
|
||||
fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
|
||||
(self.write)()
|
||||
}
|
||||
|
||||
fn try_write_untracked(
|
||||
&self,
|
||||
) -> Option<impl DerefMut<Target = Self::Value>> {
|
||||
let mut guard = (self.write)()?;
|
||||
guard.untrack();
|
||||
Some(guard)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IsDisposed for ArcField<T> {
|
||||
fn is_disposed(&self) -> bool {
|
||||
false
|
||||
|
||||
@@ -6,18 +6,10 @@ use crate::{
|
||||
};
|
||||
use reactive_graph::{
|
||||
owner::{ArenaItem, Storage, SyncStorage},
|
||||
traits::{
|
||||
DefinedAt, IsDisposed, Notify, ReadUntracked, Track, UntrackableGuard,
|
||||
Write,
|
||||
},
|
||||
traits::{DefinedAt, IsDisposed, Notify, ReadUntracked, Track},
|
||||
unwrap_signal,
|
||||
};
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
hash::Hash,
|
||||
ops::{DerefMut, IndexMut},
|
||||
panic::Location,
|
||||
};
|
||||
use std::{fmt::Debug, hash::Hash, ops::IndexMut, panic::Location};
|
||||
|
||||
/// Wraps access to a single field of type `T`.
|
||||
///
|
||||
@@ -212,24 +204,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Write for Field<T> {
|
||||
type Value = T;
|
||||
|
||||
fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
|
||||
self.inner.try_get_value().and_then(|inner| (inner.write)())
|
||||
}
|
||||
|
||||
fn try_write_untracked(
|
||||
&self,
|
||||
) -> Option<impl DerefMut<Target = Self::Value>> {
|
||||
self.inner.try_get_value().and_then(|inner| {
|
||||
let mut guard = (inner.write)()?;
|
||||
guard.untrack();
|
||||
Some(guard)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> IsDisposed for Field<T, S> {
|
||||
fn is_disposed(&self) -> bool {
|
||||
self.inner.is_disposed()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{StoreField, Subfield};
|
||||
use reactive_graph::traits::{Read, ReadUntracked};
|
||||
use reactive_graph::traits::Read;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// Extends optional store fields, with the ability to unwrap or map over them.
|
||||
@@ -23,23 +23,12 @@ where
|
||||
self,
|
||||
map_fn: impl FnOnce(Subfield<Self, Option<Self::Output>, Self::Output>) -> U,
|
||||
) -> Option<U>;
|
||||
|
||||
/// Unreactively maps over the field.
|
||||
///
|
||||
/// This returns `None` if the subfield is currently `None`,
|
||||
/// and a new store subfield with the inner value if it is `Some`. This is an unreactive variant of
|
||||
/// `[OptionStoreExt::map]`, and will not cause the reactive context to re-run if the field changes.
|
||||
fn map_untracked<U>(
|
||||
self,
|
||||
map_fn: impl FnOnce(Subfield<Self, Option<Self::Output>, Self::Output>) -> U,
|
||||
) -> Option<U>;
|
||||
}
|
||||
|
||||
impl<T, S> OptionStoreExt for S
|
||||
where
|
||||
S: StoreField<Value = Option<T>> + Read + ReadUntracked,
|
||||
S: StoreField<Value = Option<T>> + Read,
|
||||
<S as Read>::Value: Deref<Target = Option<T>>,
|
||||
<S as ReadUntracked>::Value: Deref<Target = Option<T>>,
|
||||
{
|
||||
type Output = T;
|
||||
|
||||
@@ -62,17 +51,6 @@ where
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn map_untracked<U>(
|
||||
self,
|
||||
map_fn: impl FnOnce(Subfield<S, Option<T>, T>) -> U,
|
||||
) -> Option<U> {
|
||||
if self.read_untracked().is_some() {
|
||||
Some(map_fn(self.unwrap()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reactive_stores_macro"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-rc1"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_router"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
authors = ["Greg Johnston", "Ben Wishovich"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -13,8 +13,8 @@ use crate::{
|
||||
resolve_path::resolve_path,
|
||||
ChooseView, MatchNestedRoutes, NestedRoute, RouteDefs, SsrMode,
|
||||
};
|
||||
use either_of::EitherOf3;
|
||||
use leptos::{children, prelude::*};
|
||||
use either_of::Either;
|
||||
use leptos::prelude::*;
|
||||
use reactive_graph::{
|
||||
owner::{provide_context, use_context, Owner},
|
||||
signal::ArcRwSignal,
|
||||
@@ -64,8 +64,8 @@ pub fn Router<Chil>(
|
||||
//#[prop(optional)]
|
||||
//trailing_slash: TrailingSlash,
|
||||
/// The `<Router/>` should usually wrap your whole page. It can contain
|
||||
/// any elements, and should include a [`Routes`] component somewhere
|
||||
/// to define and display [`Route`]s.
|
||||
/// any elements, and should include a [`Routes`](crate::Routes) component somewhere
|
||||
/// to define and display [`Route`](crate::Route)s.
|
||||
children: TypedChildren<Chil>,
|
||||
) -> impl IntoView
|
||||
where
|
||||
@@ -328,10 +328,9 @@ where
|
||||
/// and the element it should display.
|
||||
#[component(transparent)]
|
||||
pub fn Route<Segments, View>(
|
||||
/// The path fragment that this route should match. This can be created using the
|
||||
/// [`path`](crate::path) macro, or path segments ([`StaticSegment`](crate::StaticSegment),
|
||||
/// [`ParamSegment`](crate::ParamSegment), [`WildcardSegment`](crate::WildcardSegment), and
|
||||
/// [`OptionalParamSegment`](crate::OptionalParamSegment)).
|
||||
/// The path fragment that this route should match. This can be created using the [`path`]
|
||||
/// macro, or path segments ([`StaticSegment`], [`ParamSegment`], [`WildcardSegment`], and
|
||||
/// [`OptionalParamSegment`]).
|
||||
path: Segments,
|
||||
/// The view for this route.
|
||||
view: View,
|
||||
@@ -350,10 +349,9 @@ where
|
||||
/// and the element it should display.
|
||||
#[component(transparent)]
|
||||
pub fn ParentRoute<Segments, View, Children>(
|
||||
/// The path fragment that this route should match. This can be created using the
|
||||
/// [`path`](crate::path) macro, or path segments ([`StaticSegment`](crate::StaticSegment),
|
||||
/// [`ParamSegment`](crate::ParamSegment), [`WildcardSegment`](crate::WildcardSegment), and
|
||||
/// [`OptionalParamSegment`](crate::OptionalParamSegment)).
|
||||
/// The path fragment that this route should match. This can be created using the [`path`]
|
||||
/// macro, or path segments ([`StaticSegment`], [`ParamSegment`], [`WildcardSegment`], and
|
||||
/// [`OptionalParamSegment`]).
|
||||
path: Segments,
|
||||
/// The view for this route.
|
||||
view: View,
|
||||
@@ -376,10 +374,9 @@ where
|
||||
/// redirects to `redirect_path` instead of displaying its `view`.
|
||||
#[component(transparent)]
|
||||
pub fn ProtectedRoute<Segments, ViewFn, View, C, PathFn, P>(
|
||||
/// The path fragment that this route should match. This can be created using the
|
||||
/// [`path`](crate::path) macro, or path segments ([`StaticSegment`](crate::StaticSegment),
|
||||
/// [`ParamSegment`](crate::ParamSegment), [`WildcardSegment`](crate::WildcardSegment), and
|
||||
/// [`OptionalParamSegment`](crate::OptionalParamSegment)).
|
||||
/// The path fragment that this route should match. This can be created using the [`path`]
|
||||
/// macro, or path segments ([`StaticSegment`], [`ParamSegment`], [`WildcardSegment`], and
|
||||
/// [`OptionalParamSegment`]).
|
||||
path: Segments,
|
||||
/// The view for this route.
|
||||
view: ViewFn,
|
||||
@@ -389,9 +386,6 @@ pub fn ProtectedRoute<Segments, ViewFn, View, C, PathFn, P>(
|
||||
condition: C,
|
||||
/// The path that will be redirected to if the condition is `Some(false)`.
|
||||
redirect_path: PathFn,
|
||||
/// Will be displayed while the condition is pending. By default this is the empty view.
|
||||
#[prop(optional, into)]
|
||||
fallback: children::ViewFn,
|
||||
/// The mode that this route prefers during server-side rendering.
|
||||
/// Defaults to out-of-order streaming.
|
||||
#[prop(optional)]
|
||||
@@ -404,26 +398,23 @@ where
|
||||
PathFn: Fn() -> P + Send + Clone + 'static,
|
||||
P: Display + 'static,
|
||||
{
|
||||
let fallback = move || fallback.run();
|
||||
let view = move || {
|
||||
let condition = condition.clone();
|
||||
let redirect_path = redirect_path.clone();
|
||||
let view = view.clone();
|
||||
let fallback = fallback.clone();
|
||||
(view! {
|
||||
<Transition fallback=fallback.clone()>
|
||||
<Transition>
|
||||
{move || {
|
||||
let condition = condition();
|
||||
let view = view.clone();
|
||||
let redirect_path = redirect_path.clone();
|
||||
let fallback = fallback.clone();
|
||||
Unsuspend::new(move || match condition {
|
||||
Some(true) => EitherOf3::A(view()),
|
||||
Some(true) => Either::Left(view()),
|
||||
#[allow(clippy::unit_arg)]
|
||||
Some(false) => {
|
||||
EitherOf3::B(view! { <Redirect path=redirect_path()/> }.into_inner())
|
||||
Either::Right(view! { <Redirect path=redirect_path()/> }.into_inner())
|
||||
}
|
||||
None => EitherOf3::C(fallback()),
|
||||
None => Either::Right(()),
|
||||
})
|
||||
}}
|
||||
|
||||
@@ -436,10 +427,9 @@ where
|
||||
|
||||
#[component(transparent)]
|
||||
pub fn ProtectedParentRoute<Segments, ViewFn, View, C, PathFn, P, Children>(
|
||||
/// The path fragment that this route should match. This can be created using the
|
||||
/// [`path`](crate::path) macro, or path segments ([`StaticSegment`](crate::StaticSegment),
|
||||
/// [`ParamSegment`](crate::ParamSegment), [`WildcardSegment`](crate::WildcardSegment), and
|
||||
/// [`OptionalParamSegment`](crate::OptionalParamSegment)).
|
||||
/// The path fragment that this route should match. This can be created using the [`path`]
|
||||
/// macro, or path segments ([`StaticSegment`], [`ParamSegment`], [`WildcardSegment`], and
|
||||
/// [`OptionalParamSegment`]).
|
||||
path: Segments,
|
||||
/// The view for this route.
|
||||
view: ViewFn,
|
||||
@@ -447,9 +437,6 @@ pub fn ProtectedParentRoute<Segments, ViewFn, View, C, PathFn, P, Children>(
|
||||
/// the page, `Some(false)` means the user cannot access the page, and `None` means this
|
||||
/// information is still loading.
|
||||
condition: C,
|
||||
/// Will be displayed while the condition is pending. By default this is the empty view.
|
||||
#[prop(optional, into)]
|
||||
fallback: children::ViewFn,
|
||||
/// The path that will be redirected to if the condition is `Some(false)`.
|
||||
redirect_path: PathFn,
|
||||
/// Nested child routes.
|
||||
@@ -466,21 +453,17 @@ where
|
||||
PathFn: Fn() -> P + Send + Clone + 'static,
|
||||
P: Display + 'static,
|
||||
{
|
||||
let fallback = move || fallback.run();
|
||||
let children = children.into_inner();
|
||||
let view = move || {
|
||||
let condition = condition.clone();
|
||||
let redirect_path = redirect_path.clone();
|
||||
let fallback = fallback.clone();
|
||||
let view = view.clone();
|
||||
let owner = Owner::current().unwrap();
|
||||
let view = {
|
||||
let fallback = fallback.clone();
|
||||
move || {
|
||||
let condition = condition();
|
||||
let view = view.clone();
|
||||
let redirect_path = redirect_path.clone();
|
||||
let fallback = fallback.clone();
|
||||
let owner = owner.clone();
|
||||
Unsuspend::new(move || match condition {
|
||||
// reset the owner so that things like providing context work
|
||||
@@ -489,16 +472,16 @@ where
|
||||
//
|
||||
// clippy: not redundant, a FnOnce vs FnMut issue
|
||||
#[allow(clippy::redundant_closure)]
|
||||
Some(true) => EitherOf3::A(owner.with(|| view())),
|
||||
Some(true) => Either::Left(owner.with(|| view())),
|
||||
#[allow(clippy::unit_arg)]
|
||||
Some(false) => EitherOf3::B(
|
||||
Some(false) => Either::Right(
|
||||
view! { <Redirect path=redirect_path()/> }.into_inner(),
|
||||
),
|
||||
None => EitherOf3::C(fallback()),
|
||||
None => Either::Right(()),
|
||||
})
|
||||
}
|
||||
};
|
||||
(view! { <Transition fallback>{view}</Transition> }).into_any()
|
||||
(view! { <Transition>{view}</Transition> }).into_any()
|
||||
};
|
||||
NestedRoute::new(path, view).ssr_mode(ssr).child(children)
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
//! and are rendered by different components. This means you can navigate between siblings
|
||||
//! in this tree without re-rendering or triggering any change in the parent routes.
|
||||
//!
|
||||
//! 3. **Progressive enhancement.** The [`A`](crate::components::A) and
|
||||
//! [`Form`](crate::components::Form) components resolve any relative
|
||||
//! 3. **Progressive enhancement.** The [`A`] and [`Form`] components resolve any relative
|
||||
//! nested routes, render actual `<a>` and `<form>` elements, and (when possible)
|
||||
//! upgrading them to handle those navigations with client-side routing. If you’re using
|
||||
//! them with server-side rendering (with or without hydration), they just work,
|
||||
|
||||
@@ -9,7 +9,8 @@ pub use static_segment::*;
|
||||
/// or URL segment.
|
||||
///
|
||||
/// This is a "horizontal" matching: i.e., it treats a tuple of route segments
|
||||
/// as subsequent segments of the URL and tries to match them all.
|
||||
/// as subsequent segments of the URL and tries to match them all. For a "vertical"
|
||||
/// matching that sees a tuple as alternatives to one another, see [`RouteChild`](super::RouteChild).
|
||||
pub trait PossibleRouteMatch {
|
||||
const OPTIONAL: bool = false;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ mod vertical;
|
||||
use crate::{static_routes::RegenerationFn, Method, SsrMode};
|
||||
pub use horizontal::*;
|
||||
pub use nested::*;
|
||||
use std::{borrow::Cow, collections::HashSet, sync::atomic::Ordering};
|
||||
use std::{borrow::Cow, collections::HashSet};
|
||||
pub use vertical::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -91,16 +91,6 @@ where
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct RouteMatchId(pub(crate) u16);
|
||||
|
||||
impl RouteMatchId {
|
||||
/// Creates a new match ID based on the current route ID used in nested route generation.
|
||||
///
|
||||
/// In general, you do not need this; it should only be used for custom route matching behavior
|
||||
/// in a library that creates its own route types.
|
||||
pub fn new_from_route_id() -> RouteMatchId {
|
||||
RouteMatchId(ROUTE_ID.fetch_add(1, Ordering::Relaxed))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MatchInterface {
|
||||
type Child: MatchInterface + MatchParams + 'static;
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use std::{
|
||||
|
||||
mod tuples;
|
||||
|
||||
pub(crate) static ROUTE_ID: AtomicU16 = AtomicU16::new(1);
|
||||
static ROUTE_ID: AtomicU16 = AtomicU16::new(1);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct NestedRoute<Segments, Children, Data, View> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::location::State;
|
||||
|
||||
/// Options that can be used to configure a navigation. Used with [use_navigate](crate::hooks::use_navigate).
|
||||
/// Options that can be used to configure a navigation. Used with [use_navigate](crate::use_navigate).
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct NavigateOptions {
|
||||
/// Whether the URL being navigated to should be resolved relative to the current route.
|
||||
|
||||
@@ -24,7 +24,7 @@ impl ParamsMap {
|
||||
/// Inserts a value into the map.
|
||||
///
|
||||
/// If a value with that key already exists, the new value will be added to it.
|
||||
/// To replace the value instead, see [`replace`](Self::replace).
|
||||
/// To replace the value instead, see [`replace`].
|
||||
pub fn insert(&mut self, key: impl Into<Cow<'static, str>>, value: String) {
|
||||
let value = Url::unescape(&value);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_router_macro"
|
||||
version = "0.7.0"
|
||||
version = "0.7.0-rc1"
|
||||
authors = ["Greg Johnston", "Ben Wishovich"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -30,7 +30,7 @@ once_cell = "1.20"
|
||||
actix-web = { version = "4.9", optional = true }
|
||||
|
||||
# axum
|
||||
axum = { version = "0.7.9", optional = true, default-features = false, features = [
|
||||
axum = { version = "0.7.8", optional = true, default-features = false, features = [
|
||||
"multipart",
|
||||
] }
|
||||
tower = { version = "0.5.1", optional = true }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tachys"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-rc1"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -9,9 +9,8 @@ where
|
||||
E: AsRef<str>,
|
||||
{
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
tag: Custom(tag),
|
||||
|
||||
attributes: (),
|
||||
children: (),
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ use crate::{
|
||||
use wasm_bindgen::JsValue;
|
||||
use web_sys::Element;
|
||||
|
||||
/// Extends an HTML element, allowing you to add attributes and children to the
|
||||
/// element's built state at runtime, with a similar API to how they
|
||||
/// Extends the [`Element`](Renderer::Element) type of a [`Renderer`], allowing you to add
|
||||
/// attributes and children to the element's built state at runtime, with a similar API to how they
|
||||
/// can be added to the static view tree at compile time.
|
||||
///
|
||||
/// ```rust,ignore
|
||||
|
||||
@@ -25,11 +25,10 @@ macro_rules! html_element_inner {
|
||||
|
||||
{
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
tag: $struct_name,
|
||||
attributes: (),
|
||||
children: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,17 +55,10 @@ macro_rules! html_element_inner {
|
||||
At: NextTuple,
|
||||
<At as NextTuple>::Output<Attr<$crate::html::attribute::[<$attr:camel>], V>>: Attribute,
|
||||
{
|
||||
let HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
children,
|
||||
attributes
|
||||
} = self;
|
||||
let HtmlElement { tag, children, attributes } = self;
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
|
||||
children,
|
||||
attributes: attributes.next_tuple($crate::html::attribute::$attr(value)),
|
||||
}
|
||||
@@ -126,16 +118,14 @@ macro_rules! html_self_closing_elements {
|
||||
paste::paste! {
|
||||
$(
|
||||
#[$meta]
|
||||
#[track_caller]
|
||||
pub fn $tag() -> HtmlElement<[<$tag:camel>], (), ()>
|
||||
where
|
||||
|
||||
{
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
attributes: (),
|
||||
children: (),
|
||||
|
||||
tag: [<$tag:camel>],
|
||||
}
|
||||
}
|
||||
@@ -148,6 +138,7 @@ macro_rules! html_self_closing_elements {
|
||||
impl<At> HtmlElement<[<$tag:camel>], At, ()>
|
||||
where
|
||||
At: Attribute,
|
||||
|
||||
{
|
||||
$(
|
||||
#[doc = concat!("The [`", stringify!($attr), "`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/", stringify!($tag), "#", stringify!($attr) ,") attribute on `<", stringify!($tag), ">`.")]
|
||||
@@ -160,18 +151,13 @@ macro_rules! html_self_closing_elements {
|
||||
V: AttributeValue,
|
||||
At: NextTuple,
|
||||
<At as NextTuple>::Output<Attr<$crate::html::attribute::[<$attr:camel>], V>>: Attribute,
|
||||
|
||||
{
|
||||
let HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
children,
|
||||
attributes,
|
||||
let HtmlElement { tag, children, attributes,
|
||||
} = self;
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
|
||||
children,
|
||||
attributes: attributes.next_tuple($crate::html::attribute::$attr(value)),
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#[cfg(debug_assertions)]
|
||||
use crate::hydration::set_currently_hydrating;
|
||||
use crate::{
|
||||
html::attribute::Attribute,
|
||||
hydration::{failed_to_cast_element, Cursor},
|
||||
hydration::Cursor,
|
||||
renderer::{CastFrom, Rndr},
|
||||
ssr::StreamBuilder,
|
||||
view::{
|
||||
@@ -26,14 +24,10 @@ pub use custom::*;
|
||||
pub use element_ext::*;
|
||||
pub use elements::*;
|
||||
pub use inner_html::*;
|
||||
#[cfg(debug_assertions)]
|
||||
use std::panic::Location;
|
||||
|
||||
/// The typed representation of an HTML element.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct HtmlElement<E, At, Ch> {
|
||||
#[cfg(debug_assertions)]
|
||||
pub(crate) defined_at: &'static Location<'static>,
|
||||
pub(crate) tag: E,
|
||||
pub(crate) attributes: At,
|
||||
pub(crate) children: Ch,
|
||||
@@ -42,9 +36,8 @@ pub struct HtmlElement<E, At, Ch> {
|
||||
impl<E: Clone, At: Clone, Ch: Clone> Clone for HtmlElement<E, At, Ch> {
|
||||
fn clone(&self) -> Self {
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: self.defined_at,
|
||||
tag: self.tag.clone(),
|
||||
|
||||
attributes: self.attributes.clone(),
|
||||
children: self.children.clone(),
|
||||
}
|
||||
@@ -82,16 +75,14 @@ where
|
||||
|
||||
fn child(self, child: NewChild) -> Self::Output {
|
||||
let HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
|
||||
attributes,
|
||||
children,
|
||||
} = self;
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
|
||||
attributes,
|
||||
children: children.next_tuple(child.into_render()),
|
||||
}
|
||||
@@ -112,15 +103,11 @@ where
|
||||
attr: NewAttr,
|
||||
) -> Self::Output<NewAttr> {
|
||||
let HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
attributes,
|
||||
children,
|
||||
} = self;
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
attributes: attributes.add_any_attr(attr),
|
||||
children,
|
||||
@@ -242,9 +229,8 @@ where
|
||||
let (attributes, children) =
|
||||
join(self.attributes.resolve(), self.children.resolve()).await;
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: self.defined_at,
|
||||
tag: self.tag,
|
||||
|
||||
attributes,
|
||||
children,
|
||||
}
|
||||
@@ -350,11 +336,6 @@ where
|
||||
cursor: &Cursor,
|
||||
position: &PositionState,
|
||||
) -> Self::State {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
set_currently_hydrating(Some(self.defined_at));
|
||||
}
|
||||
|
||||
// non-Static custom elements need special support in templates
|
||||
// because they haven't been inserted type-wise
|
||||
if E::TAG.is_empty() && !FROM_SERVER {
|
||||
@@ -368,9 +349,7 @@ where
|
||||
cursor.sibling();
|
||||
}
|
||||
let el = crate::renderer::types::Element::cast_from(cursor.current())
|
||||
.unwrap_or_else(|| {
|
||||
failed_to_cast_element(E::TAG, cursor.current())
|
||||
});
|
||||
.unwrap();
|
||||
|
||||
let attrs = self.attributes.hydrate::<FROM_SERVER>(&el);
|
||||
|
||||
|
||||
@@ -128,9 +128,7 @@ where
|
||||
}
|
||||
|
||||
/// Any type that can be added to the `style` attribute or set as a style in
|
||||
/// the [`CssStyleDeclaration`](web_sys::CssStyleDeclaration).
|
||||
///
|
||||
/// This could be a plain string, or a property name-value pair.
|
||||
/// the [`CssStyleDeclaration`]. This could be a plain string, or a property name-value pair.
|
||||
pub trait IntoStyle: Send {
|
||||
/// The type after all async data have resolved.
|
||||
type AsyncOutput: IntoStyle;
|
||||
|
||||
@@ -2,10 +2,7 @@ use crate::{
|
||||
renderer::{CastFrom, Rndr},
|
||||
view::{Position, PositionState},
|
||||
};
|
||||
#[cfg(debug_assertions)]
|
||||
use std::cell::Cell;
|
||||
use std::{cell::RefCell, panic::Location, rc::Rc};
|
||||
use web_sys::{Comment, Element, Node, Text};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
/// Hydration works by walking over the DOM, adding interactivity as needed.
|
||||
///
|
||||
@@ -98,121 +95,13 @@ where
|
||||
}
|
||||
let marker = self.current();
|
||||
position.set(Position::NextChild);
|
||||
crate::renderer::types::Placeholder::cast_from(marker.clone())
|
||||
.unwrap_or_else(|| failed_to_cast_marker_node(marker))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
thread_local! {
|
||||
static CURRENTLY_HYDRATING: Cell<Option<&'static Location<'static>>> = const { Cell::new(None) };
|
||||
}
|
||||
|
||||
pub(crate) fn set_currently_hydrating(
|
||||
location: Option<&'static Location<'static>>,
|
||||
) {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
CURRENTLY_HYDRATING.set(location);
|
||||
}
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
_ = location;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn failed_to_cast_element(tag_name: &str, node: Node) -> Element {
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
_ = node;
|
||||
unreachable!();
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let hydrating = CURRENTLY_HYDRATING
|
||||
.take()
|
||||
.map(|n| n.to_string())
|
||||
.unwrap_or_else(|| "{unknown}".to_string());
|
||||
web_sys::console::error_3(
|
||||
&wasm_bindgen::JsValue::from_str(&format!(
|
||||
"A hydration error occurred while trying to hydrate an \
|
||||
element defined at {hydrating}.\n\nThe framework expected an \
|
||||
HTML <{tag_name}> element, but found this instead: ",
|
||||
)),
|
||||
&node,
|
||||
&wasm_bindgen::JsValue::from_str(
|
||||
"\n\nThe hydration mismatch may have occurred slightly \
|
||||
earlier, but this is the first time the framework found a \
|
||||
node of an unexpected type.",
|
||||
),
|
||||
);
|
||||
panic!(
|
||||
"Unrecoverable hydration error. Please read the error message \
|
||||
directly above this for more details."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn failed_to_cast_marker_node(node: Node) -> Comment {
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
_ = node;
|
||||
unreachable!();
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let hydrating = CURRENTLY_HYDRATING
|
||||
.take()
|
||||
.map(|n| n.to_string())
|
||||
.unwrap_or_else(|| "{unknown}".to_string());
|
||||
web_sys::console::error_3(
|
||||
&wasm_bindgen::JsValue::from_str(&format!(
|
||||
"A hydration error occurred while trying to hydrate an \
|
||||
element defined at {hydrating}.\n\nThe framework expected a \
|
||||
marker node, but found this instead: ",
|
||||
)),
|
||||
&node,
|
||||
&wasm_bindgen::JsValue::from_str(
|
||||
"\n\nThe hydration mismatch may have occurred slightly \
|
||||
earlier, but this is the first time the framework found a \
|
||||
node of an unexpected type.",
|
||||
),
|
||||
);
|
||||
panic!(
|
||||
"Unrecoverable hydration error. Please read the error message \
|
||||
directly above this for more details."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn failed_to_cast_text_node(node: Node) -> Text {
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
_ = node;
|
||||
unreachable!();
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let hydrating = CURRENTLY_HYDRATING
|
||||
.take()
|
||||
.map(|n| n.to_string())
|
||||
.unwrap_or_else(|| "{unknown}".to_string());
|
||||
web_sys::console::error_3(
|
||||
&wasm_bindgen::JsValue::from_str(&format!(
|
||||
"A hydration error occurred while trying to hydrate an \
|
||||
element defined at {hydrating}.\n\nThe framework expected a \
|
||||
text node, but found this instead: ",
|
||||
)),
|
||||
&node,
|
||||
&wasm_bindgen::JsValue::from_str(
|
||||
"\n\nThe hydration mismatch may have occurred slightly \
|
||||
earlier, but this is the first time the framework found a \
|
||||
node of an unexpected type.",
|
||||
),
|
||||
);
|
||||
panic!(
|
||||
"Unrecoverable hydration error. Please read the error message \
|
||||
directly above this for more details."
|
||||
);
|
||||
crate::renderer::types::Placeholder::cast_from(marker)
|
||||
.expect("could not convert current node into marker node")
|
||||
/*let marker2 = marker.clone();
|
||||
Rndr::Placeholder::cast_from(marker).unwrap_or_else(|| {
|
||||
crate::dom::log("expecting to find a marker. instead, found");
|
||||
Rndr::log_node(&marker2);
|
||||
panic!("oops.");
|
||||
})*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,17 +22,10 @@ macro_rules! mathml_global {
|
||||
At: NextTuple,
|
||||
<At as NextTuple>::Output<Attr<$crate::html::attribute::[<$attr:camel>], V>>: Attribute,
|
||||
{
|
||||
let HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
children,
|
||||
attributes
|
||||
} = self;
|
||||
let HtmlElement { tag, children, attributes } = self;
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
|
||||
children,
|
||||
attributes: attributes.next_tuple($crate::html::attribute::$attr(value)),
|
||||
}
|
||||
@@ -53,11 +46,10 @@ macro_rules! mathml_elements {
|
||||
|
||||
{
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
tag: [<$tag:camel>],
|
||||
attributes: (),
|
||||
children: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,17 +84,10 @@ macro_rules! mathml_elements {
|
||||
At: NextTuple,
|
||||
<At as NextTuple>::Output<Attr<$crate::html::attribute::[<$attr:camel>], V>>: Attribute,
|
||||
{
|
||||
let HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
children,
|
||||
attributes
|
||||
} = self;
|
||||
let HtmlElement { tag, children, attributes } = self;
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at,
|
||||
tag,
|
||||
|
||||
children,
|
||||
attributes: attributes.next_tuple($crate::html::attribute::$attr(value)),
|
||||
}
|
||||
|
||||
@@ -519,7 +519,6 @@ mod stable {
|
||||
|
||||
macro_rules! class_signal_arena {
|
||||
($sig:ident) => {
|
||||
#[allow(deprecated)]
|
||||
impl<C, S> IntoClass for $sig<C, S>
|
||||
where
|
||||
$sig<C, S>: Get<Value = C>,
|
||||
@@ -589,7 +588,6 @@ mod stable {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<S> IntoClass for (&'static str, $sig<bool, S>)
|
||||
where
|
||||
$sig<bool, S>: Get<Value = bool>,
|
||||
@@ -827,14 +825,12 @@ mod stable {
|
||||
|
||||
use super::RenderEffect;
|
||||
use crate::html::class::IntoClass;
|
||||
#[allow(deprecated)]
|
||||
use reactive_graph::wrappers::read::MaybeSignal;
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, Memo},
|
||||
owner::Storage,
|
||||
signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
|
||||
traits::Get,
|
||||
wrappers::read::{ArcSignal, Signal},
|
||||
wrappers::read::{ArcSignal, MaybeSignal, Signal},
|
||||
};
|
||||
|
||||
class_signal_arena!(RwSignal);
|
||||
|
||||
@@ -89,15 +89,13 @@ where
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
mod stable {
|
||||
use crate::html::element::InnerHtmlValue;
|
||||
#[allow(deprecated)]
|
||||
use reactive_graph::wrappers::read::MaybeSignal;
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, Memo},
|
||||
effect::RenderEffect,
|
||||
owner::Storage,
|
||||
signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
|
||||
traits::Get,
|
||||
wrappers::read::{ArcSignal, Signal},
|
||||
wrappers::read::{ArcSignal, MaybeSignal, Signal},
|
||||
};
|
||||
|
||||
macro_rules! inner_html_signal {
|
||||
@@ -161,7 +159,6 @@ mod stable {
|
||||
|
||||
macro_rules! inner_html_signal_arena {
|
||||
($sig:ident) => {
|
||||
#[allow(deprecated)]
|
||||
impl<V, S> InnerHtmlValue for $sig<V, S>
|
||||
where
|
||||
$sig<V, S>: Get<Value = V>,
|
||||
|
||||
@@ -507,15 +507,13 @@ mod stable {
|
||||
RenderHtml,
|
||||
},
|
||||
};
|
||||
#[allow(deprecated)]
|
||||
use reactive_graph::wrappers::read::MaybeSignal;
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, Memo},
|
||||
effect::RenderEffect,
|
||||
owner::Storage,
|
||||
signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
|
||||
traits::Get,
|
||||
wrappers::read::{ArcSignal, Signal},
|
||||
wrappers::read::{ArcSignal, MaybeSignal, Signal},
|
||||
};
|
||||
|
||||
macro_rules! signal_impl {
|
||||
@@ -685,7 +683,6 @@ mod stable {
|
||||
|
||||
macro_rules! signal_impl_arena {
|
||||
($sig:ident $dry_resolve:literal) => {
|
||||
#[allow(deprecated)]
|
||||
impl<V, S> Render for $sig<V, S>
|
||||
where
|
||||
$sig<V, S>: Get<Value = V>,
|
||||
@@ -710,7 +707,6 @@ mod stable {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<V, S> AddAnyAttr for $sig<V, S>
|
||||
where
|
||||
$sig<V, S>: Get<Value = V>,
|
||||
@@ -732,7 +728,6 @@ mod stable {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<V, S> RenderHtml for $sig<V, S>
|
||||
where
|
||||
$sig<V, S>: Get<Value = V>,
|
||||
@@ -798,7 +793,6 @@ mod stable {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<V, S> AttributeValue for $sig<V, S>
|
||||
where
|
||||
$sig<V, S>: Get<Value = V>,
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
use crate::html::{element::ElementType, node_ref::NodeRefContainer};
|
||||
use reactive_graph::{
|
||||
effect::Effect,
|
||||
signal::{
|
||||
guards::{Derefable, ReadGuard},
|
||||
RwSignal,
|
||||
},
|
||||
traits::{
|
||||
DefinedAt, Get, Notify, ReadUntracked, Set, Track, UntrackableGuard,
|
||||
Write,
|
||||
},
|
||||
traits::{DefinedAt, ReadUntracked, Set, Track},
|
||||
};
|
||||
use send_wrapper::SendWrapper;
|
||||
use std::{cell::Cell, ops::DerefMut};
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
/// A reactive reference to a DOM node that can be used with the `node_ref` attribute.
|
||||
@@ -31,25 +26,6 @@ where
|
||||
pub fn new() -> Self {
|
||||
Self(RwSignal::new(None))
|
||||
}
|
||||
|
||||
/// Runs the provided closure when the `NodeRef` has been connected
|
||||
/// with its element.
|
||||
#[inline(always)]
|
||||
pub fn on_load<F>(self, f: F)
|
||||
where
|
||||
E: 'static,
|
||||
F: FnOnce(E::Output) + 'static,
|
||||
E: ElementType,
|
||||
E::Output: JsCast + Clone + 'static,
|
||||
{
|
||||
let f = Cell::new(Some(f));
|
||||
|
||||
Effect::new(move |_| {
|
||||
if let Some(node_ref) = self.get() {
|
||||
f.take().unwrap()(node_ref);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Default for NodeRef<E>
|
||||
@@ -102,34 +78,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Notify for NodeRef<E>
|
||||
where
|
||||
E: ElementType,
|
||||
E::Output: JsCast + Clone + 'static,
|
||||
{
|
||||
fn notify(&self) {
|
||||
self.0.notify();
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Write for NodeRef<E>
|
||||
where
|
||||
E: ElementType,
|
||||
E::Output: JsCast + Clone + 'static,
|
||||
{
|
||||
type Value = Option<SendWrapper<E::Output>>;
|
||||
|
||||
fn try_write(&self) -> Option<impl UntrackableGuard<Target = Self::Value>> {
|
||||
self.0.try_write()
|
||||
}
|
||||
|
||||
fn try_write_untracked(
|
||||
&self,
|
||||
) -> Option<impl DerefMut<Target = Self::Value>> {
|
||||
self.0.try_write_untracked()
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> ReadUntracked for NodeRef<E>
|
||||
where
|
||||
E: ElementType,
|
||||
|
||||
@@ -82,15 +82,13 @@ where
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
mod stable {
|
||||
use crate::html::property::IntoProperty;
|
||||
#[allow(deprecated)]
|
||||
use reactive_graph::wrappers::read::MaybeSignal;
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, Memo},
|
||||
effect::RenderEffect,
|
||||
owner::Storage,
|
||||
signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
|
||||
traits::Get,
|
||||
wrappers::read::{ArcSignal, Signal},
|
||||
wrappers::read::{ArcSignal, MaybeSignal, Signal},
|
||||
};
|
||||
|
||||
macro_rules! property_signal {
|
||||
@@ -138,7 +136,6 @@ mod stable {
|
||||
|
||||
macro_rules! property_signal_arena {
|
||||
($sig:ident) => {
|
||||
#[allow(deprecated)]
|
||||
impl<V, S> IntoProperty for $sig<V, S>
|
||||
where
|
||||
$sig<V, S>: Get<Value = V>,
|
||||
|
||||
@@ -393,7 +393,6 @@ mod stable {
|
||||
|
||||
macro_rules! style_signal_arena {
|
||||
($sig:ident) => {
|
||||
#[allow(deprecated)]
|
||||
impl<C, S> IntoStyle for $sig<C, S>
|
||||
where
|
||||
$sig<C, S>: Get<Value = C>,
|
||||
@@ -459,7 +458,6 @@ mod stable {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<S, St> IntoStyle for (&'static str, $sig<S, St>)
|
||||
where
|
||||
$sig<S, St>: Get<Value = S>,
|
||||
@@ -536,14 +534,12 @@ mod stable {
|
||||
|
||||
use super::RenderEffect;
|
||||
use crate::html::style::IntoStyle;
|
||||
#[allow(deprecated)]
|
||||
use reactive_graph::wrappers::read::MaybeSignal;
|
||||
use reactive_graph::{
|
||||
computed::{ArcMemo, Memo},
|
||||
owner::Storage,
|
||||
signal::{ArcReadSignal, ArcRwSignal, ReadSignal, RwSignal},
|
||||
traits::Get,
|
||||
wrappers::read::{ArcSignal, Signal},
|
||||
wrappers::read::{ArcSignal, MaybeSignal, Signal},
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
//! See [`Renderer`](crate::renderer::Renderer) and [`Rndr`](crate::renderer::Rndr) for additional information.
|
||||
//! See [`Renderer`](super::Renderer) and [`Rndr`](super::Rndr) for additional information.
|
||||
|
||||
use super::{CastFrom, RemoveEventHandler};
|
||||
use crate::{
|
||||
@@ -15,7 +15,7 @@ use std::{any::TypeId, borrow::Cow, cell::RefCell};
|
||||
use wasm_bindgen::{intern, prelude::Closure, JsCast, JsValue};
|
||||
use web_sys::{Comment, HtmlTemplateElement};
|
||||
|
||||
/// A [`Renderer`](crate::renderer::Renderer) that uses `web-sys` to manipulate DOM elements in the browser.
|
||||
/// A [`Renderer`] that uses `web-sys` to manipulate DOM elements in the browser.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Dom;
|
||||
|
||||
|
||||
@@ -14,8 +14,7 @@ pub mod dom;
|
||||
/// applications, so this "generic rendering" approach was removed before 0.7.0 release.
|
||||
///
|
||||
/// It is possible that we will try a different approach to achieve the same functionality in the
|
||||
/// future, so to the extent possible the rest of the crate tries to stick to using
|
||||
/// [`Renderer`].
|
||||
/// future, so to the extent possible the rest of the crate tries to stick to using [`Renderer`]
|
||||
/// methods rather than directly manipulating the DOM inline.
|
||||
pub type Rndr = dom::Dom;
|
||||
|
||||
|
||||
@@ -14,16 +14,15 @@ macro_rules! svg_elements {
|
||||
/// An SVG element.
|
||||
// `tag()` function
|
||||
#[allow(non_snake_case)]
|
||||
#[track_caller]
|
||||
pub fn $tag() -> HtmlElement<[<$tag:camel>], (), ()>
|
||||
where
|
||||
|
||||
{
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
tag: [<$tag:camel>],
|
||||
attributes: (),
|
||||
children: (),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,12 +153,9 @@ svg_elements![
|
||||
|
||||
/// An SVG element.
|
||||
#[allow(non_snake_case)]
|
||||
#[track_caller]
|
||||
pub fn r#use() -> HtmlElement<Use, (), ()>
|
||||
where {
|
||||
HtmlElement {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: std::panic::Location::caller(),
|
||||
tag: Use,
|
||||
attributes: (),
|
||||
children: (),
|
||||
|
||||
@@ -29,6 +29,9 @@ pub mod template;
|
||||
pub mod tuples;
|
||||
|
||||
/// The `Render` trait allows rendering something as part of the user interface.
|
||||
///
|
||||
/// It is generic over the renderer itself, as long as that implements the [`Renderer`]
|
||||
/// trait.
|
||||
pub trait Render: Sized {
|
||||
/// The “view state” for this type, which can be retained between updates.
|
||||
///
|
||||
|
||||
@@ -100,8 +100,8 @@ macro_rules! render_primitive {
|
||||
}
|
||||
|
||||
let node = cursor.current();
|
||||
let node = crate::renderer::types::Text::cast_from(node.clone())
|
||||
.unwrap_or_else(|| crate::hydration::failed_to_cast_text_node(node));
|
||||
let node = crate::renderer::types::Text::cast_from(node)
|
||||
.expect("couldn't cast text node from node");
|
||||
|
||||
if !FROM_SERVER {
|
||||
Rndr::set_text(&node, &self.to_string());
|
||||
|
||||
@@ -90,10 +90,8 @@ impl RenderHtml for &str {
|
||||
}
|
||||
|
||||
let node = cursor.current();
|
||||
let node = crate::renderer::types::Text::cast_from(node.clone())
|
||||
.unwrap_or_else(|| {
|
||||
crate::hydration::failed_to_cast_text_node(node)
|
||||
});
|
||||
let node = crate::renderer::types::Text::cast_from(node)
|
||||
.expect("couldn't cast text node from node");
|
||||
|
||||
if !FROM_SERVER {
|
||||
Rndr::set_text(&node, self);
|
||||
|
||||
Reference in New Issue
Block a user