mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-28 09:02:37 -05:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10db2f83eb | ||
|
|
357f3be393 | ||
|
|
a1f5d6f79f | ||
|
|
34ecd2d541 | ||
|
|
df38b075d8 | ||
|
|
46233e3097 | ||
|
|
46f6d9ae26 | ||
|
|
8264d478e4 | ||
|
|
9c54da304e | ||
|
|
1c002a2df8 | ||
|
|
6e4dac91bf | ||
|
|
6493b0b359 | ||
|
|
d58042b7ba | ||
|
|
7a5b27ad20 | ||
|
|
78d0dbdfa2 | ||
|
|
1c30a4c131 | ||
|
|
b91429d4f0 | ||
|
|
6663fddf76 | ||
|
|
28af33d511 | ||
|
|
5a3413d3b3 | ||
|
|
702d2e247b | ||
|
|
71f698f322 | ||
|
|
8d4776bf5f | ||
|
|
65798e430f | ||
|
|
d46d1a4fab | ||
|
|
f9533ab75b | ||
|
|
d08f8822c0 | ||
|
|
7357839efb |
5
.github/workflows/autofix.yml
vendored
5
.github/workflows/autofix.yml
vendored
@@ -13,6 +13,7 @@ concurrency:
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUST_BACKTRACE: 1
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
jobs:
|
||||
autofix:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -21,6 +22,10 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with: {toolchain: nightly, components: "rustfmt, clippy", target: "wasm32-unknown-unknown", rustflags: ""}
|
||||
- name: Install Glib
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libglib2.0-dev
|
||||
- name: Install jq
|
||||
run: sudo apt-get install jq
|
||||
- run: |
|
||||
|
||||
6
.github/workflows/ci-semver.yml
vendored
6
.github/workflows/ci-semver.yml
vendored
@@ -8,6 +8,8 @@ on:
|
||||
branches:
|
||||
- main
|
||||
- leptos_0.6
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
jobs:
|
||||
get-leptos-changed:
|
||||
uses: ./.github/workflows/get-leptos-changed.yml
|
||||
@@ -17,6 +19,10 @@ jobs:
|
||||
name: Run semver check (nightly-2024-08-01)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Glib
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libglib2.0-dev
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Semver Checks
|
||||
|
||||
5
.github/workflows/run-cargo-make-task.yml
vendored
5
.github/workflows/run-cargo-make-task.yml
vendored
@@ -14,6 +14,7 @@ on:
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
jobs:
|
||||
test:
|
||||
name: Run ${{ inputs.cargo_make_task }} (${{ inputs.toolchain }})
|
||||
@@ -33,6 +34,10 @@ jobs:
|
||||
echo "Disk space after cleanup:"
|
||||
df -h
|
||||
# Setup environment
|
||||
- name: Install Glib
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libglib2.0-dev
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Rust
|
||||
uses: dtolnay/rust-toolchain@master
|
||||
|
||||
122
Cargo.lock
generated
122
Cargo.lock
generated
@@ -278,7 +278,7 @@ dependencies = [
|
||||
"async-executor",
|
||||
"futures",
|
||||
"glib",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.9",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"wasm-bindgen-futures",
|
||||
@@ -603,9 +603,9 @@ checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.4"
|
||||
version = "1.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf"
|
||||
checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@@ -918,7 +918,7 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "either_of"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
@@ -1173,9 +1173,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "gio-sys"
|
||||
version = "0.20.7"
|
||||
version = "0.20.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c16e55573888c1802b8fd169201cadee4e3fd4c889bfb23c9fa652a7945335da"
|
||||
checksum = "8446d9b475730ebef81802c1738d972db42fde1c5a36a627ebc4d665fc87db04"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
@@ -1484,9 +1484,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.27.3"
|
||||
version = "0.27.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333"
|
||||
checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"http 1.2.0",
|
||||
@@ -1710,9 +1710,12 @@ checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8"
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.15"
|
||||
version = "0.3.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767"
|
||||
checksum = "e5d80fade88dd420ce0d9ab6f7c58ef2272dde38db874657950f827d4982c817"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
@@ -1768,13 +1771,14 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "leptos"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"base64",
|
||||
"cfg-if",
|
||||
"either_of",
|
||||
"futures",
|
||||
"getrandom",
|
||||
"hydration_context",
|
||||
"leptos-spin-macro",
|
||||
"leptos_config",
|
||||
@@ -1795,7 +1799,7 @@ dependencies = [
|
||||
"server_fn",
|
||||
"slotmap",
|
||||
"tachys",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.9",
|
||||
"throw_error",
|
||||
"tracing",
|
||||
"typed-builder",
|
||||
@@ -1818,7 +1822,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_actix"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"actix-files",
|
||||
"actix-http",
|
||||
@@ -1843,7 +1847,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_axum"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"axum",
|
||||
@@ -1866,21 +1870,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_config"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"config",
|
||||
"regex",
|
||||
"serde",
|
||||
"temp-env",
|
||||
"tempfile",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.9",
|
||||
"tokio",
|
||||
"typed-builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "leptos_dom"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"leptos",
|
||||
@@ -1897,7 +1901,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_hot_reload"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"camino",
|
||||
@@ -1913,7 +1917,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_integration_utils"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"hydration_context",
|
||||
@@ -1926,7 +1930,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_macro"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"attribute-derive",
|
||||
"cfg-if",
|
||||
@@ -1944,7 +1948,7 @@ dependencies = [
|
||||
"rstml",
|
||||
"serde",
|
||||
"server_fn",
|
||||
"server_fn_macro 0.7.1",
|
||||
"server_fn_macro 0.7.3",
|
||||
"syn 2.0.90",
|
||||
"tracing",
|
||||
"trybuild",
|
||||
@@ -1954,7 +1958,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_meta"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"indexmap",
|
||||
@@ -1969,7 +1973,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_router"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"either_of",
|
||||
@@ -1984,7 +1988,7 @@ dependencies = [
|
||||
"reactive_graph",
|
||||
"send_wrapper",
|
||||
"tachys",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.9",
|
||||
"tracing",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
@@ -1993,7 +1997,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_router_macro"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"leptos_router",
|
||||
"proc-macro-error2",
|
||||
@@ -2003,7 +2007,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "leptos_server"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"base64",
|
||||
@@ -2024,9 +2028,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.168"
|
||||
version = "0.2.169"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
|
||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||
|
||||
[[package]]
|
||||
name = "linear-map"
|
||||
@@ -2166,9 +2170,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.0"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
|
||||
checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
@@ -2280,9 +2284,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.5"
|
||||
version = "0.36.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -2293,7 +2297,7 @@ version = "0.2.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2614,7 +2618,7 @@ dependencies = [
|
||||
"rustc-hash 2.1.0",
|
||||
"rustls",
|
||||
"socket2",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.9",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
@@ -2633,7 +2637,7 @@ dependencies = [
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"slab",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.9",
|
||||
"tinyvec",
|
||||
"tracing",
|
||||
"web-time",
|
||||
@@ -2641,9 +2645,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quinn-udp"
|
||||
version = "0.5.8"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52cd4b1eff68bf27940dd39811292c49e007f4d0b4c357358dc9b0197be6b527"
|
||||
checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
@@ -2731,7 +2735,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reactive_graph"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"async-lock",
|
||||
@@ -2744,7 +2748,7 @@ dependencies = [
|
||||
"send_wrapper",
|
||||
"serde",
|
||||
"slotmap",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.9",
|
||||
"tokio",
|
||||
"tokio-test",
|
||||
"tracing",
|
||||
@@ -2753,7 +2757,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reactive_stores"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"guardian",
|
||||
@@ -3139,9 +3143,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "security-framework-sys"
|
||||
version = "2.12.1"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2"
|
||||
checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
@@ -3216,9 +3220,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.133"
|
||||
version = "1.0.134"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
|
||||
checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -3270,7 +3274,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "server_fn"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"axum",
|
||||
@@ -3298,7 +3302,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_qs",
|
||||
"server_fn_macro_default",
|
||||
"thiserror 2.0.7",
|
||||
"thiserror 2.0.9",
|
||||
"throw_error",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
@@ -3326,7 +3330,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "server_fn_macro"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"const_format",
|
||||
"convert_case 0.6.0",
|
||||
@@ -3338,9 +3342,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "server_fn_macro_default"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
dependencies = [
|
||||
"server_fn_macro 0.7.1",
|
||||
"server_fn_macro 0.7.3",
|
||||
"syn 2.0.90",
|
||||
]
|
||||
|
||||
@@ -3535,7 +3539,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tachys"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"any_spawner",
|
||||
"const_str_slice_concat",
|
||||
@@ -3629,11 +3633,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.7"
|
||||
version = "2.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767"
|
||||
checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc"
|
||||
dependencies = [
|
||||
"thiserror-impl 2.0.7",
|
||||
"thiserror-impl 2.0.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3649,9 +3653,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.7"
|
||||
version = "2.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36"
|
||||
checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3708,9 +3712,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.8.0"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938"
|
||||
checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
@@ -4352,9 +4356,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "xxhash-rust"
|
||||
version = "0.8.12"
|
||||
version = "0.8.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984"
|
||||
checksum = "a08fd76779ae1883bbf1e46c2c46a75a0c4e37c445e68a24b01479d438f26ae6"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
|
||||
33
Cargo.toml
33
Cargo.toml
@@ -40,7 +40,7 @@ members = [
|
||||
exclude = ["benchmarks", "examples", "projects"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
edition = "2021"
|
||||
rust-version = "1.76"
|
||||
|
||||
@@ -50,25 +50,25 @@ any_spawner = { path = "./any_spawner/", version = "0.2.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.1" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.7.1" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.7.1" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.7.1" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.7.1" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.7.1" }
|
||||
leptos_router = { path = "./router", version = "0.7.1" }
|
||||
leptos_router_macro = { path = "./router_macro", version = "0.7.1" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.7.1" }
|
||||
leptos_meta = { path = "./meta", version = "0.7.1" }
|
||||
leptos = { path = "./leptos", version = "0.7.3" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.7.3" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.7.3" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.7.3" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.7.3" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.7.3" }
|
||||
leptos_router = { path = "./router", version = "0.7.3" }
|
||||
leptos_router_macro = { path = "./router_macro", version = "0.7.3" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.7.3" }
|
||||
leptos_meta = { path = "./meta", version = "0.7.3" }
|
||||
next_tuple = { path = "./next_tuple", version = "0.1.0" }
|
||||
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.1" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.7.1" }
|
||||
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.7.1" }
|
||||
server_fn = { path = "./server_fn", version = "0.7.3" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.7.3" }
|
||||
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.7.3" }
|
||||
tachys = { path = "./tachys", version = "0.1.0" }
|
||||
|
||||
[profile.release]
|
||||
@@ -80,4 +80,7 @@ opt-level = 'z'
|
||||
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
|
||||
|
||||
[workspace.lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)', 'cfg(erase_components)'] }
|
||||
unexpected_cfgs = { level = "warn", check-cfg = [
|
||||
'cfg(leptos_debuginfo)',
|
||||
'cfg(erase_components)',
|
||||
] }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "either_of"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
//! - `default`: supports running in a typical native Tokio/Axum environment
|
||||
//! - `wasm`: with `default-features = false`, supports running in a JS Fetch-based
|
||||
//! environment
|
||||
//! - `islands`: activates Leptos [islands mode](https://leptos-rs.github.io/leptos/islands.html)
|
||||
//!
|
||||
//! ### Important Note
|
||||
//! Prior to 0.5, using `default-features = false` on `leptos_axum` simply did nothing. Now, it actively
|
||||
@@ -1994,12 +1993,12 @@ pub fn file_and_error_handler<S, IV>(
|
||||
+ 'static
|
||||
where
|
||||
IV: IntoView + 'static,
|
||||
S: Send + 'static,
|
||||
S: Send + Sync + Clone + 'static,
|
||||
LeptosOptions: FromRef<S>,
|
||||
{
|
||||
move |uri: Uri, State(options): State<S>, req: Request<Body>| {
|
||||
move |uri: Uri, State(state): State<S>, req: Request<Body>| {
|
||||
Box::pin(async move {
|
||||
let options = LeptosOptions::from_ref(&options);
|
||||
let options = LeptosOptions::from_ref(&state);
|
||||
let res = get_static_file(uri, &options.site_root, req.headers());
|
||||
let res = res.await.unwrap();
|
||||
|
||||
@@ -2007,7 +2006,9 @@ where
|
||||
res.into_response()
|
||||
} else {
|
||||
let mut res = handle_response_inner(
|
||||
|| {},
|
||||
move || {
|
||||
provide_context(state.clone());
|
||||
},
|
||||
move || shell(options),
|
||||
req,
|
||||
|app, chunks| {
|
||||
|
||||
@@ -11,7 +11,10 @@ edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
throw_error = { workspace = true }
|
||||
any_spawner = { workspace = true, features = ["wasm-bindgen", "futures-executor"] }
|
||||
any_spawner = { workspace = true, features = [
|
||||
"wasm-bindgen",
|
||||
"futures-executor",
|
||||
] }
|
||||
base64 = { version = "0.22.1", optional = true }
|
||||
cfg-if = "1.0"
|
||||
hydration_context = { workspace = true }
|
||||
@@ -28,7 +31,11 @@ paste = "1.0"
|
||||
rand = { version = "0.8.5", optional = true }
|
||||
reactive_graph = { workspace = true, features = ["serde"] }
|
||||
rustc-hash = "2.0"
|
||||
tachys = { workspace = true, features = ["reactive_graph", "reactive_stores", "oco"] }
|
||||
tachys = { workspace = true, features = [
|
||||
"reactive_graph",
|
||||
"reactive_stores",
|
||||
"oco",
|
||||
] }
|
||||
thiserror = "2.0"
|
||||
tracing = { version = "0.1.41", optional = true }
|
||||
typed-builder = "0.20.0"
|
||||
@@ -50,20 +57,22 @@ serde_qs = "0.13.0"
|
||||
slotmap = "1.0"
|
||||
futures = "0.3.31"
|
||||
send_wrapper = "0.6.0"
|
||||
getrandom = { version = "0.2", features = ["js"], optional = true }
|
||||
|
||||
[features]
|
||||
hydration = [
|
||||
"reactive_graph/hydration",
|
||||
"leptos_server/hydration",
|
||||
"hydration_context/browser",
|
||||
"leptos_dom/hydration"
|
||||
"leptos_dom/hydration",
|
||||
]
|
||||
csr = ["leptos_macro/csr", "reactive_graph/effects"]
|
||||
csr = ["leptos_macro/csr", "reactive_graph/effects", "dep:getrandom"]
|
||||
hydrate = [
|
||||
"leptos_macro/hydrate",
|
||||
"hydration",
|
||||
"tachys/hydrate",
|
||||
"reactive_graph/effects",
|
||||
"dep:getrandom",
|
||||
]
|
||||
default-tls = ["server_fn/default-tls"]
|
||||
rustls = ["server_fn/rustls"]
|
||||
@@ -89,7 +98,7 @@ spin = ["leptos-spin-macro"]
|
||||
islands = ["leptos_macro/islands", "dep:serde_json"]
|
||||
trace-component-props = [
|
||||
"leptos_macro/trace-component-props",
|
||||
"leptos_dom/trace-component-props"
|
||||
"leptos_dom/trace-component-props",
|
||||
]
|
||||
delegation = ["tachys/delegation"]
|
||||
|
||||
@@ -101,26 +110,56 @@ denylist = [
|
||||
"rustls",
|
||||
"default-tls",
|
||||
"wasm-bindgen",
|
||||
"rkyv", # was causing clippy issues on nightly
|
||||
"rkyv", # was causing clippy issues on nightly
|
||||
"trace-component-props",
|
||||
"spin",
|
||||
"islands",
|
||||
]
|
||||
skip_feature_sets = [
|
||||
["csr", "ssr"],
|
||||
["csr", "hydrate"],
|
||||
["ssr", "hydrate"],
|
||||
["serde", "serde-lite"],
|
||||
["serde-lite", "miniserde"],
|
||||
["serde", "miniserde"],
|
||||
["serde", "rkyv"],
|
||||
["miniserde", "rkyv"],
|
||||
["serde-lite", "rkyv"],
|
||||
["default-tls", "rustls"],
|
||||
[
|
||||
"csr",
|
||||
"ssr",
|
||||
],
|
||||
[
|
||||
"csr",
|
||||
"hydrate",
|
||||
],
|
||||
[
|
||||
"ssr",
|
||||
"hydrate",
|
||||
],
|
||||
[
|
||||
"serde",
|
||||
"serde-lite",
|
||||
],
|
||||
[
|
||||
"serde-lite",
|
||||
"miniserde",
|
||||
],
|
||||
[
|
||||
"serde",
|
||||
"miniserde",
|
||||
],
|
||||
[
|
||||
"serde",
|
||||
"rkyv",
|
||||
],
|
||||
[
|
||||
"miniserde",
|
||||
"rkyv",
|
||||
],
|
||||
[
|
||||
"serde-lite",
|
||||
"rkyv",
|
||||
],
|
||||
[
|
||||
"default-tls",
|
||||
"rustls",
|
||||
],
|
||||
]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)'] }
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)'] }
|
||||
|
||||
@@ -35,7 +35,7 @@ type ChildBuilder<T> = dyn Fn(AnyAttribute) -> T + Send + Sync + 'static;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[component]
|
||||
#[component(transparent)]
|
||||
pub fn AttributeInterceptor<Chil, T>(
|
||||
/// The elements that will be rendered, with the attributes this component received as a
|
||||
/// parameter.
|
||||
|
||||
@@ -44,6 +44,67 @@ use tachys::{reactive_graph::OwnedView, view::keyed::keyed};
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// For convenience, you can also choose to write template code directly in the `<For>`
|
||||
/// component, using the `let` syntax:
|
||||
///
|
||||
/// ```
|
||||
/// # use leptos::prelude::*;
|
||||
///
|
||||
/// # #[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
/// # struct Counter {
|
||||
/// # id: usize,
|
||||
/// # count: RwSignal<i32>
|
||||
/// # }
|
||||
/// #
|
||||
/// # #[component]
|
||||
/// # fn Counters() -> impl IntoView {
|
||||
/// # let (counters, set_counters) = create_signal::<Vec<Counter>>(vec![]);
|
||||
/// #
|
||||
/// view! {
|
||||
/// <div>
|
||||
/// <For
|
||||
/// each=move || counters.get()
|
||||
/// key=|counter| counter.id
|
||||
/// let(counter)
|
||||
/// >
|
||||
/// <button>"Value: " {move || counter.count.get()}</button>
|
||||
/// </For>
|
||||
/// </div>
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// The `let` syntax also supports destructuring the pattern of your data.
|
||||
/// `let((one, two))` in the case of tuples, and `let(Struct { field_one, field_two })`
|
||||
/// in the case of structs.
|
||||
///
|
||||
/// ```
|
||||
/// # use leptos::prelude::*;
|
||||
///
|
||||
/// # #[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
/// # struct Counter {
|
||||
/// # id: usize,
|
||||
/// # count: RwSignal<i32>
|
||||
/// # }
|
||||
/// #
|
||||
/// # #[component]
|
||||
/// # fn Counters() -> impl IntoView {
|
||||
/// # let (counters, set_counters) = create_signal::<Vec<Counter>>(vec![]);
|
||||
/// #
|
||||
/// view! {
|
||||
/// <div>
|
||||
/// <For
|
||||
/// each=move || counters.get()
|
||||
/// key=|counter| counter.id
|
||||
/// let(Counter { id, count })
|
||||
/// >
|
||||
/// <button>"Value: " {move || count.get()}</button>
|
||||
/// </For>
|
||||
/// </div>
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
|
||||
#[component]
|
||||
pub fn For<IF, I, T, EF, N, KF, K>(
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
((root, pkg_path, output_name, wasm_output_name) => {
|
||||
let MOST_RECENT_CHILDREN_CB;
|
||||
|
||||
function idle(c) {
|
||||
if ("requestIdleCallback" in window) {
|
||||
window.requestIdleCallback(c);
|
||||
@@ -6,55 +8,49 @@
|
||||
c();
|
||||
}
|
||||
}
|
||||
function islandTree(rootNode) {
|
||||
const tree = [];
|
||||
|
||||
function traverse(node, parent) {
|
||||
function hydrateIslands(rootNode, mod) {
|
||||
function traverse(node) {
|
||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
if(node.tagName.toLowerCase() === 'leptos-island') {
|
||||
const tag = node.tagName.toLowerCase();
|
||||
if(tag === 'leptos-island') {
|
||||
const children = [];
|
||||
const id = node.dataset.component || null;
|
||||
const data = { id, node, children };
|
||||
|
||||
hydrateIsland(node, id, mod);
|
||||
|
||||
for(const child of node.children) {
|
||||
traverse(child, children);
|
||||
}
|
||||
|
||||
(parent || tree).push(data);
|
||||
} else {
|
||||
if(tag === 'leptos-children') {
|
||||
MOST_RECENT_CHILDREN_CB = node.$$on_hydrate;
|
||||
}
|
||||
for(const child of node.children) {
|
||||
traverse(child, parent);
|
||||
traverse(child);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traverse(rootNode, null);
|
||||
|
||||
return { el: null, id: null, children: tree };
|
||||
traverse(rootNode);
|
||||
}
|
||||
function hydrateIsland(el, id, mod) {
|
||||
const islandFn = mod[id];
|
||||
if (islandFn) {
|
||||
if (MOST_RECENT_CHILDREN_CB) {
|
||||
MOST_RECENT_CHILDREN_CB();
|
||||
}
|
||||
islandFn(el);
|
||||
} else {
|
||||
console.warn(`Could not find WASM function for the island ${id}.`);
|
||||
}
|
||||
}
|
||||
function hydrateIslands(entry, mod) {
|
||||
if(entry.node) {
|
||||
hydrateIsland(entry.node, entry.id, mod);
|
||||
}
|
||||
for (const island of entry.children) {
|
||||
hydrateIslands(island, mod);
|
||||
}
|
||||
}
|
||||
idle(() => {
|
||||
import(`${root}/${pkg_path}/${output_name}.js`)
|
||||
.then(mod => {
|
||||
mod.default(`${root}/${pkg_path}/${wasm_output_name}.wasm`).then(() => {
|
||||
mod.hydrate();
|
||||
hydrateIslands(islandTree(document.body, null), mod);
|
||||
hydrateIslands(document.body, mod);
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1535,7 +1535,7 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
@@ -1851,7 +1851,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote-use"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58e9a38ef862d7fec635661503289062bc5b3035e61859a8de3d3f81823accd2"
|
||||
dependencies = [
|
||||
@@ -1953,7 +1953,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
|
||||
dependencies = [
|
||||
@@ -2104,7 +2104,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||
dependencies = [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_macro"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
@@ -83,4 +83,7 @@ skip_feature_sets = [
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)', 'cfg(erase_components)'] }
|
||||
unexpected_cfgs = { level = "warn", check-cfg = [
|
||||
'cfg(leptos_debuginfo)',
|
||||
'cfg(erase_components)',
|
||||
] }
|
||||
|
||||
@@ -260,8 +260,12 @@ impl ToTokens for Model {
|
||||
let body_name = unmodified_fn_name_from_fn_name(&body_name);
|
||||
let body_expr = if is_island {
|
||||
quote! {
|
||||
::leptos::reactive::owner::Owner::with_hydration(move || {
|
||||
#body_name(#prop_names)
|
||||
::leptos::reactive::owner::Owner::new().with(|| {
|
||||
::leptos::reactive::owner::Owner::with_hydration(move || {
|
||||
::leptos::tachys::reactive_graph::OwnedView::new({
|
||||
#body_name(#prop_names)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
@@ -301,8 +305,8 @@ impl ToTokens for Model {
|
||||
let hydrate_fn_name = hydrate_fn_name.as_ref().unwrap();
|
||||
quote! {
|
||||
{
|
||||
if ::leptos::reactive::owner::Owner::current_shared_context()
|
||||
.map(|sc| sc.get_is_hydrating())
|
||||
if ::leptos::context::use_context::<::leptos::reactive::owner::IsHydrating>()
|
||||
.map(|h| h.0)
|
||||
.unwrap_or(false) {
|
||||
::leptos::either::Either::Left(
|
||||
#component
|
||||
@@ -339,9 +343,23 @@ impl ToTokens for Model {
|
||||
let children = Box::new(|| {
|
||||
let sc = ::leptos::reactive::owner::Owner::current_shared_context().unwrap();
|
||||
let prev = sc.get_is_hydrating();
|
||||
let value = ::leptos::reactive::owner::Owner::with_no_hydration(||
|
||||
::leptos::tachys::html::islands::IslandChildren::new(children()).into_any()
|
||||
);
|
||||
let owner = ::leptos::reactive::owner::Owner::new();
|
||||
let value = owner.clone().with(|| {
|
||||
::leptos::reactive::owner::Owner::with_no_hydration(move || {
|
||||
::leptos::tachys::reactive_graph::OwnedView::new({
|
||||
::leptos::tachys::html::islands::IslandChildren::new_with_on_hydrate(
|
||||
children(),
|
||||
{
|
||||
let owner = owner.clone();
|
||||
move || {
|
||||
owner.set()
|
||||
}
|
||||
}
|
||||
|
||||
)
|
||||
}).into_any()
|
||||
})
|
||||
});
|
||||
sc.set_is_hydrating(prev);
|
||||
value
|
||||
});
|
||||
@@ -424,20 +442,21 @@ impl ToTokens for Model {
|
||||
};
|
||||
let children = if is_island_with_children {
|
||||
quote! {
|
||||
.children({Box::new(|| {
|
||||
.children({
|
||||
let owner = leptos::reactive::owner::Owner::current();
|
||||
Box::new(move || {
|
||||
use leptos::tachys::view::any_view::IntoAny;
|
||||
::leptos::tachys::html::islands::IslandChildren::new(
|
||||
// TODO owner restoration for context
|
||||
()
|
||||
::leptos::tachys::html::islands::IslandChildren::new_with_on_hydrate(
|
||||
(),
|
||||
{
|
||||
let owner = owner.clone();
|
||||
move || {
|
||||
if let Some(owner) = &owner {
|
||||
owner.set()
|
||||
}
|
||||
}
|
||||
}
|
||||
).into_any()})})
|
||||
//.children(children)
|
||||
/*.children(Box::new(|| {
|
||||
use leptos::tachys::view::any_view::IntoAny;
|
||||
::leptos::tachys::html::islands::IslandChildren::new(
|
||||
// TODO owner restoration for context
|
||||
()
|
||||
).into_any()
|
||||
}))*/
|
||||
}
|
||||
} else {
|
||||
quote! {}
|
||||
@@ -655,14 +674,44 @@ impl Prop {
|
||||
abort!(e.span(), e.to_string());
|
||||
});
|
||||
|
||||
let name = if let Pat::Ident(i) = *typed.pat {
|
||||
i
|
||||
} else {
|
||||
abort!(
|
||||
typed.pat,
|
||||
"only `prop: bool` style types are allowed within the \
|
||||
`#[component]` macro"
|
||||
);
|
||||
let name = match *typed.pat {
|
||||
Pat::Ident(i) => {
|
||||
if let Some(name) = &prop_opts.name {
|
||||
PatIdent {
|
||||
attrs: vec![],
|
||||
by_ref: None,
|
||||
mutability: None,
|
||||
ident: Ident::new(name, i.span()),
|
||||
subpat: None,
|
||||
}
|
||||
} else {
|
||||
i
|
||||
}
|
||||
}
|
||||
Pat::Struct(_) | Pat::Tuple(_) | Pat::TupleStruct(_) => {
|
||||
if let Some(name) = &prop_opts.name {
|
||||
PatIdent {
|
||||
attrs: vec![],
|
||||
by_ref: None,
|
||||
mutability: None,
|
||||
ident: Ident::new(name, typed.pat.span()),
|
||||
subpat: None,
|
||||
}
|
||||
} else {
|
||||
abort!(
|
||||
typed.pat,
|
||||
"destructured props must be given a name e.g. \
|
||||
#[prop(name = \"data\")]"
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
abort!(
|
||||
typed.pat,
|
||||
"only `prop: bool` style types are allowed within the \
|
||||
`#[component]` macro"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Self {
|
||||
@@ -865,6 +914,7 @@ struct PropOpt {
|
||||
default: Option<syn::Expr>,
|
||||
into: bool,
|
||||
attrs: bool,
|
||||
name: Option<String>,
|
||||
}
|
||||
|
||||
struct TypedBuilderOpts {
|
||||
|
||||
@@ -108,9 +108,12 @@ pub(crate) fn component_to_tokens(
|
||||
let KeyedAttributeValue::Binding(binding) = &attr.possible_value
|
||||
else {
|
||||
if let Some(ident) = attr.key.to_string().strip_prefix("let:") {
|
||||
let ident1 =
|
||||
format_ident!("{ident}", span = attr.key.span());
|
||||
return Some(quote! { #ident1 });
|
||||
let span = match &attr.key {
|
||||
NodeName::Punctuated(path) => path[1].span(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let ident1 = format_ident!("{ident}", span = span);
|
||||
return Some(quote_spanned! { span => #ident1 });
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
use core::num::NonZeroUsize;
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct UserInfo {
|
||||
user_id: String,
|
||||
email: String,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
struct Admin(bool);
|
||||
|
||||
#[component]
|
||||
fn Component(
|
||||
#[prop(optional)] optional: bool,
|
||||
@@ -10,6 +19,10 @@ fn Component(
|
||||
#[prop(default = NonZeroUsize::new(10).unwrap())] default: NonZeroUsize,
|
||||
#[prop(into)] into: String,
|
||||
impl_trait: impl Fn() -> i32 + 'static,
|
||||
#[prop(name = "data")] UserInfo { email, user_id }: UserInfo,
|
||||
#[prop(name = "tuple")] (name, id): (String, i32),
|
||||
#[prop(name = "tuple_struct")] Admin(is_admin): Admin,
|
||||
#[prop(name = "outside_name")] inside_name: i32,
|
||||
) -> impl IntoView {
|
||||
_ = optional;
|
||||
_ = optional_into;
|
||||
@@ -18,6 +31,12 @@ fn Component(
|
||||
_ = default;
|
||||
_ = into;
|
||||
_ = impl_trait;
|
||||
_ = email;
|
||||
_ = user_id;
|
||||
_ = id;
|
||||
_ = name;
|
||||
_ = is_admin;
|
||||
_ = inside_name;
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -26,6 +45,13 @@ fn component() {
|
||||
.into("")
|
||||
.strip_option(9)
|
||||
.impl_trait(|| 42)
|
||||
.data(UserInfo {
|
||||
email: "em@il".into(),
|
||||
user_id: "1".into(),
|
||||
})
|
||||
.tuple(("Joe".into(), 12))
|
||||
.tuple_struct(Admin(true))
|
||||
.outside_name(1)
|
||||
.build();
|
||||
assert!(!cp.optional);
|
||||
assert_eq!(cp.optional_into, None);
|
||||
@@ -34,6 +60,16 @@ fn component() {
|
||||
assert_eq!(cp.default, NonZeroUsize::new(10).unwrap());
|
||||
assert_eq!(cp.into, "");
|
||||
assert_eq!((cp.impl_trait)(), 42);
|
||||
assert_eq!(
|
||||
cp.data,
|
||||
UserInfo {
|
||||
email: "em@il".into(),
|
||||
user_id: "1".into(),
|
||||
}
|
||||
);
|
||||
assert_eq!(cp.tuple, ("Joe".into(), 12));
|
||||
assert_eq!(cp.tuple_struct, Admin(true));
|
||||
assert_eq!(cp.outside_name, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -45,12 +81,26 @@ fn component_nostrip() {
|
||||
strip_option=9
|
||||
into=""
|
||||
impl_trait=|| 42
|
||||
data=UserInfo {
|
||||
email: "em@il".into(),
|
||||
user_id: "1".into(),
|
||||
}
|
||||
tuple=("Joe".into(), 12)
|
||||
tuple_struct=Admin(true)
|
||||
outside_name=1
|
||||
/>
|
||||
<Component
|
||||
nostrip:optional_into=Some("foo")
|
||||
strip_option=9
|
||||
into=""
|
||||
impl_trait=|| 42
|
||||
data=UserInfo {
|
||||
email: "em@il".into(),
|
||||
user_id: "1".into(),
|
||||
}
|
||||
tuple=("Joe".into(), 12)
|
||||
tuple_struct=Admin(true)
|
||||
outside_name=1
|
||||
/>
|
||||
};
|
||||
}
|
||||
|
||||
@@ -44,4 +44,10 @@ fn default_with_invalid_value(
|
||||
_ = default;
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn destructure_without_name((default, value): (bool, i32)) -> impl IntoView {
|
||||
_ = default;
|
||||
_ = value;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
error: supported fields are `optional`, `optional_no_strip`, `strip_option`, `default`, `into` and `attrs`
|
||||
error: supported fields are `optional`, `optional_no_strip`, `strip_option`, `default`, `into`, `attrs` and `name`
|
||||
--> tests/ui/component.rs:10:31
|
||||
|
|
||||
10 | fn unknown_prop_option(#[prop(hello)] test: bool) -> impl IntoView {
|
||||
@@ -41,3 +41,9 @@ error: unexpected end of input, expected one of: identifier, `::`, `<`, `_`, lit
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the attribute macro `component` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: destructured props must be given a name e.g. #[prop(name = "data")]
|
||||
--> tests/ui/component.rs:48:29
|
||||
|
|
||||
48 | fn destructure_without_name((default, value): (bool, i32)) -> impl IntoView {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
error: supported fields are `optional`, `optional_no_strip`, `strip_option`, `default`, `into` and `attrs`
|
||||
error: supported fields are `optional`, `optional_no_strip`, `strip_option`, `default`, `into`, `attrs` and `name`
|
||||
--> tests/ui/component_absolute.rs:5:31
|
||||
|
|
||||
5 | fn unknown_prop_option(#[prop(hello)] test: bool) -> impl ::leptos::IntoView {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_meta"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
@@ -34,4 +34,4 @@ rustdoc-args = ["--generate-link-to-definition"]
|
||||
denylist = ["tracing"]
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)'] }
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)'] }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reactive_graph"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
@@ -25,7 +25,7 @@ async-lock = "3.4.0"
|
||||
send_wrapper = { version = "0.6.0", features = ["futures"] }
|
||||
|
||||
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
|
||||
web-sys = "0.3.72"
|
||||
web-sys = { version = "0.3.72", features = ["console"] }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.41", features = ["rt-multi-thread", "macros"] }
|
||||
|
||||
@@ -292,6 +292,8 @@ impl Owner {
|
||||
#[cfg(feature = "hydration")]
|
||||
pub fn with_hydration<T>(fun: impl FnOnce() -> T + 'static) -> T {
|
||||
fn inner<T>(fun: Box<dyn FnOnce() -> T>) -> T {
|
||||
provide_context(IsHydrating(true));
|
||||
|
||||
let sc = OWNER.with_borrow(|o| {
|
||||
o.as_ref()
|
||||
.and_then(|current| current.shared_context.clone())
|
||||
@@ -315,6 +317,8 @@ impl Owner {
|
||||
#[cfg(feature = "hydration")]
|
||||
pub fn with_no_hydration<T>(fun: impl FnOnce() -> T + 'static) -> T {
|
||||
fn inner<T>(fun: Box<dyn FnOnce() -> T>) -> T {
|
||||
provide_context(IsHydrating(false));
|
||||
|
||||
let sc = OWNER.with_borrow(|o| {
|
||||
o.as_ref()
|
||||
.and_then(|current| current.shared_context.clone())
|
||||
@@ -335,6 +339,10 @@ impl Owner {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct IsHydrating(pub bool);
|
||||
|
||||
/// Registers a function to be run the next time the current owner is cleaned up.
|
||||
///
|
||||
/// Because the ownership model is associated with reactive nodes, each "decision point" in an
|
||||
|
||||
@@ -104,7 +104,7 @@ impl<T: 'static> Debug for Plain<T> {
|
||||
impl<T: 'static> Plain<T> {
|
||||
/// Takes a reference-counted read guard on the given lock.
|
||||
pub fn try_new(inner: Arc<RwLock<T>>) -> Option<Self> {
|
||||
ArcRwLockReadGuardian::take(inner)
|
||||
ArcRwLockReadGuardian::try_take(inner)?
|
||||
.ok()
|
||||
.map(|guard| Plain { guard })
|
||||
}
|
||||
@@ -331,7 +331,7 @@ pub struct UntrackedWriteGuard<T: 'static>(ArcRwLockWriteGuardian<T>);
|
||||
impl<T: 'static> UntrackedWriteGuard<T> {
|
||||
/// Creates a write guard from the given lock.
|
||||
pub fn try_new(inner: Arc<RwLock<T>>) -> Option<Self> {
|
||||
ArcRwLockWriteGuardian::take(inner)
|
||||
ArcRwLockWriteGuardian::try_take(inner)?
|
||||
.ok()
|
||||
.map(UntrackedWriteGuard)
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ pub trait Dispose {
|
||||
/// Allows tracking the value of some reactive data.
|
||||
pub trait Track {
|
||||
/// Subscribes to this signal in the current reactive scope without doing anything with its value.
|
||||
#[track_caller]
|
||||
fn track(&self);
|
||||
}
|
||||
|
||||
@@ -404,6 +405,7 @@ where
|
||||
/// Notifies subscribers of a change in this signal.
|
||||
pub trait Notify {
|
||||
/// Notifies subscribers of a change in this signal.
|
||||
#[track_caller]
|
||||
fn notify(&self);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reactive_stores"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -450,10 +450,7 @@ where
|
||||
let inner = self.inner.reader()?;
|
||||
|
||||
let inner_path = self.inner.path().into_iter().collect();
|
||||
let keys = self
|
||||
.inner
|
||||
.keys()
|
||||
.expect("using keys on a store with no keys");
|
||||
let keys = self.inner.keys()?;
|
||||
let index = keys
|
||||
.with_field_keys(
|
||||
inner_path,
|
||||
@@ -461,8 +458,7 @@ where
|
||||
|| self.inner.latest_keys(),
|
||||
)
|
||||
.flatten()
|
||||
.map(|(_, idx)| idx)
|
||||
.expect("reading from a keyed field that has not yet been created");
|
||||
.map(|(_, idx)| idx)?;
|
||||
|
||||
Some(MappedMutArc::new(
|
||||
inner,
|
||||
@@ -654,8 +650,8 @@ where
|
||||
#[track_caller]
|
||||
fn into_iter(self) -> StoreFieldKeyedIter<Inner, Prev, K, T> {
|
||||
// reactively track changes to this field
|
||||
let trigger = self.get_trigger(self.path().into_iter().collect());
|
||||
trigger.this.track();
|
||||
self.update_keys();
|
||||
self.track_field();
|
||||
|
||||
// get the current length of the field by accessing slice
|
||||
let reader = self
|
||||
|
||||
@@ -114,8 +114,8 @@ use reactive_graph::{
|
||||
ArcTrigger,
|
||||
},
|
||||
traits::{
|
||||
DefinedAt, IsDisposed, Notify, ReadUntracked, Track, UntrackableGuard,
|
||||
Write,
|
||||
DefinedAt, Dispose, IsDisposed, Notify, ReadUntracked, Track,
|
||||
UntrackableGuard, Write,
|
||||
},
|
||||
};
|
||||
pub use reactive_stores_macro::{Patch, Store};
|
||||
@@ -335,6 +335,12 @@ impl<T> ArcStore<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Default for ArcStore<T> {
|
||||
fn default() -> Self {
|
||||
Self::new(T::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Debug> Debug for ArcStore<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let mut f = f.debug_struct("ArcStore");
|
||||
@@ -468,6 +474,24 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for Store<T>
|
||||
where
|
||||
T: Default + Send + Sync + 'static,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self::new(T::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for Store<T, LocalStorage>
|
||||
where
|
||||
T: Default + 'static,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self::new_local(T::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Debug, S> Debug for Store<T, S>
|
||||
where
|
||||
S: Debug,
|
||||
@@ -511,6 +535,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> Dispose for Store<T, S>
|
||||
where
|
||||
T: 'static,
|
||||
{
|
||||
fn dispose(self) {
|
||||
self.inner.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> ReadUntracked for Store<T, S>
|
||||
where
|
||||
T: 'static,
|
||||
@@ -569,6 +602,20 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> From<ArcStore<T>> for Store<T, S>
|
||||
where
|
||||
T: 'static,
|
||||
S: Storage<ArcStore<T>>,
|
||||
{
|
||||
fn from(value: ArcStore<T>) -> Self {
|
||||
Self {
|
||||
#[cfg(debug_assertions)]
|
||||
defined_at: value.defined_at,
|
||||
inner: ArenaItem::new_with_storage(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{self as reactive_stores, Patch, Store, StoreFieldIterator};
|
||||
|
||||
@@ -24,12 +24,15 @@ pub trait StoreField: Sized {
|
||||
type Writer: UntrackableGuard<Target = Self::Value>;
|
||||
|
||||
/// Returns the trigger that tracks access and updates for this field.
|
||||
#[track_caller]
|
||||
fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger;
|
||||
|
||||
/// The path of this field (see [`StorePath`]).
|
||||
#[track_caller]
|
||||
fn path(&self) -> impl IntoIterator<Item = StorePathSegment>;
|
||||
|
||||
/// Reactively tracks this field.
|
||||
#[track_caller]
|
||||
fn track_field(&self) {
|
||||
let path = self.path().into_iter().collect();
|
||||
let trigger = self.get_trigger(path);
|
||||
@@ -38,12 +41,15 @@ pub trait StoreField: Sized {
|
||||
}
|
||||
|
||||
/// Returns a read guard to access this field.
|
||||
#[track_caller]
|
||||
fn reader(&self) -> Option<Self::Reader>;
|
||||
|
||||
/// Returns a write guard to update this field.
|
||||
#[track_caller]
|
||||
fn writer(&self) -> Option<Self::Writer>;
|
||||
|
||||
/// The keys for this field, if it is a keyed field.
|
||||
#[track_caller]
|
||||
fn keys(&self) -> Option<KeyMap>;
|
||||
}
|
||||
|
||||
@@ -55,26 +61,31 @@ where
|
||||
type Reader = Plain<T>;
|
||||
type Writer = WriteGuard<ArcTrigger, UntrackedWriteGuard<T>>;
|
||||
|
||||
#[track_caller]
|
||||
fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
|
||||
let triggers = &self.signals;
|
||||
let trigger = triggers.write().or_poisoned().get_or_insert(path);
|
||||
trigger
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn path(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||
iter::empty()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn reader(&self) -> Option<Self::Reader> {
|
||||
Plain::try_new(Arc::clone(&self.value))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn writer(&self) -> Option<Self::Writer> {
|
||||
let trigger = self.get_trigger(Default::default());
|
||||
let guard = UntrackedWriteGuard::try_new(Arc::clone(&self.value))?;
|
||||
Some(WriteGuard::new(trigger.children, guard))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn keys(&self) -> Option<KeyMap> {
|
||||
Some(self.keys.clone())
|
||||
}
|
||||
@@ -89,6 +100,7 @@ where
|
||||
type Reader = Plain<T>;
|
||||
type Writer = WriteGuard<ArcTrigger, UntrackedWriteGuard<T>>;
|
||||
|
||||
#[track_caller]
|
||||
fn get_trigger(&self, path: StorePath) -> StoreFieldTrigger {
|
||||
self.inner
|
||||
.try_get_value()
|
||||
@@ -96,6 +108,7 @@ where
|
||||
.unwrap_or_else(unwrap_signal!(self))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn path(&self) -> impl IntoIterator<Item = StorePathSegment> {
|
||||
self.inner
|
||||
.try_get_value()
|
||||
@@ -103,14 +116,17 @@ where
|
||||
.unwrap_or_else(unwrap_signal!(self))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn reader(&self) -> Option<Self::Reader> {
|
||||
self.inner.try_get_value().and_then(|n| n.reader())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn writer(&self) -> Option<Self::Writer> {
|
||||
self.inner.try_get_value().and_then(|n| n.writer())
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn keys(&self) -> Option<KeyMap> {
|
||||
self.inner.try_get_value().and_then(|inner| inner.keys())
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ where
|
||||
self.inner.keys()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn track_field(&self) {
|
||||
let inner = self
|
||||
.inner
|
||||
@@ -144,6 +145,7 @@ where
|
||||
Inner: StoreField<Value = Prev>,
|
||||
Prev: 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn notify(&self) {
|
||||
let trigger = self.get_trigger(self.path().into_iter().collect());
|
||||
trigger.this.notify();
|
||||
@@ -157,6 +159,7 @@ where
|
||||
Prev: 'static,
|
||||
T: 'static,
|
||||
{
|
||||
#[track_caller]
|
||||
fn track(&self) {
|
||||
self.track_field();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_router"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
authors = ["Greg Johnston", "Ben Wishovich"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -82,13 +82,18 @@ where
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
let (location_provider, current_url, redirect_hook) = {
|
||||
let owner = Owner::current();
|
||||
let location =
|
||||
BrowserUrl::new().expect("could not access browser navigation"); // TODO options here
|
||||
location.init(base.clone());
|
||||
provide_context(location.clone());
|
||||
let current_url = location.as_url().clone();
|
||||
|
||||
let redirect_hook = Box::new(|loc: &str| BrowserUrl::redirect(loc));
|
||||
let redirect_hook = Box::new(move |loc: &str| {
|
||||
if let Some(owner) = &owner {
|
||||
owner.with(|| BrowserUrl::redirect(loc));
|
||||
}
|
||||
});
|
||||
|
||||
(Some(location), current_url, redirect_hook)
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leptos_router_macro"
|
||||
version = "0.7.1"
|
||||
version = "0.7.3"
|
||||
authors = ["Greg Johnston", "Ben Wishovich"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
@@ -21,4 +21,4 @@ quote = "1.0"
|
||||
leptos_router = { path = "../router" }
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)'] }
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)'] }
|
||||
|
||||
8
server_fn/Cargo.lock
generated
8
server_fn/Cargo.lock
generated
@@ -1190,7 +1190,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
dependencies = [
|
||||
@@ -1447,7 +1447,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "radium"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||
|
||||
@@ -1704,7 +1704,7 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
|
||||
dependencies = [
|
||||
@@ -1810,7 +1810,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||
dependencies = [
|
||||
|
||||
@@ -231,4 +231,4 @@ skip_feature_sets = [
|
||||
]
|
||||
|
||||
[lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)'] }
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(leptos_debuginfo)'] }
|
||||
|
||||
@@ -117,7 +117,7 @@ impl<T> JsonStream<T> {
|
||||
pub fn new(
|
||||
value: impl Stream<Item = Result<T, ServerFnError>> + Send + 'static,
|
||||
) -> Self {
|
||||
Self(Box::pin(value.map(|value| value.map(Into::into))))
|
||||
Self(Box::pin(value.map(|value| value)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -175,7 +175,7 @@ impl TextStream {
|
||||
pub fn new(
|
||||
value: impl Stream<Item = Result<String, ServerFnError>> + Send + 'static,
|
||||
) -> Self {
|
||||
Self(Box::pin(value.map(|value| value.map(Into::into))))
|
||||
Self(Box::pin(value.map(|value| value)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tachys"
|
||||
version = "0.1.1"
|
||||
version = "0.1.3"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::{
|
||||
renderer::Rndr,
|
||||
view::{Position, ToTemplate},
|
||||
};
|
||||
use std::{future::Future, sync::Arc};
|
||||
use std::{borrow::Cow, future::Future, sync::Arc};
|
||||
|
||||
/// Adds a CSS class.
|
||||
#[inline(always)]
|
||||
@@ -324,6 +324,63 @@ impl IntoClass for &str {
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoClass for Cow<'_, str> {
|
||||
type AsyncOutput = Self;
|
||||
type State = (crate::renderer::types::Element, Self);
|
||||
type Cloneable = Arc<str>;
|
||||
type CloneableOwned = Arc<str>;
|
||||
|
||||
fn html_len(&self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn to_html(self, class: &mut String) {
|
||||
IntoClass::to_html(&*self, class);
|
||||
}
|
||||
|
||||
fn hydrate<const FROM_SERVER: bool>(
|
||||
self,
|
||||
el: &crate::renderer::types::Element,
|
||||
) -> Self::State {
|
||||
if !FROM_SERVER {
|
||||
Rndr::set_attribute(el, "class", &self);
|
||||
}
|
||||
(el.clone(), self)
|
||||
}
|
||||
|
||||
fn build(self, el: &crate::renderer::types::Element) -> Self::State {
|
||||
Rndr::set_attribute(el, "class", &self);
|
||||
(el.clone(), self)
|
||||
}
|
||||
|
||||
fn rebuild(self, state: &mut Self::State) {
|
||||
let (el, prev) = state;
|
||||
if self != *prev {
|
||||
Rndr::set_attribute(el, "class", &self);
|
||||
}
|
||||
*prev = self;
|
||||
}
|
||||
|
||||
fn into_cloneable(self) -> Self::Cloneable {
|
||||
self.into()
|
||||
}
|
||||
|
||||
fn into_cloneable_owned(self) -> Self::CloneableOwned {
|
||||
self.into()
|
||||
}
|
||||
|
||||
fn dry_resolve(&mut self) {}
|
||||
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
self
|
||||
}
|
||||
|
||||
fn reset(state: &mut Self::State) {
|
||||
let (el, _prev) = state;
|
||||
Rndr::remove_attribute(el, "class");
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoClass for String {
|
||||
type AsyncOutput = Self;
|
||||
type State = (crate::renderer::types::Element, Self);
|
||||
|
||||
@@ -250,7 +250,7 @@ html_elements! {
|
||||
/// The `<body>` HTML element represents the content of an HTML document. There can be only one `<body>` element in a document.
|
||||
body HtmlBodyElement [] true,
|
||||
/// The `<button>` HTML element represents a clickable button, used to submit forms or anywhere in a document for accessible, standard button functionality.
|
||||
button HtmlButtonElement [disabled, form, formaction, formenctype, formmethod, formnovalidate, formtarget, name, r#type, value] true,
|
||||
button HtmlButtonElement [disabled, form, formaction, formenctype, formmethod, formnovalidate, formtarget, name, r#type, value, popovertarget, popovertargetaction] true,
|
||||
/// Use the HTML `<canvas>` element with either the canvas scripting API or the WebGL API to draw graphics and animations.
|
||||
canvas HtmlCanvasElement [height, width] true,
|
||||
/// The `<caption>` HTML element specifies the caption (or title) of a table.
|
||||
|
||||
@@ -176,6 +176,7 @@ where
|
||||
cursor.sibling();
|
||||
}
|
||||
position.set(Position::FirstChild);
|
||||
|
||||
self.view.hydrate::<FROM_SERVER>(cursor, position)
|
||||
}
|
||||
}
|
||||
@@ -183,12 +184,28 @@ where
|
||||
/// The children that will be projected into an [`Island`].
|
||||
pub struct IslandChildren<View> {
|
||||
view: View,
|
||||
on_hydrate: Option<Box<dyn Fn() + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl<View> IslandChildren<View> {
|
||||
/// Creates a new representation of the children.
|
||||
pub fn new(view: View) -> Self {
|
||||
IslandChildren { view }
|
||||
IslandChildren {
|
||||
view,
|
||||
on_hydrate: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new representation of the children, with a function to be called whenever
|
||||
/// a child island hydrates.
|
||||
pub fn new_with_on_hydrate(
|
||||
view: View,
|
||||
on_hydrate: impl Fn() + Send + Sync + 'static,
|
||||
) -> Self {
|
||||
IslandChildren {
|
||||
view,
|
||||
on_hydrate: Some(Box::new(on_hydrate)),
|
||||
}
|
||||
}
|
||||
|
||||
fn open_tag(buf: &mut String) {
|
||||
@@ -229,9 +246,10 @@ where
|
||||
where
|
||||
Self::Output<NewAttr>: RenderHtml,
|
||||
{
|
||||
let IslandChildren { view } = self;
|
||||
let IslandChildren { view, on_hydrate } = self;
|
||||
IslandChildren {
|
||||
view: view.add_any_attr(attr),
|
||||
on_hydrate,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,9 +270,10 @@ where
|
||||
}
|
||||
|
||||
async fn resolve(self) -> Self::AsyncOutput {
|
||||
let IslandChildren { view } = self;
|
||||
let IslandChildren { view, on_hydrate } = self;
|
||||
IslandChildren {
|
||||
view: view.resolve().await,
|
||||
on_hydrate,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,5 +332,28 @@ where
|
||||
} else if curr_position != Position::Current {
|
||||
cursor.sibling();
|
||||
}
|
||||
|
||||
if let Some(on_hydrate) = self.on_hydrate {
|
||||
use crate::{
|
||||
hydration::failed_to_cast_element, renderer::CastFrom,
|
||||
};
|
||||
|
||||
let el =
|
||||
crate::renderer::types::Element::cast_from(cursor.current())
|
||||
.unwrap_or_else(|| {
|
||||
failed_to_cast_element(
|
||||
"leptos-children",
|
||||
cursor.current(),
|
||||
)
|
||||
});
|
||||
let cb = wasm_bindgen::closure::Closure::wrap(
|
||||
on_hydrate as Box<dyn Fn()>,
|
||||
);
|
||||
_ = js_sys::Reflect::set(
|
||||
&el,
|
||||
&wasm_bindgen::JsValue::from_str("$$on_hydrate"),
|
||||
&cb.into_js_value(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,6 +212,9 @@ impl<const V: &'static str> RenderHtml for Static<V> {
|
||||
.unwrap_or_else(|| {
|
||||
crate::hydration::failed_to_cast_text_node(node)
|
||||
});
|
||||
|
||||
position.set(Position::NextChildAfterText);
|
||||
|
||||
Some(node)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user