mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-28 06:42:35 -05:00
Compare commits
503 Commits
2182
...
hn-js-fetc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11f8453f7c | ||
|
|
d0f2069f1c | ||
|
|
54481223bf | ||
|
|
6ac6fc6a12 | ||
|
|
a09cb02b31 | ||
|
|
1f9ec1b979 | ||
|
|
6c72aaf444 | ||
|
|
899feb0575 | ||
|
|
b0c1bf46af | ||
|
|
ec4958959c | ||
|
|
174a5a1769 | ||
|
|
ae68435fb6 | ||
|
|
e507945cd1 | ||
|
|
8f6620d06a | ||
|
|
23f433efa4 | ||
|
|
d9502a94c1 | ||
|
|
ae0dc13ce7 | ||
|
|
22b1132340 | ||
|
|
cb7656599e | ||
|
|
f40d0c1334 | ||
|
|
8a878eaaa4 | ||
|
|
f70702c6c4 | ||
|
|
e2d41f91fa | ||
|
|
dc21e4ff53 | ||
|
|
d5aecbe705 | ||
|
|
032faec5bc | ||
|
|
443fca495d | ||
|
|
c5f0f4a6ed | ||
|
|
64cdfbd2a8 | ||
|
|
698d7f6f1b | ||
|
|
8789ed0882 | ||
|
|
fd5a6bebd3 | ||
|
|
0a081fafe3 | ||
|
|
f8711611b0 | ||
|
|
f508f30be9 | ||
|
|
52261415cd | ||
|
|
65b270307d | ||
|
|
f2db13da10 | ||
|
|
1d90b11e81 | ||
|
|
f0048e4d45 | ||
|
|
5c211cf1ce | ||
|
|
aed4d49537 | ||
|
|
fa15a00288 | ||
|
|
40b383a0f7 | ||
|
|
cd289ef811 | ||
|
|
76dcb823d8 | ||
|
|
88c9742e6c | ||
|
|
edc86bbb43 | ||
|
|
3fc0a6ff32 | ||
|
|
3797a4167a | ||
|
|
5ffcfc4079 | ||
|
|
87f5d95bc3 | ||
|
|
0597cda70a | ||
|
|
a2f6ebf3a6 | ||
|
|
0be5628038 | ||
|
|
52434ada9d | ||
|
|
ae0b09419d | ||
|
|
2f93b6d147 | ||
|
|
4cf7dd0e0c | ||
|
|
2402688493 | ||
|
|
36726e9dfc | ||
|
|
ab886a1258 | ||
|
|
2d51311362 | ||
|
|
9262b512e0 | ||
|
|
28b38329a3 | ||
|
|
0567aeb5b8 | ||
|
|
f9cd5ca159 | ||
|
|
9b72efb9c4 | ||
|
|
61ee451e19 | ||
|
|
50d4eb2f50 | ||
|
|
72aa8a6598 | ||
|
|
06fe32e90b | ||
|
|
75184a4638 | ||
|
|
29e5396912 | ||
|
|
b8df56afa1 | ||
|
|
7d4b7d2ce8 | ||
|
|
d132c8e338 | ||
|
|
6bf6fb6923 | ||
|
|
1bda454441 | ||
|
|
9aca55f14f | ||
|
|
f1a007bf15 | ||
|
|
d83c2acded | ||
|
|
f984197070 | ||
|
|
c8491cc709 | ||
|
|
222aed6d11 | ||
|
|
7d37c60bae | ||
|
|
fea3fdb387 | ||
|
|
d57f484502 | ||
|
|
62bd6a244e | ||
|
|
fe147f0c4d | ||
|
|
3e0d4e4876 | ||
|
|
9eda75525a | ||
|
|
de1864867b | ||
|
|
116d8f072b | ||
|
|
6097e3cc57 | ||
|
|
59c18d945a | ||
|
|
0b750e17b5 | ||
|
|
dd6f1f4660 | ||
|
|
de07282b0a | ||
|
|
f6046fa8a7 | ||
|
|
d945e27d72 | ||
|
|
74a2486944 | ||
|
|
142a7d64f9 | ||
|
|
f87ce51ff9 | ||
|
|
5f979635a3 | ||
|
|
f648bc2e85 | ||
|
|
bcc75d46c0 | ||
|
|
2e0d70765b | ||
|
|
24f6b6afb5 | ||
|
|
ca0b2e6b4d | ||
|
|
4eb8c2a5b1 | ||
|
|
a18de6eb4f | ||
|
|
bf8844f040 | ||
|
|
da9553cc7a | ||
|
|
5e3d4ac37a | ||
|
|
4366bc156d | ||
|
|
23bbba0ef8 | ||
|
|
35f86535d0 | ||
|
|
1ca8e082c3 | ||
|
|
b20542e22d | ||
|
|
abfff8f98d | ||
|
|
46c89a5862 | ||
|
|
32518e46df | ||
|
|
639f801c79 | ||
|
|
924358d829 | ||
|
|
91e7266103 | ||
|
|
347611ebec | ||
|
|
424c3a7209 | ||
|
|
4c078e8eb0 | ||
|
|
0ed1420076 | ||
|
|
5221675946 | ||
|
|
50d4d08b9b | ||
|
|
b51215af8f | ||
|
|
e37f3ee756 | ||
|
|
9c949f6d9a | ||
|
|
59d3a9853f | ||
|
|
4df0a6c7e9 | ||
|
|
4560f5e31c | ||
|
|
0887ada9a9 | ||
|
|
cddbd24eff | ||
|
|
19db6d9388 | ||
|
|
466cc39411 | ||
|
|
5b39f7d27f | ||
|
|
ab18371c32 | ||
|
|
9d818d7796 | ||
|
|
5316066612 | ||
|
|
10af7b81cc | ||
|
|
51b261d202 | ||
|
|
b5e0c2b150 | ||
|
|
e322fb1b33 | ||
|
|
24c7fd954e | ||
|
|
a303814d84 | ||
|
|
75d1b14e59 | ||
|
|
3a7dbafda3 | ||
|
|
3271bcda4e | ||
|
|
36e4eca909 | ||
|
|
23d1579d23 | ||
|
|
474fba0ab5 | ||
|
|
8725a329d2 | ||
|
|
ffa0883b48 | ||
|
|
b6ed91b81b | ||
|
|
fdb298f254 | ||
|
|
93d0b3fa26 | ||
|
|
ab57926d8f | ||
|
|
6eeb22f1f0 | ||
|
|
648d96f316 | ||
|
|
a60e5235d7 | ||
|
|
76deab365e | ||
|
|
b4948745c7 | ||
|
|
059df60373 | ||
|
|
5f464298b3 | ||
|
|
9c304d8d75 | ||
|
|
ca909becc1 | ||
|
|
f231503baf | ||
|
|
d1d6238d9b | ||
|
|
0543b05738 | ||
|
|
1a09f1f54a | ||
|
|
3201cacca1 | ||
|
|
454d179cf9 | ||
|
|
8c73455eeb | ||
|
|
e8c5a69412 | ||
|
|
6088da7342 | ||
|
|
ea76a0f74e | ||
|
|
5e43d37601 | ||
|
|
d70ef1178e | ||
|
|
30556af5f6 | ||
|
|
9255ad1840 | ||
|
|
e53d139fc1 | ||
|
|
07f1eed36a | ||
|
|
02587781ac | ||
|
|
d32d6d8fe8 | ||
|
|
c10a3d251d | ||
|
|
8550b54be6 | ||
|
|
becc1075ab | ||
|
|
6b5467d451 | ||
|
|
3375dbdcbc | ||
|
|
4842ef28e0 | ||
|
|
8945fc8724 | ||
|
|
bee37de5c9 | ||
|
|
b192136a4b | ||
|
|
907b9df06e | ||
|
|
b6a62ab4d9 | ||
|
|
e36fce4351 | ||
|
|
76ec0b78c2 | ||
|
|
bec33e255d | ||
|
|
cdcfcf6a0e | ||
|
|
422de7c8af | ||
|
|
662bd4fd78 | ||
|
|
a4b4e2b3ac | ||
|
|
4e84a78307 | ||
|
|
012535a2d7 | ||
|
|
43c953c4b9 | ||
|
|
143973960c | ||
|
|
8a0f43affe | ||
|
|
b55a19a533 | ||
|
|
21cdadf461 | ||
|
|
d95e59a685 | ||
|
|
28468a0bae | ||
|
|
b183bb981c | ||
|
|
ee5e4bc5c0 | ||
|
|
581d5d0469 | ||
|
|
d2bb6d5062 | ||
|
|
8a419705d8 | ||
|
|
0a7b025534 | ||
|
|
060338e643 | ||
|
|
8dee986164 | ||
|
|
05166d2cb7 | ||
|
|
40d8cfb04b | ||
|
|
53fbe76761 | ||
|
|
c3d8d1e828 | ||
|
|
4636192fa3 | ||
|
|
02705dec31 | ||
|
|
dc09faf7eb | ||
|
|
402eb95221 | ||
|
|
d92b430fbf | ||
|
|
030d06521e | ||
|
|
c8f2ef375b | ||
|
|
8ed8b5605b | ||
|
|
7c526cfa52 | ||
|
|
5e20b8fcca | ||
|
|
6b3ccdf2f4 | ||
|
|
d7a321aa69 | ||
|
|
abfa2d02fe | ||
|
|
7b8edda5ae | ||
|
|
967bf2fdfc | ||
|
|
274ac2ba34 | ||
|
|
3b10fb54c6 | ||
|
|
1274c0890e | ||
|
|
b05bbb5499 | ||
|
|
77bce6d440 | ||
|
|
4f01c4f61e | ||
|
|
0812f8d850 | ||
|
|
059968ca58 | ||
|
|
b67229ca78 | ||
|
|
d59f234d88 | ||
|
|
1e2815b0a0 | ||
|
|
4ae8a6d54c | ||
|
|
3c3e97e8b9 | ||
|
|
83be4167d8 | ||
|
|
691b44baa1 | ||
|
|
c58f05e129 | ||
|
|
ddfa4dd76f | ||
|
|
1dd8175aa4 | ||
|
|
18c5e4c804 | ||
|
|
65a30910b1 | ||
|
|
f0b6995f50 | ||
|
|
ffce98f928 | ||
|
|
3b71be89ca | ||
|
|
941ea12420 | ||
|
|
e44504f8ba | ||
|
|
9924f8fef7 | ||
|
|
cb2f66a955 | ||
|
|
c43379cb68 | ||
|
|
71e34935e5 | ||
|
|
ab9a1d8b0a | ||
|
|
05db18e2b8 | ||
|
|
b530b46064 | ||
|
|
ebeec2c3bd | ||
|
|
a4304876bf | ||
|
|
38ca7137e0 | ||
|
|
9b6108dae7 | ||
|
|
6092971f7c | ||
|
|
80e5274a88 | ||
|
|
0d705c3318 | ||
|
|
1c3b157293 | ||
|
|
ff950daa6e | ||
|
|
af1cb9fca1 | ||
|
|
d82e43f526 | ||
|
|
b95b8ea43d | ||
|
|
077dd85964 | ||
|
|
f24af45e19 | ||
|
|
ce2390d6d0 | ||
|
|
a82a72400d | ||
|
|
e37ca85bdd | ||
|
|
de138b397c | ||
|
|
28ae64bc06 | ||
|
|
95b4cd3841 | ||
|
|
6f7522381c | ||
|
|
d6997bddc5 | ||
|
|
7de95ff99f | ||
|
|
fa28d56928 | ||
|
|
3f2cdf77a3 | ||
|
|
f8500f416f | ||
|
|
2f81a81c06 | ||
|
|
ffb8e8bea3 | ||
|
|
6f158a8974 | ||
|
|
2cc1ec9b3c | ||
|
|
dbed68e5ba | ||
|
|
1a1d2e1c07 | ||
|
|
b3871dea75 | ||
|
|
eba4711fa7 | ||
|
|
e8273348db | ||
|
|
af051aa72a | ||
|
|
e9ec7412fa | ||
|
|
e5757c56b7 | ||
|
|
031d78cd5a | ||
|
|
a0ba356cc1 | ||
|
|
adf6a8e368 | ||
|
|
6eed4e8253 | ||
|
|
88d311a0c5 | ||
|
|
0d7db85e9e | ||
|
|
2f77fb1892 | ||
|
|
a66662397c | ||
|
|
105e2c7686 | ||
|
|
324bebcf50 | ||
|
|
e553ad3a68 | ||
|
|
b7ecac308f | ||
|
|
79ebd416a3 | ||
|
|
4e2b9b1878 | ||
|
|
c1a6f2f479 | ||
|
|
fb855cb07f | ||
|
|
1850231c92 | ||
|
|
55c7b84a00 | ||
|
|
4e2646513f | ||
|
|
9a75edd34c | ||
|
|
81afa8d0c8 | ||
|
|
d3919d3568 | ||
|
|
5b23fddd02 | ||
|
|
8de1f86db3 | ||
|
|
97901bfedb | ||
|
|
f6eb7fa8b6 | ||
|
|
36ccc3d834 | ||
|
|
82ba7195c8 | ||
|
|
5f7cdb1091 | ||
|
|
e3a0f59f4a | ||
|
|
b77e127588 | ||
|
|
c0d51ede3d | ||
|
|
49b2b5047e | ||
|
|
058d357e59 | ||
|
|
6b0a47ae8a | ||
|
|
49de4bc671 | ||
|
|
2033ce251e | ||
|
|
c37a4e02a6 | ||
|
|
39357bf9a7 | ||
|
|
5ead1ec3df | ||
|
|
1826586d03 | ||
|
|
ad29695eac | ||
|
|
76a12a9bf4 | ||
|
|
8ce815f210 | ||
|
|
e9a05f095e | ||
|
|
c114df5ebb | ||
|
|
17977d8fb7 | ||
|
|
455cbc07a6 | ||
|
|
272b6da00c | ||
|
|
09cc5df975 | ||
|
|
106aaaf412 | ||
|
|
521172ef5f | ||
|
|
51d0ed4735 | ||
|
|
05bd7a6276 | ||
|
|
7f911ac26a | ||
|
|
3d0810bb5e | ||
|
|
49f1fce64d | ||
|
|
86377d208d | ||
|
|
d07bcb1bb4 | ||
|
|
9389195e6b | ||
|
|
b98ba8e2fa | ||
|
|
005766495c | ||
|
|
1cb9a82239 | ||
|
|
fcdc5f8b9e | ||
|
|
aa624fccc7 | ||
|
|
d742179c2f | ||
|
|
470f7f15fe | ||
|
|
4f45b1032e | ||
|
|
5f3623574d | ||
|
|
fbde9eaefa | ||
|
|
83067627db | ||
|
|
53d51e03ff | ||
|
|
0205d715c2 | ||
|
|
05b7e83778 | ||
|
|
4d0339ee05 | ||
|
|
fba207df08 | ||
|
|
a16367215c | ||
|
|
376b90d60b | ||
|
|
20b0894b9f | ||
|
|
c197131b6b | ||
|
|
1ea18bb3eb | ||
|
|
62decfde51 | ||
|
|
8f3ecd84b2 | ||
|
|
6b1f6563d2 | ||
|
|
b5bfa41400 | ||
|
|
018f347673 | ||
|
|
ab35ea7d21 | ||
|
|
cb0a0292d5 | ||
|
|
351e42e885 | ||
|
|
3a89396ccc | ||
|
|
32183692c0 | ||
|
|
4cf95432b7 | ||
|
|
b24e52773f | ||
|
|
3bcf7c7355 | ||
|
|
be971d018a | ||
|
|
1f391d08c0 | ||
|
|
8682487650 | ||
|
|
3c062e5b3e | ||
|
|
6117cfa849 | ||
|
|
7344618160 | ||
|
|
83696c14da | ||
|
|
eacaaaec90 | ||
|
|
c51e8f3569 | ||
|
|
64fc1b8bd1 | ||
|
|
1b4ae08943 | ||
|
|
eff6aa2459 | ||
|
|
8e6c2e50b4 | ||
|
|
dd9aa9e4cd | ||
|
|
47e11acf80 | ||
|
|
3bed48abaa | ||
|
|
a72221de2a | ||
|
|
0243a705fa | ||
|
|
abaab492c0 | ||
|
|
935bdd2d61 | ||
|
|
c5679b9a2a | ||
|
|
d2ef1c833e | ||
|
|
e357ca5d02 | ||
|
|
e913ad7439 | ||
|
|
6b57437514 | ||
|
|
19c965bb35 | ||
|
|
657d0057f2 | ||
|
|
45f5a4ea39 | ||
|
|
feeab73833 | ||
|
|
10c142a655 | ||
|
|
d97e72d2f4 | ||
|
|
3952fa4952 | ||
|
|
87772466d1 | ||
|
|
8479fddf92 | ||
|
|
8b738d3a2a | ||
|
|
df7f83165b | ||
|
|
f54b4f3d1e | ||
|
|
21a8bd31c7 | ||
|
|
02e9e48d89 | ||
|
|
e0a1b7a813 | ||
|
|
748c600e59 | ||
|
|
26cacbd379 | ||
|
|
36df86b3b7 | ||
|
|
57fd178afb | ||
|
|
ce559e1e22 | ||
|
|
ff51f064d4 | ||
|
|
3379462633 | ||
|
|
3e3359bea1 | ||
|
|
0702b02011 | ||
|
|
5af8ca4202 | ||
|
|
17e822c14b | ||
|
|
3db9e627db | ||
|
|
1cb0c6c5c8 | ||
|
|
de81d9d92f | ||
|
|
6a107cfa23 | ||
|
|
93d00ae968 | ||
|
|
cd322144f7 | ||
|
|
d89025e347 | ||
|
|
ebc7bcd469 | ||
|
|
597dc6c625 | ||
|
|
45daa770fe | ||
|
|
16b282da9e | ||
|
|
dccf5a010d | ||
|
|
5cdfdf52bd | ||
|
|
9fc3b8b52b | ||
|
|
d4555671e1 | ||
|
|
c83a3b537c | ||
|
|
d09d6acbf1 | ||
|
|
9d93c451a6 | ||
|
|
ca298ea3d8 | ||
|
|
0339392658 | ||
|
|
ae36060ebe | ||
|
|
46a839bf43 | ||
|
|
c274518c18 | ||
|
|
b204f569eb | ||
|
|
a3286fd9b6 | ||
|
|
9fd5a646f1 | ||
|
|
65b2042682 | ||
|
|
c57347edd7 | ||
|
|
8f7db58b7c | ||
|
|
bae1312f06 | ||
|
|
5e9a69a9ca | ||
|
|
bcfe54b1ca | ||
|
|
2a2a3d1461 | ||
|
|
b70c4da854 | ||
|
|
0436a82c65 | ||
|
|
6260ca49b0 | ||
|
|
d045ad335d | ||
|
|
3bb34b2358 | ||
|
|
27b2eca74c | ||
|
|
1a525fe9e7 | ||
|
|
6f24d29bcf | ||
|
|
d2f88f004d | ||
|
|
33f0720be1 |
13
.github/dependabot.yml
vendored
13
.github/dependabot.yml
vendored
@@ -1,13 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: "cargo"
|
||||
directories:
|
||||
- "/"
|
||||
- "/examples/*"
|
||||
- "/benchmarks"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
6
.github/workflows/ci-semver.yml
vendored
6
.github/workflows/ci-semver.yml
vendored
@@ -14,8 +14,8 @@ jobs:
|
||||
|
||||
test:
|
||||
needs: [get-leptos-changed]
|
||||
if: github.event.pull_request.labels[0].name == 'semver' # needs.get-leptos-changed.outputs.leptos_changed == 'true' && github.event.pull_request.labels[0].name != 'breaking'
|
||||
name: Run semver check (nightly-2024-08-01)
|
||||
if: needs.get-leptos-changed.outputs.leptos_changed == 'true' && github.event.pull_request.labels[0].name != 'breaking'
|
||||
name: Run semver check (nightly-2024-04-14)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@@ -25,4 +25,4 @@ jobs:
|
||||
- name: Semver Checks
|
||||
uses: obi1kenobi/cargo-semver-checks-action@v2
|
||||
with:
|
||||
rust-toolchain: nightly-2024-08-01
|
||||
rust-toolchain: nightly-2024-04-14
|
||||
|
||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -49,4 +49,4 @@ jobs:
|
||||
with:
|
||||
directory: ${{ matrix.directory }}
|
||||
cargo_make_task: "ci"
|
||||
toolchain: nightly-2024-08-01
|
||||
toolchain: nightly-2024-04-14
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
- name: Get example project directories that changed
|
||||
id: changed-dirs
|
||||
uses: tj-actions/changed-files@v44
|
||||
uses: tj-actions/changed-files@v41
|
||||
with:
|
||||
dir_names: true
|
||||
dir_names_max_depth: "2"
|
||||
|
||||
2
.github/workflows/get-example-changed.yml
vendored
2
.github/workflows/get-example-changed.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
|
||||
- name: Get example files that changed
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v44
|
||||
uses: tj-actions/changed-files@v43
|
||||
with:
|
||||
files: |
|
||||
examples/**
|
||||
|
||||
2
.github/workflows/get-leptos-changed.yml
vendored
2
.github/workflows/get-leptos-changed.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
|
||||
- name: Get source files that changed
|
||||
id: changed-source
|
||||
uses: tj-actions/changed-files@v44
|
||||
uses: tj-actions/changed-files@v43
|
||||
with:
|
||||
files: |
|
||||
any_error/**
|
||||
|
||||
2
.github/workflows/run-cargo-make-task.yml
vendored
2
.github/workflows/run-cargo-make-task.yml
vendored
@@ -64,7 +64,7 @@ jobs:
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v3
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
|
||||
56
Cargo.toml
56
Cargo.toml
@@ -37,39 +37,37 @@ members = [
|
||||
"router_macro",
|
||||
"any_error",
|
||||
]
|
||||
exclude = ["benchmarks", "examples", "projects"]
|
||||
exclude = ["benchmarks", "examples"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.7.0-beta2"
|
||||
edition = "2021"
|
||||
rust-version = "1.76"
|
||||
version = "0.7.0-alpha"
|
||||
rust-version = "1.75"
|
||||
|
||||
[workspace.dependencies]
|
||||
throw_error = { path = "./any_error/", version = "0.2.0-beta2" }
|
||||
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-beta2" }
|
||||
leptos = { path = "./leptos", version = "0.7.0-beta2" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.7.0-beta2" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.7.0-beta2" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.7.0-beta2" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.7.0-beta2" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.7.0-beta2" }
|
||||
leptos_router = { path = "./router", version = "0.7.0-beta2" }
|
||||
leptos_router_macro = { path = "./router_macro", version = "0.7.0-beta2" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.7.0-beta2" }
|
||||
leptos_meta = { path = "./meta", version = "0.7.0-beta2" }
|
||||
next_tuple = { path = "./next_tuple", version = "0.1.0-beta2" }
|
||||
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-beta2" }
|
||||
reactive_stores = { path = "./reactive_stores", version = "0.1.0-beta2" }
|
||||
reactive_stores_macro = { path = "./reactive_stores_macro", version = "0.1.0-beta2" }
|
||||
server_fn = { path = "./server_fn", version = "0.7.0-beta2" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.7.0-beta2" }
|
||||
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.7.0-beta2" }
|
||||
tachys = { path = "./tachys", version = "0.1.0-beta2" }
|
||||
throw_error = { path = "./any_error/", version = "0.1" }
|
||||
any_spawner = { path = "./any_spawner/", version = "0.1" }
|
||||
const_str_slice_concat = { path = "./const_str_slice_concat", version = "0.1" }
|
||||
either_of = { path = "./either_of/", version = "0.1" }
|
||||
hydration_context = { path = "./hydration_context", version = "0.2.0-alpha" }
|
||||
leptos = { path = "./leptos", version = "0.7.0-alpha" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.7.0-alpha" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.7.0-alpha" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.7.0-alpha" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.7.0-alpha" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.7.0-alpha" }
|
||||
leptos_router = { path = "./router", version = "0.7.0-alpha" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.7.0-alpha" }
|
||||
leptos_meta = { path = "./meta", version = "0.7.0-alpha" }
|
||||
next_tuple = { path = "./next_tuple", version = "0.1.0-alpha" }
|
||||
oco_ref = { path = "./oco", version = "0.2" }
|
||||
or_poisoned = { path = "./or_poisoned", version = "0.1" }
|
||||
reactive_graph = { path = "./reactive_graph", version = "0.1.0-alpha" }
|
||||
reactive_stores = { path = "./reactive_stores", version = "0.1.0-alpha" }
|
||||
reactive_stores_macro = { path = "./reactive_stores_macro", version = "0.1.0-alpha" }
|
||||
server_fn = { path = "./server_fn", version = "0.7.0-alpha" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.7.0-alpha" }
|
||||
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.7.0-alpha" }
|
||||
tachys = { path = "./tachys", version = "0.1.0-alpha" }
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
|
||||
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,13 +1,13 @@
|
||||
[package]
|
||||
name = "throw_error"
|
||||
version = "0.2.0-beta2"
|
||||
edition = "2021"
|
||||
version = "0.1.0"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Utilities for wrapping, throwing, and catching errors."
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
pin-project-lite = "0.2.14"
|
||||
pin-project-lite = "0.2"
|
||||
|
||||
@@ -9,7 +9,7 @@ use std::{
|
||||
error,
|
||||
fmt::{self, Display},
|
||||
future::Future,
|
||||
mem, ops,
|
||||
ops,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
task::{Context, Poll},
|
||||
@@ -92,25 +92,9 @@ thread_local! {
|
||||
static ERROR_HOOK: RefCell<Option<Arc<dyn ErrorHook>>> = RefCell::new(None);
|
||||
}
|
||||
|
||||
/// Resets the error hook to its previous state when dropped.
|
||||
pub struct ResetErrorHookOnDrop(Option<Arc<dyn ErrorHook>>);
|
||||
|
||||
impl Drop for ResetErrorHookOnDrop {
|
||||
fn drop(&mut self) {
|
||||
ERROR_HOOK.with_borrow_mut(|this| *this = self.0.take())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the current error hook.
|
||||
pub fn get_error_hook() -> Option<Arc<dyn ErrorHook>> {
|
||||
ERROR_HOOK.with_borrow(Clone::clone)
|
||||
}
|
||||
|
||||
/// Sets the current thread-local error hook, which will be invoked when [`throw`] is called.
|
||||
pub fn set_error_hook(hook: Arc<dyn ErrorHook>) -> ResetErrorHookOnDrop {
|
||||
ResetErrorHookOnDrop(
|
||||
ERROR_HOOK.with_borrow_mut(|this| mem::replace(this, Some(hook))),
|
||||
)
|
||||
pub fn set_error_hook(hook: Arc<dyn ErrorHook>) {
|
||||
ERROR_HOOK.with_borrow_mut(|this| *this = Some(hook))
|
||||
}
|
||||
|
||||
/// Invokes the error hook set by [`set_error_hook`] with the given error.
|
||||
@@ -156,10 +140,9 @@ where
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let this = self.project();
|
||||
let _hook = this
|
||||
.hook
|
||||
.as_ref()
|
||||
.map(|hook| set_error_hook(Arc::clone(hook)));
|
||||
if let Some(hook) = &this.hook {
|
||||
set_error_hook(Arc::clone(hook))
|
||||
}
|
||||
this.inner.poll(cx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
[package]
|
||||
name = "any_spawner"
|
||||
edition = "2021"
|
||||
version = "0.1.1"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Spawn asynchronous tasks in an executor-independent way."
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
futures = "0.3.30"
|
||||
glib = { version = "0.20.0", optional = true }
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1.39", optional = true, default-features = false, features = [
|
||||
"rt",
|
||||
futures = "0.3"
|
||||
glib = { version = "0.19", optional = true }
|
||||
thiserror = "1"
|
||||
tokio = { version = "1", optional = true, default-features = false, features = [
|
||||
"rt",
|
||||
] }
|
||||
tracing = { version = "0.1.40", optional = true }
|
||||
wasm-bindgen-futures = { version = "0.4.42", optional = true }
|
||||
tracing = { version = "0.1", optional = true }
|
||||
wasm-bindgen-futures = { version = "0.4", optional = true }
|
||||
|
||||
[features]
|
||||
tracing = ["dep:tracing"]
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
use std::{future::Future, pin::Pin, sync::OnceLock};
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -6,31 +6,31 @@ rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
l0410 = { package = "leptos", version = "0.4.10", features = [
|
||||
"nightly",
|
||||
"ssr",
|
||||
"nightly",
|
||||
"ssr",
|
||||
] }
|
||||
leptos = { path = "../leptos", features = ["ssr", "nightly"] }
|
||||
leptos_reactive = { path = "../leptos_reactive", features = ["ssr", "nightly"] }
|
||||
tachydom = { git = "https://github.com/gbj/tachys", features = [
|
||||
"nightly",
|
||||
"leptos",
|
||||
"nightly",
|
||||
"leptos",
|
||||
] }
|
||||
tachy_maccy = { git = "https://github.com/gbj/tachys", features = ["nightly"] }
|
||||
sycamore = { version = "0.8.0", features = ["ssr"] }
|
||||
yew = { version = "0.20.0", features = ["ssr"] }
|
||||
tokio-test = "0.4.0"
|
||||
miniserde = "0.1.0"
|
||||
gloo = "0.8.0"
|
||||
uuid = { version = "1.0", features = ["serde", "v4", "wasm-bindgen"] }
|
||||
wasm-bindgen = "0.2.0"
|
||||
lazy_static = "1.0"
|
||||
log = "0.4.0"
|
||||
strum = "0.24.0"
|
||||
strum_macros = "0.24.0"
|
||||
serde = { version = "1.0", features = ["derive", "rc"] }
|
||||
serde_json = "1.0"
|
||||
tera = "1.0"
|
||||
sycamore = { version = "0.8", features = ["ssr"] }
|
||||
yew = { version = "0.20", features = ["ssr"] }
|
||||
tokio-test = "0.4"
|
||||
miniserde = "0.1"
|
||||
gloo = "0.8"
|
||||
uuid = { version = "1", features = ["serde", "v4", "wasm-bindgen"] }
|
||||
wasm-bindgen = "0.2"
|
||||
lazy_static = "1"
|
||||
log = "0.4"
|
||||
strum = "0.24"
|
||||
strum_macros = "0.24"
|
||||
serde = { version = "1", features = ["derive", "rc"] }
|
||||
serde_json = "1"
|
||||
tera = "1"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.0"
|
||||
version = "0.3"
|
||||
features = ["Window", "Document", "HtmlElement", "HtmlInputElement"]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
[package]
|
||||
name = "const_str_slice_concat"
|
||||
edition = "2021"
|
||||
version = "0.1.0"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
@@ -7,6 +8,5 @@ readme = "../README.md"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Utilities for const concatenation of string slices."
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
[package]
|
||||
name = "either_of"
|
||||
edition = "2021"
|
||||
version = "0.1.0"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
@@ -7,7 +8,6 @@ readme = "../README.md"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Utilities for working with enumerated types that contain one of 2..n other types."
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
pin-project-lite = "0.2.14"
|
||||
pin-project-lite = "0.2"
|
||||
|
||||
@@ -7,18 +7,19 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
actix-files = { version = "0.6.6", optional = true }
|
||||
actix-web = { version = "4.8", optional = true, features = ["macros"] }
|
||||
console_error_panic_hook = "0.1.7"
|
||||
cfg-if = "1.0"
|
||||
actix-files = { version = "0.6", optional = true }
|
||||
actix-web = { version = "4", optional = true, features = ["macros"] }
|
||||
console_error_panic_hook = "0.1"
|
||||
cfg-if = "1"
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_actix = { path = "../../integrations/actix", optional = true }
|
||||
leptos_router = { path = "../../router" }
|
||||
wasm-bindgen = "0.2.93"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
wasm-bindgen = "0.2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
|
||||
[features]
|
||||
csr = ["leptos/csr"]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
"dep:actix-files",
|
||||
|
||||
@@ -1,9 +1,68 @@
|
||||
# Action Form Error Handling Example
|
||||
<picture>
|
||||
<source srcset="https://raw.githubusercontent.com/leptos-rs/leptos/main/docs/logos/Leptos_logo_Solid_White.svg" media="(prefers-color-scheme: dark)">
|
||||
<img src="https://raw.githubusercontent.com/leptos-rs/leptos/main/docs/logos/Leptos_logo_RGB.svg" alt="Leptos Logo">
|
||||
</picture>
|
||||
|
||||
## Getting Started
|
||||
# Leptos Starter Template
|
||||
|
||||
See the [Examples README](../README.md) for setup and run instructions.
|
||||
This is a template for use with the [Leptos](https://github.com/leptos-rs/leptos) web framework and the [cargo-leptos](https://github.com/akesson/cargo-leptos) tool.
|
||||
|
||||
## Quick Start
|
||||
## Creating your template repo
|
||||
|
||||
Execute `cargo leptos watch` to run this example.
|
||||
If you don't have `cargo-leptos` installed you can install it with
|
||||
|
||||
`cargo install cargo-leptos`
|
||||
|
||||
Then run
|
||||
|
||||
`cargo leptos new --git leptos-rs/start`
|
||||
|
||||
to generate a new project template (you will be prompted to enter a project name).
|
||||
|
||||
`cd {projectname}`
|
||||
|
||||
to go to your newly created project.
|
||||
|
||||
Of course, you should explore around the project structure, but the best place to start with your application code is in `src/app.rs`.
|
||||
|
||||
## Running your project
|
||||
|
||||
`cargo leptos watch`
|
||||
By default, you can access your local project at `http://localhost:3000`
|
||||
|
||||
## Installing Additional Tools
|
||||
|
||||
By default, `cargo-leptos` uses `nightly` Rust, `cargo-generate`, and `sass`. If you run into any trouble, you may need to install one or more of these tools.
|
||||
|
||||
1. `rustup toolchain install nightly --allow-downgrade` - make sure you have Rust nightly
|
||||
2. `rustup target add wasm32-unknown-unknown` - add the ability to compile Rust to WebAssembly
|
||||
3. `cargo install cargo-generate` - install `cargo-generate` binary (should be installed automatically in future)
|
||||
4. `npm install -g sass` - install `dart-sass` (should be optional in future)
|
||||
|
||||
## Executing a Server on a Remote Machine Without the Toolchain
|
||||
After running a `cargo leptos build --release` the minimum files needed are:
|
||||
|
||||
1. The server binary located in `target/server/release`
|
||||
2. The `site` directory and all files within located in `target/site`
|
||||
|
||||
Copy these files to your remote server. The directory structure should be:
|
||||
```text
|
||||
leptos_start
|
||||
site/
|
||||
```
|
||||
Set the following environment variables (updating for your project as needed):
|
||||
```sh
|
||||
export LEPTOS_OUTPUT_NAME="leptos_start"
|
||||
export LEPTOS_SITE_ROOT="site"
|
||||
export LEPTOS_SITE_PKG_DIR="pkg"
|
||||
export LEPTOS_SITE_ADDR="127.0.0.1:3000"
|
||||
export LEPTOS_RELOAD_PORT="3001"
|
||||
```
|
||||
Finally, run the server binary.
|
||||
|
||||
## Notes about CSR and Trunk:
|
||||
Although it is not recommended, you can also run your project without server integration using the feature `csr` and `trunk serve`:
|
||||
|
||||
`trunk serve --open --features csr`
|
||||
|
||||
This may be useful for integrating external tools which require a static site, e.g. `tauri`.
|
||||
|
||||
@@ -52,10 +52,23 @@ async fn main() -> std::io::Result<()> {
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
#[cfg(not(any(feature = "ssr", feature = "csr")))]
|
||||
pub fn main() {
|
||||
// no client-side main function
|
||||
// unless we want this to work with e.g., Trunk for pure client-side testing
|
||||
// see lib.rs for hydration function instead
|
||||
// see optional feature `csr` instead
|
||||
}
|
||||
|
||||
#[cfg(all(not(feature = "ssr"), feature = "csr"))]
|
||||
pub fn main() {
|
||||
// a client-side main function is required for using `trunk serve`
|
||||
// prefer using `cargo leptos serve` instead
|
||||
// to run: `trunk serve --open --features csr`
|
||||
use action_form_error_handling::app::*;
|
||||
use leptos::prelude::*;
|
||||
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
mount_to_body(App);
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ lto = true
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
console_log = "1.0"
|
||||
log = "0.4.22"
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
gloo-timers = { version = "0.3.0", features = ["futures"] }
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen = "0.2.93"
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
web-sys = "0.3.70"
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
web-sys = "0.3"
|
||||
|
||||
@@ -10,7 +10,7 @@ pub fn SimpleCounter(
|
||||
/// The change that should be applied each time the button is clicked.
|
||||
step: i32,
|
||||
) -> impl IntoView {
|
||||
let (value, set_value) = signal(initial_value);
|
||||
/*let (value, set_value) = signal(initial_value);
|
||||
|
||||
view! {
|
||||
<div>
|
||||
@@ -19,5 +19,24 @@ pub fn SimpleCounter(
|
||||
<span>"Value: " {value} "!"</span>
|
||||
<button on:click=move |_| set_value.update(|value| *value += step)>"+1"</button>
|
||||
</div>
|
||||
}
|
||||
}*/
|
||||
App()
|
||||
}
|
||||
|
||||
use gloo_timers::future::TimeoutFuture;
|
||||
use leptos::{html::Input, prelude::*};
|
||||
|
||||
#[component]
|
||||
fn Widget() -> impl IntoView {
|
||||
let input_ref = NodeRef::<Input>::new();
|
||||
|
||||
Effect::new(move |_| {
|
||||
let Some(_) = input_ref.get() else {
|
||||
log!("no ref");
|
||||
return;
|
||||
};
|
||||
log!("ref");
|
||||
});
|
||||
|
||||
view! { <input node_ref=input_ref type="text"/> }
|
||||
}
|
||||
|
||||
@@ -11,34 +11,34 @@ codegen-units = 1
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
actix-files = { version = "0.6.6", optional = true }
|
||||
actix-web = { version = "4.8", optional = true, features = ["macros"] }
|
||||
broadcaster = "1.0"
|
||||
console_log = "1.0"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
futures = "0.3.30"
|
||||
lazy_static = "1.5"
|
||||
actix-files = { version = "0.6", optional = true }
|
||||
actix-web = { version = "4", optional = true, features = ["macros"] }
|
||||
broadcaster = "1"
|
||||
console_log = "1"
|
||||
console_error_panic_hook = "0.1"
|
||||
futures = "0.3"
|
||||
lazy_static = "1"
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos_actix = { path = "../../integrations/actix", optional = true }
|
||||
leptos_router = { path = "../../router" }
|
||||
log = "0.4.22"
|
||||
once_cell = "1.19"
|
||||
gloo-net = { version = "0.6.0" }
|
||||
wasm-bindgen = "0.2.93"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
simple_logger = "5.0"
|
||||
tracing = { version = "0.1.40", optional = true }
|
||||
log = "0.4"
|
||||
once_cell = "1.18"
|
||||
gloo-net = { git = "https://github.com/rustwasm/gloo" }
|
||||
wasm-bindgen = "0.2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
simple_logger = "4.3"
|
||||
tracing = { version = "0.1", optional = true }
|
||||
send_wrapper = "0.6.0"
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
"dep:actix-files",
|
||||
"dep:actix-web",
|
||||
"dep:tracing",
|
||||
"leptos/ssr",
|
||||
"leptos_actix",
|
||||
"leptos_router/ssr",
|
||||
"dep:actix-files",
|
||||
"dep:actix-web",
|
||||
"dep:tracing",
|
||||
"leptos/ssr",
|
||||
"leptos_actix",
|
||||
"leptos_router/ssr",
|
||||
]
|
||||
|
||||
[package.metadata.cargo-all-features]
|
||||
|
||||
@@ -76,9 +76,18 @@ pub fn Counters() -> impl IntoView {
|
||||
</nav>
|
||||
<main>
|
||||
<FlatRoutes fallback=|| "Not found.">
|
||||
<Route path=StaticSegment("") view=Counter/>
|
||||
<Route path=StaticSegment("form") view=FormCounter/>
|
||||
<Route path=StaticSegment("multi") view=MultiuserCounter/>
|
||||
<Route
|
||||
path=StaticSegment("")
|
||||
view=Counter
|
||||
/>
|
||||
<Route
|
||||
path=StaticSegment("form")
|
||||
view=FormCounter
|
||||
/>
|
||||
<Route
|
||||
path=StaticSegment("multi")
|
||||
view=MultiuserCounter
|
||||
/>
|
||||
</FlatRoutes>
|
||||
</main>
|
||||
</Router>
|
||||
@@ -113,10 +122,13 @@ pub fn Counter() -> impl IntoView {
|
||||
</p>
|
||||
<ErrorBoundary fallback=|errors| move || format!("Error: {:#?}", errors.get())>
|
||||
<div>
|
||||
<button on:click=move |_| { clear.dispatch(()); }>"Clear"</button>
|
||||
<button on:click=move |_| { dec.dispatch(()); }>"-1"</button>
|
||||
<span>"Value: " <Suspense>{counter} "!"</Suspense></span>
|
||||
<button on:click=move |_| { inc.dispatch(()); }>"+1"</button>
|
||||
<button on:click=move |_| clear.dispatch(())>"Clear"</button>
|
||||
<button on:click=move |_| dec.dispatch(())>"-1"</button>
|
||||
<span>
|
||||
"Value: "
|
||||
<Suspense>{counter} "!" </Suspense>
|
||||
</span>
|
||||
<button on:click=move |_| inc.dispatch(())>"+1"</button>
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
</div>
|
||||
@@ -224,12 +236,12 @@ pub fn MultiuserCounter() -> impl IntoView {
|
||||
"This one uses server-sent events (SSE) to live-update when other users make changes."
|
||||
</p>
|
||||
<div>
|
||||
<button on:click=move |_| { clear.dispatch(()); }>"Clear"</button>
|
||||
<button on:click=move |_| { dec.dispatch(()); }>"-1"</button>
|
||||
<button on:click=move |_| clear.dispatch(())>"Clear"</button>
|
||||
<button on:click=move |_| dec.dispatch(())>"-1"</button>
|
||||
<span>
|
||||
"Multiplayer Value: " {move || multiplayer_value.get().unwrap_or_default()}
|
||||
</span>
|
||||
<button on:click=move |_| { inc.dispatch(()); }>"+1"</button>
|
||||
<button on:click=move |_| inc.dispatch(())>"+1"</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@ leptos_router = { path = "../../router", features = [] }
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen = "0.2.93"
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
web-sys = "0.3.70"
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
web-sys = "0.3"
|
||||
|
||||
@@ -14,10 +14,10 @@ console_error_panic_hook = "0.1.7"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
pretty_assertions = "1.4"
|
||||
rstest = "0.22.0"
|
||||
wasm-bindgen-test = "0.3.34"
|
||||
pretty_assertions = "1.3.0"
|
||||
rstest = "0.17.0"
|
||||
|
||||
[dev-dependencies.web-sys]
|
||||
features = ["HtmlElement", "XPathResult"]
|
||||
version = "0.3.70"
|
||||
version = "0.3.61"
|
||||
|
||||
@@ -4,10 +4,10 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
wasm-bindgen = "0.2.93"
|
||||
web-sys = "0.3.70"
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
wasm-bindgen = "0.2"
|
||||
web-sys = "0.3"
|
||||
|
||||
@@ -5,12 +5,12 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
log = "0.4.22"
|
||||
console_log = "1.0"
|
||||
log = "0.4"
|
||||
console_log = "1"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
web-sys = { version = "0.3.70", features = ["Clipboard", "Navigator"] }
|
||||
web-sys = { version = "0.3", features = ["Clipboard", "Navigator"] }
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
wasm-bindgen = "0.2.93"
|
||||
web-sys = { version = "0.3.70", features = ["NodeList"] }
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
wasm-bindgen = "0.2"
|
||||
web-sys = { version = "0.3", features = ["NodeList"] }
|
||||
|
||||
@@ -24,7 +24,11 @@ pub fn copy_to_clipboard(el: Element, content: &str) {
|
||||
evt.prevent_default();
|
||||
evt.stop_propagation();
|
||||
|
||||
let _ = window().navigator().clipboard().write_text(&content);
|
||||
let _ = window()
|
||||
.navigator()
|
||||
.clipboard()
|
||||
.expect("navigator.clipboard to be available")
|
||||
.write_text(&content);
|
||||
|
||||
el.set_inner_html(&format!("Copied \"{}\"", &content));
|
||||
});
|
||||
@@ -49,6 +53,7 @@ impl From<()> for Amount {
|
||||
}
|
||||
}
|
||||
|
||||
// .into() will automatically be called on the parameter
|
||||
pub fn add_dot(el: Element, amount: Amount) {
|
||||
use leptos::wasm_bindgen::JsCast;
|
||||
let el = el.unchecked_into::<web_sys::HtmlElement>();
|
||||
@@ -77,17 +82,12 @@ pub fn App() -> impl IntoView {
|
||||
let data = "Hello World!";
|
||||
|
||||
view! {
|
||||
<a href="#" use:copy_to_clipboard=data>
|
||||
"Copy \""
|
||||
{data}
|
||||
"\" to clipboard"
|
||||
</a>
|
||||
<a href="#" use:copy_to_clipboard=data>"Copy \"" {data} "\" to clipboard"</a>
|
||||
// automatically applies the directive to every root element in `SomeComponent`
|
||||
<SomeComponent use:highlight/>
|
||||
<SomeComponent use:highlight />
|
||||
// no value will default to `().into()`
|
||||
<button use:add_dot>"Add a dot"</button>
|
||||
// can manually call `.into()` to convert to the correct type
|
||||
// (automatically calling `.into()` prevents using generics in directive functions)
|
||||
<button use:add_dot=5.into()>"Add 5 dots"</button>
|
||||
// `5.into()` automatically called
|
||||
<button use:add_dot=5>"Add 5 dots"</button>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@ lto = true
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
console_log = "1.0"
|
||||
log = "0.4.22"
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
||||
@@ -7,19 +7,19 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
console_error_panic_hook = "0.1"
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos_axum = { path = "../../integrations/axum", optional = true }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_router = { path = "../../router" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
axum = { version = "0.7.5", optional = true }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
tower-http = { version = "0.5.2", features = ["fs"], optional = true }
|
||||
tokio = { version = "1.39", features = ["full"], optional = true }
|
||||
http = { version = "1.1" }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
axum = { version = "0.7", optional = true }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs"], optional = true }
|
||||
tokio = { version = "1", features = ["full"], optional = true }
|
||||
http = { version = "1.0" }
|
||||
thiserror = "1.0"
|
||||
wasm-bindgen = "0.2.93"
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
|
||||
@@ -9,16 +9,16 @@ lto = true
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr", "tracing"] }
|
||||
reqwasm = "0.5.0"
|
||||
gloo-timers = { version = "0.3.0", features = ["futures"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
log = "0.4.22"
|
||||
console_log = "1.0"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
thiserror = "1.0"
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = "0.3.18"
|
||||
tracing-subscriber-wasm = "0.1.0"
|
||||
reqwasm = "0.5"
|
||||
gloo-timers = { version = "0.3", features = ["futures"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
log = "0.4"
|
||||
console_log = "1"
|
||||
console_error_panic_hook = "0.1"
|
||||
thiserror = "1"
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = "0.3"
|
||||
tracing-subscriber-wasm = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
wasm-bindgen-test = "0.3"
|
||||
|
||||
@@ -85,7 +85,7 @@ pub fn fetch_example() -> impl IntoView {
|
||||
<Transition fallback=|| view! { <div>"Loading..."</div> } {..spreadable}>
|
||||
<ErrorBoundary fallback>
|
||||
<ul>
|
||||
{move || Suspend::new(async move {
|
||||
{move || Suspend(async move {
|
||||
cats.await
|
||||
.map(|cats| {
|
||||
cats.iter()
|
||||
|
||||
@@ -4,15 +4,15 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
throw_error = { path = "../../any_error/" }
|
||||
|
||||
# these are used to build the integration
|
||||
gtk = { version = "0.9.0", package = "gtk4" }
|
||||
any_spawner = { path = "../../any_spawner/" }
|
||||
next_tuple = { path = "../../next_tuple/" }
|
||||
paste = "1.0"
|
||||
gtk = { version = "0.8.0", package = "gtk4", optional = true }
|
||||
paste = "1.0.14"
|
||||
|
||||
# we want to support using glib for the reactive runtime event loop
|
||||
any_spawner = { path = "../../any_spawner/", features = ["glib"] }
|
||||
# yes, we want effects to run: this is a "frontend," not a backend
|
||||
reactive_graph = { path = "../../reactive_graph", features = ["effects"] }
|
||||
console_error_panic_hook = { version = "0.1", optional = true }
|
||||
|
||||
[features]
|
||||
gtk = ["dep:gtk", "any_spawner/glib"]
|
||||
wasm = ["any_spawner/wasm-bindgen", "dep:console_error_panic_hook"]
|
||||
|
||||
@@ -56,12 +56,11 @@ impl Mountable<LeptosGtk> for Element {
|
||||
.insert_before(&parent.0, marker.as_ref().map(|m| &m.0));
|
||||
}
|
||||
|
||||
fn insert_before_this(&self, child: &mut dyn Mountable<LeptosGtk>) -> bool {
|
||||
if let Some(parent) = self.0.parent() {
|
||||
child.mount(&Element(parent), Some(self));
|
||||
return true;
|
||||
}
|
||||
false
|
||||
fn insert_before_this(&self,
|
||||
child: &mut dyn Mountable<LeptosGtk>,
|
||||
) -> bool {
|
||||
child.mount(parent, Some(self.as_ref()));
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,8 +79,11 @@ impl Mountable<LeptosGtk> for Text {
|
||||
.insert_before(&parent.0, marker.as_ref().map(|m| &m.0));
|
||||
}
|
||||
|
||||
fn insert_before_this(&self, child: &mut dyn Mountable<LeptosGtk>) -> bool {
|
||||
self.0.insert_before_this(child)
|
||||
fn insert_before_this(&self,
|
||||
child: &mut dyn Mountable<LeptosGtk>,
|
||||
) -> bool {
|
||||
child.mount(parent, Some(self.as_ref()));
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,12 +332,16 @@ where
|
||||
parent: &<LeptosGtk as Renderer>::Element,
|
||||
marker: Option<&<LeptosGtk as Renderer>::Node>,
|
||||
) {
|
||||
println!("mounting {}", std::any::type_name::<Widg>());
|
||||
self.children.mount(&self.widget, None);
|
||||
LeptosGtk::insert_node(parent, &self.widget, marker);
|
||||
}
|
||||
|
||||
fn insert_before_this(&self, child: &mut dyn Mountable<LeptosGtk>) -> bool {
|
||||
self.widget.insert_before_this(child)
|
||||
fn insert_before_this(&self,
|
||||
child: &mut dyn Mountable<LeptosGtk>,
|
||||
) -> bool {
|
||||
child.mount(parent, Some(self.widget.as_ref()));
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
use any_spawner::Executor;
|
||||
use gtk::{prelude::*, Application, ApplicationWindow, Orientation};
|
||||
use leptos::prelude::*;
|
||||
use leptos_gtk::LeptosGtk;
|
||||
#[cfg(feature = "gtk")]
|
||||
use gtk::{
|
||||
glib::Value, prelude::*, Application, ApplicationWindow, Orientation,
|
||||
Widget,
|
||||
};
|
||||
#[cfg(feature = "wasm")]
|
||||
use leptos::tachys::{dom::body, html::element, html::event as ev};
|
||||
use leptos::{
|
||||
logging,
|
||||
prelude::*,
|
||||
reactive_graph::{effect::Effect, owner::Owner, signal::RwSignal},
|
||||
Executor, For, ForProps,
|
||||
};
|
||||
#[cfg(feature = "gtk")]
|
||||
use leptos_gtk::{Element, LGtkWidget, LeptosGtk};
|
||||
use std::{mem, thread, time::Duration};
|
||||
#[cfg(feature = "gtk")]
|
||||
mod leptos_gtk;
|
||||
|
||||
const APP_ID: &str = "dev.leptos.Counter";
|
||||
@@ -10,39 +22,59 @@ const APP_ID: &str = "dev.leptos.Counter";
|
||||
// Basic GTK app setup from https://gtk-rs.org/gtk4-rs/stable/latest/book/hello_world.html
|
||||
fn main() {
|
||||
// use the glib event loop to power the reactive system
|
||||
_ = Executor::init_glib();
|
||||
let app = Application::builder().application_id(APP_ID).build();
|
||||
#[cfg(feature = "gtk")]
|
||||
{
|
||||
_ = Executor::init_glib();
|
||||
let app = Application::builder().application_id(APP_ID).build();
|
||||
|
||||
app.connect_startup(|_| load_css());
|
||||
app.connect_startup(|_| load_css());
|
||||
|
||||
app.connect_activate(|app| {
|
||||
// Connect to "activate" signal of `app`
|
||||
app.connect_activate(|app| {
|
||||
// Connect to "activate" signal of `app`
|
||||
let owner = Owner::new();
|
||||
let view = owner.with(ui);
|
||||
let (root, state) = leptos_gtk::root(view);
|
||||
|
||||
let window = ApplicationWindow::builder()
|
||||
.application(app)
|
||||
.title("TachyGTK")
|
||||
.child(&root)
|
||||
.build();
|
||||
// Present window
|
||||
window.present();
|
||||
mem::forget((owner, state));
|
||||
});
|
||||
|
||||
app.run();
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "wasm", not(feature = "gtk")))]
|
||||
{
|
||||
console_error_panic_hook::set_once();
|
||||
_ = Executor::init_wasm_bindgen();
|
||||
let owner = Owner::new();
|
||||
let view = owner.with(ui);
|
||||
let (root, state) = leptos_gtk::root(view);
|
||||
|
||||
let window = ApplicationWindow::builder()
|
||||
.application(app)
|
||||
.title("TachyGTK")
|
||||
.child(&root)
|
||||
.build();
|
||||
// Present window
|
||||
window.present();
|
||||
let mut state = view.build();
|
||||
state.mount(&body().into(), None);
|
||||
mem::forget((owner, state));
|
||||
});
|
||||
|
||||
app.run();
|
||||
}
|
||||
}
|
||||
|
||||
fn ui() -> impl Render<LeptosGtk> {
|
||||
#[cfg(feature = "gtk")]
|
||||
type Rndr = LeptosGtk;
|
||||
#[cfg(all(feature = "wasm", not(feature = "gtk")))]
|
||||
type Rndr = Dom;
|
||||
|
||||
fn ui() -> impl Render<Rndr> {
|
||||
let value = RwSignal::new(0);
|
||||
let rows = RwSignal::new(vec![1, 2, 3, 4, 5]);
|
||||
|
||||
Effect::new(move |_| {
|
||||
println!("value = {}", value.get());
|
||||
logging::log!("value = {}", value.get());
|
||||
});
|
||||
|
||||
// just an example of multithreaded reactivity
|
||||
#[cfg(feature = "gtk")]
|
||||
thread::spawn(move || loop {
|
||||
thread::sleep(Duration::from_millis(250));
|
||||
value.update(|n| *n += 1);
|
||||
@@ -50,10 +82,7 @@ fn ui() -> impl Render<LeptosGtk> {
|
||||
|
||||
vstack((
|
||||
hstack((
|
||||
button("-1", move || {
|
||||
println!("clicked -1");
|
||||
value.update(|n| *n -= 1);
|
||||
}),
|
||||
button("-1", move || value.update(|n| *n -= 1)),
|
||||
move || value.get().to_string(),
|
||||
button("+1", move || value.update(|n| *n += 1)),
|
||||
)),
|
||||
@@ -62,36 +91,75 @@ fn ui() -> impl Render<LeptosGtk> {
|
||||
items.swap(1, 3);
|
||||
})
|
||||
}),
|
||||
hstack(rows),
|
||||
hstack(For(ForProps::builder()
|
||||
.each(move || rows.get())
|
||||
.key(|k| *k)
|
||||
.children(|v| v)
|
||||
.build())),
|
||||
))
|
||||
}
|
||||
|
||||
fn button(
|
||||
label: impl Render<LeptosGtk>,
|
||||
label: impl Render<Rndr>,
|
||||
callback: impl Fn() + Send + Sync + 'static,
|
||||
) -> impl Render<LeptosGtk> {
|
||||
leptos_gtk::button()
|
||||
.child(label)
|
||||
.connect("clicked", move |_| {
|
||||
callback();
|
||||
None
|
||||
})
|
||||
) -> impl Render<Rndr> {
|
||||
#[cfg(feature = "gtk")]
|
||||
{
|
||||
leptos_gtk::button()
|
||||
.child(label)
|
||||
.connect("clicked", move |_| {
|
||||
callback();
|
||||
None
|
||||
})
|
||||
}
|
||||
#[cfg(all(feature = "wasm", not(feature = "gtk")))]
|
||||
{
|
||||
element::button()
|
||||
.on(ev::click, move |_| callback())
|
||||
.child(label)
|
||||
}
|
||||
}
|
||||
|
||||
fn vstack(children: impl Render<LeptosGtk>) -> impl Render<LeptosGtk> {
|
||||
leptos_gtk::r#box()
|
||||
.orientation(Orientation::Vertical)
|
||||
.spacing(12)
|
||||
.child(children)
|
||||
fn vstack(children: impl Render<Rndr>) -> impl Render<Rndr> {
|
||||
#[cfg(feature = "gtk")]
|
||||
{
|
||||
leptos_gtk::r#box()
|
||||
.orientation(Orientation::Vertical)
|
||||
.spacing(12)
|
||||
.child(children)
|
||||
}
|
||||
#[cfg(all(feature = "wasm", not(feature = "gtk")))]
|
||||
{
|
||||
element::div()
|
||||
.style(("display", "flex"))
|
||||
.style(("flex-direction", "column"))
|
||||
.style(("align-items", "center"))
|
||||
.style(("justify-content", "center"))
|
||||
.style(("margin", "1rem"))
|
||||
.child(children)
|
||||
}
|
||||
}
|
||||
|
||||
fn hstack(children: impl Render<LeptosGtk>) -> impl Render<LeptosGtk> {
|
||||
leptos_gtk::r#box()
|
||||
.orientation(Orientation::Horizontal)
|
||||
.spacing(12)
|
||||
.child(children)
|
||||
fn hstack(children: impl Render<Rndr>) -> impl Render<Rndr> {
|
||||
#[cfg(feature = "gtk")]
|
||||
{
|
||||
leptos_gtk::r#box()
|
||||
.orientation(Orientation::Horizontal)
|
||||
.spacing(12)
|
||||
.child(children)
|
||||
}
|
||||
#[cfg(all(feature = "wasm", not(feature = "gtk")))]
|
||||
{
|
||||
element::div()
|
||||
.style(("display", "flex"))
|
||||
.style(("align-items", "center"))
|
||||
.style(("justify-content", "center"))
|
||||
.style(("margin", "1rem"))
|
||||
.child(children)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gtk")]
|
||||
fn load_css() {
|
||||
use gtk::{gdk::Display, CssProvider};
|
||||
|
||||
|
||||
@@ -13,27 +13,31 @@ panic = "abort"
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
actix-files = { version = "0.6.6", optional = true }
|
||||
actix-web = { version = "4.8", optional = true, features = ["macros"] }
|
||||
console_log = "1.0"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
actix-files = { version = "0.6", optional = true }
|
||||
actix-web = { version = "4", optional = true, features = ["macros"] }
|
||||
console_log = "1"
|
||||
console_error_panic_hook = "0.1"
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_actix = { path = "../../integrations/actix", optional = true }
|
||||
leptos_router = { path = "../../router" }
|
||||
log = "0.4.22"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
gloo-net = { version = "0.6.0", features = ["http"] }
|
||||
reqwest = { version = "0.12.5", features = ["json"] }
|
||||
wasm-bindgen = "0.2.93"
|
||||
web-sys = { version = "0.3.70", features = ["AbortController", "AbortSignal"] }
|
||||
log = "0.4"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
gloo-net = { version = "0.2", features = ["http"] }
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
wasm-bindgen = "0.2"
|
||||
web-sys = { version = "0.3", features = ["AbortController", "AbortSignal"] }
|
||||
send_wrapper = "0.6.0"
|
||||
|
||||
[features]
|
||||
default = ["csr"]
|
||||
csr = ["leptos/csr"]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = ["dep:actix-files", "dep:actix-web", "dep:leptos_actix", "leptos/ssr"]
|
||||
ssr = [
|
||||
"dep:actix-files",
|
||||
"dep:actix-web",
|
||||
"dep:leptos_actix",
|
||||
"leptos/ssr",
|
||||
]
|
||||
|
||||
[profile.wasm-release]
|
||||
inherits = "release"
|
||||
|
||||
@@ -20,7 +20,7 @@ pub fn Story() -> impl IntoView {
|
||||
},
|
||||
);
|
||||
|
||||
Suspense(SuspenseProps::builder().fallback(|| "Loading...").children(ToChildren::to_children(move || Suspend::new(async move {
|
||||
Suspense(SuspenseProps::builder().fallback(|| "Loading...").children(ToChildren::to_children(move || Suspend(async move {
|
||||
match story.await.clone() {
|
||||
None => Either::Left("Story not found."),
|
||||
Some(story) => {
|
||||
|
||||
@@ -19,7 +19,7 @@ pub fn User() -> impl IntoView {
|
||||
view! {
|
||||
<div class="user-view">
|
||||
<Suspense fallback=|| view! { "Loading..." }>
|
||||
{move || Suspend::new(async move { match user.await.clone() {
|
||||
{move || Suspend(async move { match user.await.clone() {
|
||||
None => Either::Left(view! { <h1>"User not found."</h1> }),
|
||||
Some(user) => Either::Right(view! {
|
||||
<div>
|
||||
|
||||
@@ -11,22 +11,22 @@ codegen-units = 1
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
console_error_panic_hook = "0.1"
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos_axum = { path = "../../integrations/axum", optional = true }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_router = { path = "../../router" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tracing = "0.1.40"
|
||||
gloo-net = { version = "0.6.0", features = ["http"] }
|
||||
reqwest = { version = "0.12.5", features = ["json"] }
|
||||
axum = { version = "0.7.5", optional = true }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
tower-http = { version = "0.5.2", features = ["fs"], optional = true }
|
||||
tokio = { version = "1.39", features = ["full"], optional = true }
|
||||
http = { version = "1.1", optional = true }
|
||||
web-sys = { version = "0.3.70", features = ["AbortController", "AbortSignal"] }
|
||||
wasm-bindgen = "0.2.93"
|
||||
tracing = "0.1"
|
||||
gloo-net = { version = "0.4", features = ["http"] }
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
axum = { version = "0.7", optional = true }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs"], optional = true }
|
||||
tokio = { version = "1", features = ["full"], optional = true }
|
||||
http = { version = "1.0", optional = true }
|
||||
web-sys = { version = "0.3", features = ["AbortController", "AbortSignal"] }
|
||||
wasm-bindgen = "0.2"
|
||||
send_wrapper = { version = "0.6.0", features = ["futures"] }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -20,7 +20,7 @@ pub fn Story() -> impl IntoView {
|
||||
},
|
||||
);
|
||||
|
||||
Suspense(SuspenseProps::builder().fallback(|| "Loading...").children(ToChildren::to_children(move || Suspend::new(async move {
|
||||
Suspense(SuspenseProps::builder().fallback(|| "Loading...").children(ToChildren::to_children(move || Suspend(async move {
|
||||
match story.await.clone() {
|
||||
None => Either::Left("Story not found."),
|
||||
Some(story) => {
|
||||
|
||||
@@ -19,7 +19,7 @@ pub fn User() -> impl IntoView {
|
||||
view! {
|
||||
<div class="user-view">
|
||||
<Suspense fallback=|| view! { "Loading..." }>
|
||||
{move || Suspend::new(async move { match user.await.clone() {
|
||||
{move || Suspend(async move { match user.await.clone() {
|
||||
None => Either::Left(view! { <h1>"User not found."</h1> }),
|
||||
Some(user) => Either::Right(view! {
|
||||
<div>
|
||||
|
||||
@@ -11,35 +11,34 @@ codegen-units = 1
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
leptos = { path = "../../leptos", features = ["experimental-islands"] }
|
||||
console_error_panic_hook = "0.1"
|
||||
leptos = { path = "../../leptos", features = [
|
||||
"experimental-islands",
|
||||
] }
|
||||
leptos_axum = { path = "../../integrations/axum", optional = true }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_router = { path = "../../router" }
|
||||
leptos_router = { path = "../../router"}
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tracing = "0.1.40"
|
||||
gloo-net = { version = "0.6.0", features = ["http"] }
|
||||
reqwest = { version = "0.12.5", features = ["json"] }
|
||||
axum = { version = "0.7.5", optional = true, features = ["http2"] }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
tower-http = { version = "0.5.2", features = [
|
||||
tracing = "0.1"
|
||||
gloo-net = { version = "0.4", features = ["http"] }
|
||||
reqwest = { version = "0.11", features = ["json"] }
|
||||
axum = { version = "0.7", optional = true, features = ["http2"] }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = [
|
||||
"fs",
|
||||
"compression-gzip",
|
||||
"compression-br",
|
||||
], optional = true }
|
||||
tokio = { version = "1.39", features = ["full"], optional = true }
|
||||
http = { version = "1.1", optional = true }
|
||||
web-sys = { version = "0.3.70", features = ["AbortController", "AbortSignal"] }
|
||||
wasm-bindgen = "0.2.93"
|
||||
lazy_static = "1.5"
|
||||
rust-embed = { version = "8.5", features = [
|
||||
"axum",
|
||||
"mime_guess",
|
||||
"tokio",
|
||||
], optional = true }
|
||||
mime_guess = { version = "2.0", optional = true }
|
||||
tokio = { version = "1", features = ["full"], optional = true }
|
||||
http = { version = "1.0", optional = true }
|
||||
web-sys = { version = "0.3", features = ["AbortController", "AbortSignal"] }
|
||||
wasm-bindgen = "0.2"
|
||||
lazy_static = "1.4.0"
|
||||
rust-embed = { version = "8", features = ["axum", "mime_guess", "tokio"], optional = true }
|
||||
mime_guess = { version = "2.0.4", optional = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
csr = ["leptos/csr"]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
|
||||
@@ -26,7 +26,7 @@ pub fn Story() -> impl IntoView {
|
||||
},
|
||||
);
|
||||
|
||||
Suspense(SuspenseProps::builder().fallback(|| "Loading...").children(ToChildren::to_children(move || Suspend::new(async move {
|
||||
Suspense(SuspenseProps::builder().fallback(|| "Loading...").children(ToChildren::to_children(move || Suspend(async move {
|
||||
match story.await.ok().flatten() {
|
||||
None => Either::Left("Story not found."),
|
||||
Some(story) => {
|
||||
|
||||
@@ -26,7 +26,7 @@ pub fn User() -> impl IntoView {
|
||||
view! {
|
||||
<div class="user-view">
|
||||
<Suspense fallback=|| view! { "Loading..." }>
|
||||
{move || Suspend::new(async move { match user.await.ok().flatten() {
|
||||
{move || Suspend(async move { match user.await.ok().flatten() {
|
||||
None => Either::Left(view! { <h1>"User not found."</h1> }),
|
||||
Some(user) => Either::Right(view! {
|
||||
<div>
|
||||
|
||||
@@ -11,30 +11,29 @@ codegen-units = 1
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
console_error_panic_hook = "0.1"
|
||||
console_log = "1.0"
|
||||
log = "0.4.22"
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos_axum = { path = "../../integrations/axum", default-features = false, optional = true }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_router = { path = "../../router" }
|
||||
leptos_server = { path = "../../leptos_server", optional = true }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tracing = "0.1.40"
|
||||
gloo-net = { version = "0.6.0", features = ["http"] }
|
||||
reqwest = { version = "0.12.5", features = ["json"] }
|
||||
axum = { version = "0.7.5", default-features = false, optional = true }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
http = { version = "1.1", optional = true }
|
||||
web-sys = { version = "0.3.70", features = [
|
||||
tracing = "0.1"
|
||||
gloo-net = { version = "0.5", features = ["http"] }
|
||||
reqwest = { version = "0.12", features = ["json"] }
|
||||
axum = { version = "0.7", default-features = false, optional = true }
|
||||
tower = { version = "0.4", optional = true }
|
||||
http = { version = "1.0", optional = true }
|
||||
web-sys = { version = "0.3", features = [
|
||||
"AbortController",
|
||||
"AbortSignal",
|
||||
"Request",
|
||||
"Response",
|
||||
] }
|
||||
getrandom = { version = "0.2.15", features = ["js"] }
|
||||
wasm-bindgen = "0.2.93"
|
||||
wasm-bindgen-futures = { version = "0.4.42", features = [
|
||||
getrandom = { version = "0.2.7", features = ["js"] }
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen-futures = { version = "0.4.37", features = [
|
||||
"futures-core-03-stream",
|
||||
], optional = true }
|
||||
axum-js-fetch = { git = "https://github.com/seanaye/axum-js-fetch", optional = true }
|
||||
|
||||
25
examples/hackernews_js_fetch/src/error_template.rs
Normal file
25
examples/hackernews_js_fetch/src/error_template.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use leptos::{view, Errors, For, IntoView, RwSignal, SignalGet, View};
|
||||
|
||||
// A basic function to display errors served by the error boundaries. Feel free to do more complicated things
|
||||
// here than just displaying them
|
||||
pub fn error_template(errors: Option<RwSignal<Errors>>) -> View {
|
||||
let Some(errors) = errors else {
|
||||
panic!("No Errors found and we expected errors!");
|
||||
};
|
||||
|
||||
view! {
|
||||
<h1>"Errors"</h1>
|
||||
<For
|
||||
// a function that returns the items we're iterating over; a signal is fine
|
||||
each=move || errors.get()
|
||||
// a unique key for each item as a reference
|
||||
key=|(key, _)| key.clone()
|
||||
// renders each item to a view
|
||||
children=move |(_, error)| {
|
||||
let error_string = error.to_string();
|
||||
view! { <p>"Error: " {error_string}</p> }
|
||||
}
|
||||
/>
|
||||
}
|
||||
.into_view()
|
||||
}
|
||||
68
examples/hackernews_js_fetch/src/handlers.rs
Normal file
68
examples/hackernews_js_fetch/src/handlers.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use axum::{
|
||||
body::Body,
|
||||
http::{Request, Response, StatusCode, Uri},
|
||||
response::IntoResponse,
|
||||
};
|
||||
use tower::ServiceExt;
|
||||
use tower_http::services::ServeDir;
|
||||
|
||||
pub async fn file_handler(
|
||||
uri: Uri,
|
||||
) -> Result<Response<Body>, (StatusCode, String)> {
|
||||
let res = get_static_file(uri.clone(), "/pkg").await?;
|
||||
|
||||
if res.status() == StatusCode::NOT_FOUND {
|
||||
// try with `.html`
|
||||
// TODO: handle if the Uri has query parameters
|
||||
match format!("{}.html", uri).parse() {
|
||||
Ok(uri_html) => get_static_file(uri_html, "/pkg").await,
|
||||
Err(_) => Err((
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Invalid URI".to_string(),
|
||||
)),
|
||||
}
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_static_file_handler(
|
||||
uri: Uri,
|
||||
) -> Result<Response<Body>, (StatusCode, String)> {
|
||||
let res = get_static_file(uri.clone(), "/public").await?;
|
||||
|
||||
if res.status() == StatusCode::NOT_FOUND {
|
||||
Err((StatusCode::INTERNAL_SERVER_ERROR, "Invalid URI".to_string()))
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_static_file(
|
||||
uri: Uri,
|
||||
base: &str,
|
||||
) -> Result<Response<Body>, (StatusCode, String)> {
|
||||
let req = Request::builder().uri(&uri).body(Body::empty()).unwrap();
|
||||
|
||||
// `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot`
|
||||
// When run normally, the root should be the crate root
|
||||
if base == "/public" {
|
||||
match ServeDir::new("./public").oneshot(req).await {
|
||||
Ok(res) => Ok(res.into_response()),
|
||||
Err(err) => Err((
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("Something went wrong: {}", err),
|
||||
)),
|
||||
}
|
||||
} else if base == "/pkg" {
|
||||
match ServeDir::new("./pkg").oneshot(req).await {
|
||||
Ok(res) => Ok(res.into_response()),
|
||||
Err(err) => Err((
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
format!("Something went wrong: {}", err),
|
||||
)),
|
||||
}
|
||||
} else {
|
||||
Err((StatusCode::NOT_FOUND, "Not Found".to_string()))
|
||||
}
|
||||
}
|
||||
@@ -65,10 +65,10 @@ pub fn hydrate() {
|
||||
#[cfg(feature = "ssr")]
|
||||
mod ssr_imports {
|
||||
use crate::{shell, App};
|
||||
use axum::Router;
|
||||
use axum::{routing::post, Router};
|
||||
use leptos::prelude::*;
|
||||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
use log::{info, Level};
|
||||
use tracing::log::{info, Level};
|
||||
use wasm_bindgen::prelude::wasm_bindgen;
|
||||
|
||||
#[wasm_bindgen]
|
||||
@@ -84,15 +84,15 @@ mod ssr_imports {
|
||||
.output_name("client")
|
||||
.site_pkg_dir("pkg")
|
||||
.build();
|
||||
|
||||
let routes = generate_route_list(App);
|
||||
|
||||
// build our application with a route
|
||||
let app = Router::new()
|
||||
let app: axum::Router<()> = Router::new()
|
||||
.leptos_routes(&leptos_options, routes, {
|
||||
let leptos_options = leptos_options.clone();
|
||||
move || shell(leptos_options.clone())
|
||||
let options = leptos_options.clone();
|
||||
move || shell(options.clone())
|
||||
})
|
||||
.route("/api/*fn_name", post(leptos_axum::handle_server_fns))
|
||||
.with_state(leptos_options);
|
||||
|
||||
info!("creating handler instance");
|
||||
|
||||
@@ -23,7 +23,7 @@ pub fn Story() -> impl IntoView {
|
||||
},
|
||||
);
|
||||
|
||||
Suspense(SuspenseProps::builder().fallback(|| "Loading...").children(ToChildren::to_children(move || Suspend::new(async move {
|
||||
Suspense(SuspenseProps::builder().fallback(|| "Loading...").children(ToChildren::to_children(move || Suspend(async move {
|
||||
match story.await.clone() {
|
||||
None => Either::Left("Story not found."),
|
||||
Some(story) => {
|
||||
|
||||
@@ -23,7 +23,7 @@ pub fn User() -> impl IntoView {
|
||||
<Suspense fallback=|| {
|
||||
view! { "Loading..." }
|
||||
}>
|
||||
{move || Suspend::new(async move {
|
||||
{move || Suspend(async move {
|
||||
match user.await.clone() {
|
||||
None => Either::Left(view! { <h1>"User not found."</h1> }),
|
||||
Some(user) => {
|
||||
|
||||
@@ -7,32 +7,32 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
futures = "0.3.30"
|
||||
http = "1.1"
|
||||
console_error_panic_hook = "0.1"
|
||||
futures = "0.3"
|
||||
http = "1.0"
|
||||
leptos = { path = "../../leptos", features = [
|
||||
"tracing",
|
||||
"experimental-islands",
|
||||
"tracing",
|
||||
"experimental-islands",
|
||||
] }
|
||||
server_fn = { path = "../../server_fn", features = ["serde-lite"] }
|
||||
leptos_axum = { path = "../../integrations/axum", optional = true }
|
||||
log = "0.4.22"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
axum = { version = "0.7.5", optional = true }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
tower-http = { version = "0.5.2", features = ["fs"], optional = true }
|
||||
tokio = { version = "1.39", features = ["full"], optional = true }
|
||||
wasm-bindgen = "0.2.93"
|
||||
log = "0.4"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
axum = { version = "0.7", optional = true }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs"], optional = true }
|
||||
tokio = { version = "1", features = ["full"], optional = true }
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
"dep:axum",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"leptos/ssr",
|
||||
"dep:leptos_axum",
|
||||
"dep:axum",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"leptos/ssr",
|
||||
"dep:leptos_axum",
|
||||
]
|
||||
|
||||
[profile.wasm-release]
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
[package]
|
||||
name = "islands"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
futures = "0.3.30"
|
||||
http = "1.1"
|
||||
leptos = { path = "../../leptos", features = [
|
||||
"tracing",
|
||||
"experimental-islands",
|
||||
] }
|
||||
leptos_router = { path = "../../router" }
|
||||
server_fn = { path = "../../server_fn", features = ["serde-lite"] }
|
||||
leptos_axum = { path = "../../integrations/axum", features = [
|
||||
"islands-router",
|
||||
], optional = true }
|
||||
log = "0.4.22"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
axum = { version = "0.7.5", optional = true }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
tower-http = { version = "0.5.2", features = ["fs"], optional = true }
|
||||
tokio = { version = "1.39", features = ["full"], optional = true }
|
||||
wasm-bindgen = "0.2.93"
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
"dep:axum",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"leptos/ssr",
|
||||
"dep:leptos_axum",
|
||||
]
|
||||
|
||||
[profile.wasm-release]
|
||||
inherits = "release"
|
||||
opt-level = 'z'
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
panic = "abort"
|
||||
|
||||
[package.metadata.cargo-all-features]
|
||||
denylist = ["axum", "tower", "tower-http", "tokio", "sqlx", "leptos_axum"]
|
||||
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
|
||||
|
||||
[package.metadata.leptos]
|
||||
# The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name
|
||||
output-name = "islands"
|
||||
# The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup.
|
||||
site-root = "target/site"
|
||||
# The site-root relative folder where all compiled output (JS, WASM and CSS) is written
|
||||
# Defaults to pkg
|
||||
site-pkg-dir = "pkg"
|
||||
# [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to <site-root>/<site-pkg>/app.css
|
||||
style-file = "./style.css"
|
||||
# [Optional] Files in the asset-dir will be copied to the site-root directory
|
||||
assets-dir = "public"
|
||||
# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup.
|
||||
site-addr = "127.0.0.1:3000"
|
||||
# The port to use for automatic reload monitoring
|
||||
reload-port = 3001
|
||||
# The browserlist query used for optimizing the CSS.
|
||||
browserquery = "defaults"
|
||||
# Set by cargo-leptos watch when building with that tool. Controls whether autoreload JS will be included in the head
|
||||
watch = false
|
||||
# The environment Leptos will run in, usually either "DEV" or "PROD"
|
||||
env = "DEV"
|
||||
# The features to use when compiling the bin target
|
||||
#
|
||||
# Optional. Can be over-ridden with the command line parameter --bin-features
|
||||
bin-features = ["ssr"]
|
||||
|
||||
# If the --no-default-features flag should be used when compiling the bin target
|
||||
#
|
||||
# Optional. Defaults to false.
|
||||
bin-default-features = false
|
||||
|
||||
# The features to use when compiling the lib target
|
||||
#
|
||||
# Optional. Can be over-ridden with the command line parameter --lib-features
|
||||
lib-features = ["hydrate"]
|
||||
|
||||
# If the --no-default-features flag should be used when compiling the lib target
|
||||
#
|
||||
# Optional. Defaults to false.
|
||||
lib-default-features = false
|
||||
|
||||
lib-profile-release = "wasm-release"
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Greg Johnston
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,4 +0,0 @@
|
||||
extend = [
|
||||
{ path = "../cargo-make/main.toml" },
|
||||
{ path = "../cargo-make/cargo-leptos.toml" },
|
||||
]
|
||||
@@ -1,19 +0,0 @@
|
||||
# Leptos Todo App Sqlite with Axum
|
||||
|
||||
This example creates a basic todo app with an Axum backend that uses Leptos' server functions to call sqlx from the client and seamlessly run it on the server.
|
||||
|
||||
## Getting Started
|
||||
|
||||
See the [Examples README](../README.md) for setup and run instructions.
|
||||
|
||||
## E2E Testing
|
||||
|
||||
See the [E2E README](./e2e/README.md) for more information about the testing strategy.
|
||||
|
||||
## Rendering
|
||||
|
||||
See the [SSR Notes](../SSR_NOTES.md) for more information about Server Side Rendering.
|
||||
|
||||
## Quick Start
|
||||
|
||||
Run `cargo leptos watch` to run this example.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,135 +0,0 @@
|
||||
window.addEventListener("click", async (ev) => {
|
||||
// confirm that this is an <a> that meets our requirements
|
||||
if (
|
||||
ev.defaultPrevented ||
|
||||
ev.button !== 0 ||
|
||||
ev.metaKey ||
|
||||
ev.altKey ||
|
||||
ev.ctrlKey ||
|
||||
ev.shiftKey
|
||||
)
|
||||
return;
|
||||
|
||||
/** @type HTMLAnchorElement | undefined;*/
|
||||
const a = ev
|
||||
.composedPath()
|
||||
.find(el => el instanceof Node && el.nodeName.toUpperCase() === "A");
|
||||
|
||||
if (!a) return;
|
||||
|
||||
const svg = a.namespaceURI === "http://www.w3.org/2000/svg";
|
||||
const href = svg ? a.href.baseVal : a.href;
|
||||
const target = svg ? a.target.baseVal : a.target;
|
||||
if (target || (!href && !a.hasAttribute("state"))) return;
|
||||
|
||||
const rel = (a.getAttribute("rel") || "").split(/\s+/);
|
||||
if (a.hasAttribute("download") || (rel && rel.includes("external"))) return;
|
||||
|
||||
const url = svg ? new URL(href, document.baseURI) : new URL(href);
|
||||
if (
|
||||
url.origin !== window.location.origin // ||
|
||||
// TODO base
|
||||
//(basePath && url.pathname && !url.pathname.toLowerCase().startsWith(basePath.toLowerCase()))
|
||||
)
|
||||
return;
|
||||
|
||||
ev.preventDefault();
|
||||
|
||||
// fetch the new page
|
||||
const resp = await fetch(url);
|
||||
const htmlString = await resp.text();
|
||||
|
||||
// Use DOMParser to parse the HTML string
|
||||
const parser = new DOMParser();
|
||||
// TODO parse from the request stream instead?
|
||||
const doc = parser.parseFromString(htmlString, 'text/html');
|
||||
|
||||
// The 'doc' variable now contains the parsed DOM
|
||||
const transition = document.startViewTransition(async () => {
|
||||
const oldDocWalker = document.createTreeWalker(document);
|
||||
const newDocWalker = doc.createTreeWalker(doc);
|
||||
let oldNode = oldDocWalker.currentNode;
|
||||
let newNode = newDocWalker.currentNode;
|
||||
while(oldDocWalker.nextNode() && newDocWalker.nextNode()) {
|
||||
oldNode = oldDocWalker.currentNode;
|
||||
newNode = newDocWalker.currentNode;
|
||||
// if the nodes are different, we need to replace the old with the new
|
||||
// because of the typed view tree, this should never actually happen
|
||||
if (oldNode.nodeType !== newNode.nodeType) {
|
||||
oldNode.replaceWith(newNode);
|
||||
}
|
||||
// if it's a text node, just update the text with the new text
|
||||
else if (oldNode.nodeType === Node.TEXT_NODE) {
|
||||
oldNode.textContent = newNode.textContent;
|
||||
}
|
||||
// if it's an element, replace if it's a different tag, or update attributes
|
||||
else if (oldNode.nodeType === Node.ELEMENT_NODE) {
|
||||
/** @type Element */
|
||||
const oldEl = oldNode;
|
||||
/** @type Element */
|
||||
const newEl = newNode;
|
||||
if (oldEl.tagName !== newEl.tagName) {
|
||||
oldEl.replaceWith(newEl);
|
||||
}
|
||||
else {
|
||||
for(const attr of newEl.attributes) {
|
||||
oldEl.setAttribute(attr.name, attr.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
// we use comment "branch marker" nodes to distinguish between different branches in the statically-typed view tree
|
||||
// if one of these marker is hit, then there are two options
|
||||
// 1) it's the same branch, and we just keep walking until the end
|
||||
// 2) it's a different branch, in which case the old can be replaced with the new wholesale
|
||||
else if (oldNode.nodeType === Node.COMMENT_NODE) {
|
||||
const oldText = oldNode.textContent;
|
||||
const newText = newNode.textContent;
|
||||
if(oldText.startsWith("bo") && newText !== oldText) {
|
||||
oldDocWalker.nextNode();
|
||||
newDocWalker.nextNode();
|
||||
const oldRange = new Range();
|
||||
const newRange = new Range();
|
||||
let oldBranches = 1;
|
||||
let newBranches = 1;
|
||||
while(oldBranches > 0 && newBranches > 0) {
|
||||
if(oldDocWalker.nextNode() && newDocWalker.nextNode()) {
|
||||
console.log(oldDocWalker.currentNode, newDocWalker.currentNode);
|
||||
if(oldDocWalker.currentNode.nodeType === Node.COMMENT_NODE) {
|
||||
if(oldDocWalker.currentNode.textContent.startsWith("bo")) {
|
||||
oldBranches += 1;
|
||||
} else if(oldDocWalker.currentNode.textContent.startsWith("bc")) {
|
||||
|
||||
oldBranches -= 1;
|
||||
}
|
||||
}
|
||||
if(newDocWalker.currentNode.nodeType === Node.COMMENT_NODE) {
|
||||
if(newDocWalker.currentNode.textContent.startsWith("bo")) {
|
||||
newBranches += 1;
|
||||
} else if(newDocWalker.currentNode.textContent.startsWith("bc")) {
|
||||
|
||||
newBranches -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
oldRange.setStartAfter(oldNode);
|
||||
oldRange.setEndBefore(oldDocWalker.currentNode);
|
||||
newRange.setStartAfter(newNode);
|
||||
newRange.setEndBefore(newDocWalker.currentNode);
|
||||
const newContents = newRange.extractContents();
|
||||
oldRange.deleteContents();
|
||||
oldRange.insertNode(newContents);
|
||||
oldNode.replaceWith(newNode);
|
||||
oldDocWalker.currentNode.replaceWith(newDocWalker.currentNode);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
} }
|
||||
}
|
||||
});
|
||||
await transition;
|
||||
window.history.pushState(undefined, null, url);
|
||||
});
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "stable" # test change
|
||||
@@ -1,59 +0,0 @@
|
||||
use leptos::prelude::*;
|
||||
use leptos_router::{
|
||||
components::{FlatRoutes, Route, Router},
|
||||
StaticSegment,
|
||||
};
|
||||
|
||||
pub fn shell(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=options.clone()/>
|
||||
<HydrationScripts options=options islands=true/>
|
||||
<link rel="stylesheet" id="leptos" href="/pkg/islands.css"/>
|
||||
<link rel="shortcut icon" type="image/ico" href="/favicon.ico"/>
|
||||
</head>
|
||||
<body>
|
||||
<App/>
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn App() -> impl IntoView {
|
||||
view! {
|
||||
<script src="/routing.js"></script>
|
||||
<Router>
|
||||
<header>
|
||||
<h1>"My Application"</h1>
|
||||
</header>
|
||||
<nav>
|
||||
<a href="/">"Page A"</a>
|
||||
<a href="/b">"Page B"</a>
|
||||
</nav>
|
||||
<main>
|
||||
<p>
|
||||
<label>"Home Checkbox" <input type="checkbox"/></label>
|
||||
</p>
|
||||
<FlatRoutes fallback=|| "Not found.">
|
||||
<Route path=StaticSegment("") view=PageA/>
|
||||
<Route path=StaticSegment("b") view=PageB/>
|
||||
</FlatRoutes>
|
||||
</main>
|
||||
</Router>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn PageA() -> impl IntoView {
|
||||
view! { <label>"Page A" <input type="checkbox"/></label> }
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn PageB() -> impl IntoView {
|
||||
view! { <label>"Page B" <input type="checkbox"/></label> }
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
pub mod app;
|
||||
|
||||
#[cfg(feature = "hydrate")]
|
||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||
pub fn hydrate() {
|
||||
console_error_panic_hook::set_once();
|
||||
leptos::mount::hydrate_islands();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
use axum::Router;
|
||||
use islands::app::{shell, App};
|
||||
use leptos::prelude::*;
|
||||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// Setting this to None means we'll be using cargo-leptos and its env vars
|
||||
let conf = get_configuration(None).unwrap();
|
||||
let leptos_options = conf.leptos_options;
|
||||
let addr = leptos_options.site_addr;
|
||||
let routes = generate_route_list(App);
|
||||
|
||||
// build our application with a route
|
||||
let app = Router::new()
|
||||
.leptos_routes(&leptos_options, routes, {
|
||||
let leptos_options = leptos_options.clone();
|
||||
move || shell(leptos_options.clone())
|
||||
})
|
||||
.fallback(leptos_axum::file_and_error_handler(shell))
|
||||
.with_state(leptos_options);
|
||||
|
||||
// run our app with hyper
|
||||
// `axum::Server` is a re-export of `hyper::Server`
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
||||
println!("listening on http://{}", &addr);
|
||||
axum::serve(listener, app.into_make_service())
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
.pending {
|
||||
color: purple;
|
||||
}
|
||||
@@ -8,13 +8,13 @@ codegen-units = 1
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] } # for actual benchmarking, add `nightly` and `delegation` features
|
||||
leptos = { path = "../../leptos", features = ["csr"] } # for actual benchmarking, add `nightly` and `event-delegation` features
|
||||
# used in rand, but we need to enable js feature
|
||||
getrandom = { version = "0.2.15", features = ["js"] }
|
||||
getrandom = { version = "0.2.7", features = ["js"] }
|
||||
rand = { version = "0.8.5", features = ["small_rng"] }
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
web-sys = "0.3"
|
||||
|
||||
@@ -9,7 +9,7 @@ lto = true
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
console_log = "1.0"
|
||||
log = "0.4.22"
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
web-sys = "0.3.70"
|
||||
web-sys = "0.3"
|
||||
|
||||
@@ -5,12 +5,12 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
log = "0.4.22"
|
||||
console_log = "1.0"
|
||||
log = "0.4"
|
||||
console_log = "1"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
wasm-bindgen = "0.2.93"
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
wasm-bindgen = "0.2.93"
|
||||
web-sys = "0.3.70"
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
wasm-bindgen = "0.2"
|
||||
web-sys = "0.3"
|
||||
|
||||
@@ -10,16 +10,15 @@ codegen-units = 1
|
||||
panic = "abort"
|
||||
|
||||
[dependencies]
|
||||
console_log = "1.0"
|
||||
console_log = "1"
|
||||
leptos = { path = "../../leptos", features = ["csr", "tracing"] }
|
||||
leptos_router = { path = "../../router" } #, features = ["tracing"] }
|
||||
leptos_router_macro = { path = "../../router_macro" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
futures = "0.3.30"
|
||||
leptos_router = { path = "../../router" } #, features = ["tracing"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
futures = "0.3"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
tracing-subscriber = "0.3.18"
|
||||
tracing-subscriber-wasm = "0.1.0"
|
||||
tracing = "0.1.40"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
|
||||
@@ -9,9 +9,8 @@ use leptos_router::{
|
||||
},
|
||||
hooks::{use_navigate, use_params, use_query_map},
|
||||
params::Params,
|
||||
MatchNestedRoutes,
|
||||
MatchNestedRoutes, ParamSegment, StaticSegment,
|
||||
};
|
||||
use leptos_router_macro::path;
|
||||
use tracing::info;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
@@ -39,22 +38,27 @@ pub fn RouterExample() -> impl IntoView {
|
||||
<A href="/about">"About"</A>
|
||||
<A href="/settings">"Settings"</A>
|
||||
<A href="/redirect-home">"Redirect to Home"</A>
|
||||
<button on:click=move |_| {
|
||||
set_logged_in.update(|n| *n = !*n)
|
||||
}>{move || if logged_in.get() { "Log Out" } else { "Log In" }}</button>
|
||||
<button on:click=move |_| set_logged_in.update(|n| *n = !*n)>
|
||||
{move || if logged_in.get() {
|
||||
"Log Out"
|
||||
} else {
|
||||
"Log In"
|
||||
}}
|
||||
</button>
|
||||
</nav>
|
||||
<main>
|
||||
<Routes fallback=|| "This page could not be found.">
|
||||
// paths can be created using the path!() macro, or provided as types like
|
||||
// StaticSegment("about")
|
||||
<Route path=path!("about") view=About/>
|
||||
<Route path=StaticSegment("about") view=About/>
|
||||
<ProtectedRoute
|
||||
path=path!("settings")
|
||||
path=StaticSegment("settings")
|
||||
condition=move || Some(logged_in.get())
|
||||
redirect_path=|| "/"
|
||||
view=Settings
|
||||
/>
|
||||
<Route path=path!("redirect-home") view=|| view! { <Redirect path="/"/> }/>
|
||||
<Route
|
||||
path=StaticSegment("redirect-home")
|
||||
view=|| view! { <Redirect path="/"/> }
|
||||
/>
|
||||
<ContactRoutes/>
|
||||
</Routes>
|
||||
</main>
|
||||
@@ -67,12 +71,11 @@ pub fn RouterExample() -> impl IntoView {
|
||||
#[component]
|
||||
pub fn ContactRoutes() -> impl MatchNestedRoutes<Dom> + Clone {
|
||||
view! {
|
||||
<ParentRoute path=path!("") view=ContactList>
|
||||
<Route path=path!("/") view=|| "Select a contact."/>
|
||||
<Route path=path!("/:id") view=Contact/>
|
||||
<ParentRoute path=StaticSegment("") view=ContactList>
|
||||
<Route path=StaticSegment("") view=|| "Select a contact."/>
|
||||
<Route path=ParamSegment("id") view=Contact/>
|
||||
</ParentRoute>
|
||||
}
|
||||
.into_inner()
|
||||
}
|
||||
|
||||
#[component]
|
||||
@@ -93,7 +96,7 @@ pub fn ContactList() -> impl IntoView {
|
||||
get_contacts(search.get())
|
||||
});
|
||||
let contacts = move || {
|
||||
Suspend::new(async move {
|
||||
Suspend(async move {
|
||||
// this data doesn't change frequently so we can use .map().collect() instead of a keyed <For/>
|
||||
contacts.await
|
||||
.into_iter()
|
||||
@@ -152,7 +155,7 @@ pub fn Contact() -> impl IntoView {
|
||||
});
|
||||
|
||||
let contact_display = move || {
|
||||
Suspend::new(async move {
|
||||
Suspend(async move {
|
||||
match contact.await {
|
||||
None => Either::Left(
|
||||
view! { <p>"No contact with this ID was found."</p> },
|
||||
@@ -222,12 +225,7 @@ pub fn Settings() -> impl IntoView {
|
||||
<input type="text" name="last_name" placeholder="Last"/>
|
||||
</fieldset>
|
||||
<input type="submit"/>
|
||||
<p>
|
||||
"This uses the " <code>"<Form/>"</code>
|
||||
" component, which enhances forms by using client-side navigation for "
|
||||
<code>"GET"</code> " requests, and client-side requests for " <code>"POST"</code>
|
||||
" requests, without requiring a full page reload."
|
||||
</p>
|
||||
<p>"This uses the " <code>"<Form/>"</code> " component, which enhances forms by using client-side navigation for " <code>"GET"</code> " requests, and client-side requests for " <code>"POST"</code> " requests, without requiring a full page reload."</p>
|
||||
</Form>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,52 +7,45 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
futures = "0.3.30"
|
||||
http = "1.1"
|
||||
console_error_panic_hook = "0.1"
|
||||
futures = "0.3"
|
||||
http = "1.0"
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos_axum = { path = "../../integrations/axum", optional = true }
|
||||
server_fn = { path = "../../server_fn", features = [
|
||||
"serde-lite",
|
||||
"rkyv",
|
||||
"multipart",
|
||||
] }
|
||||
log = "0.4.22"
|
||||
simple_logger = "5.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
axum = { version = "0.7.5", optional = true }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
tower-http = { version = "0.5.2", features = [
|
||||
"fs",
|
||||
"tracing",
|
||||
"trace",
|
||||
], optional = true }
|
||||
tokio = { version = "1.39", features = ["full"], optional = true }
|
||||
server_fn = { path = "../../server_fn", features = ["serde-lite", "rkyv", "multipart"] }
|
||||
log = "0.4"
|
||||
simple_logger = "4.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
axum = { version = "0.7", optional = true }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs", "tracing", "trace"], optional = true }
|
||||
tokio = { version = "1", features = ["full"], optional = true }
|
||||
thiserror = "1.0"
|
||||
wasm-bindgen = "0.2.93"
|
||||
wasm-bindgen = "0.2"
|
||||
serde_toml = "0.0.1"
|
||||
toml = "0.8.19"
|
||||
web-sys = { version = "0.3.70", features = ["FileList", "File"] }
|
||||
strum = { version = "0.26.3", features = ["strum_macros", "derive"] }
|
||||
notify = { version = "6.1", optional = true }
|
||||
pin-project-lite = "0.2.14"
|
||||
dashmap = { version = "6.0", optional = true }
|
||||
once_cell = { version = "1.19", optional = true }
|
||||
async-broadcast = { version = "0.7.1", optional = true }
|
||||
toml = "0.8.8"
|
||||
web-sys = { version = "0.3.67", features = ["FileList", "File"] }
|
||||
strum = { version = "0.25.0", features = ["strum_macros", "derive"] }
|
||||
notify = { version = "6.1.1", optional = true }
|
||||
pin-project-lite = "0.2.13"
|
||||
dashmap = { version = "5.5.3", optional = true }
|
||||
once_cell = { version = "1.19.0", optional = true }
|
||||
async-broadcast = { version = "0.6.0", optional = true }
|
||||
send_wrapper = "0.6.0"
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
"dep:axum",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"leptos/ssr",
|
||||
"dep:leptos_axum",
|
||||
"dep:notify",
|
||||
"dep:dashmap",
|
||||
"dep:once_cell",
|
||||
"dep:async-broadcast",
|
||||
"dep:axum",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"leptos/ssr",
|
||||
"dep:leptos_axum",
|
||||
"dep:notify",
|
||||
"dep:dashmap",
|
||||
"dep:once_cell",
|
||||
"dep:async-broadcast",
|
||||
]
|
||||
|
||||
[package.metadata.cargo-all-features]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use futures::StreamExt;
|
||||
use http::Method;
|
||||
use leptos::{html::Input, prelude::*, spawn::spawn_local};
|
||||
use send_wrapper::SendWrapper;
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use server_fn::{
|
||||
client::{browser::BrowserClient, Client},
|
||||
@@ -361,9 +362,10 @@ pub fn FileUpload() -> impl IntoView {
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
let upload_action = Action::new_local(|data: &FormData| {
|
||||
let upload_action = Action::new(|data: &SendWrapper<FormData>| {
|
||||
let data = (**data).clone();
|
||||
// `MultipartData` implements `From<FormData>`
|
||||
file_length(data.clone().into())
|
||||
file_length(data.into())
|
||||
});
|
||||
|
||||
view! {
|
||||
@@ -373,15 +375,14 @@ pub fn FileUpload() -> impl IntoView {
|
||||
ev.prevent_default();
|
||||
let target = ev.target().unwrap().unchecked_into::<HtmlFormElement>();
|
||||
let form_data = FormData::new_with_form(&target).unwrap();
|
||||
upload_action.dispatch_local(form_data);
|
||||
upload_action.dispatch(SendWrapper::new(form_data));
|
||||
}>
|
||||
<input type="file" name="file_to_upload"/>
|
||||
<input type="submit"/>
|
||||
</form>
|
||||
<p>
|
||||
{move || {
|
||||
if upload_action.input_local().read().is_none() && upload_action.value().read().is_none()
|
||||
{
|
||||
if upload_action.input().get().is_none() && upload_action.value().get().is_none() {
|
||||
"Upload a file.".to_string()
|
||||
} else if upload_action.pending().get() {
|
||||
"Uploading...".to_string()
|
||||
|
||||
@@ -9,6 +9,6 @@ lto = true
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
console_log = "1.0"
|
||||
log = "0.4.22"
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
||||
@@ -7,20 +7,20 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
actix-files = { version = "0.6.6", optional = true }
|
||||
actix-web = { version = "4.8", optional = true, features = ["macros"] }
|
||||
console_error_panic_hook = "0.1.7"
|
||||
console_log = "1.0"
|
||||
lazy_static = "1.5"
|
||||
leptos = { path = "../../leptos" }
|
||||
actix-files = { version = "0.6", optional = true }
|
||||
actix-web = { version = "4", optional = true, features = ["macros"] }
|
||||
console_error_panic_hook = "0.1"
|
||||
console_log = "1"
|
||||
lazy_static = "1"
|
||||
leptos = { path = "../../leptos"}
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_actix = { path = "../../integrations/actix", optional = true }
|
||||
leptos_router = { path = "../../router" }
|
||||
log = "0.4.22"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1.39", features = ["time"] }
|
||||
wasm-bindgen = "0.2.93"
|
||||
log = "0.4"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
thiserror = "1"
|
||||
tokio = { version = "1", features = ["time"] }
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
|
||||
@@ -64,7 +64,7 @@ fn HomePage() -> impl IntoView {
|
||||
view! {
|
||||
<h1>"My Great Blog"</h1>
|
||||
<Suspense fallback=move || view! { <p>"Loading posts..."</p> }>
|
||||
<p>"number of posts: " {Suspend::new(async move { posts2.await })}</p>
|
||||
<p>"number of posts: " {Suspend(async move { posts2.await })}</p>
|
||||
</Suspense>
|
||||
<Suspense fallback=move || view! { <p>"Loading posts..."</p> }>
|
||||
<ul>
|
||||
@@ -105,7 +105,7 @@ fn Post() -> impl IntoView {
|
||||
}
|
||||
});
|
||||
|
||||
let post_view = Suspend::new(async move {
|
||||
let post_view = Suspend(async move {
|
||||
match post_resource.await.to_owned() {
|
||||
Ok(Ok(post)) => Ok(view! {
|
||||
<h1>{post.title.clone()}</h1>
|
||||
|
||||
@@ -7,39 +7,37 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
console_log = "1.0"
|
||||
lazy_static = "1.5"
|
||||
leptos = { path = "../../leptos", features = [
|
||||
"hydration",
|
||||
] } #"nightly", "hydration"] }
|
||||
console_error_panic_hook = "0.1"
|
||||
console_log = "1"
|
||||
lazy_static = "1"
|
||||
leptos = { path = "../../leptos", features = ["hydration" ] } #"nightly", "hydration"] }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_axum = { path = "../../integrations/axum", optional = true }
|
||||
leptos_router = { path = "../../router" }
|
||||
log = "0.4.22"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
thiserror = "1.0"
|
||||
axum = { version = "0.7.5", optional = true }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
tower-http = { version = "0.5.2", features = ["fs"], optional = true }
|
||||
tokio = { version = "1.39", features = [
|
||||
"rt-multi-thread",
|
||||
"macros",
|
||||
"time",
|
||||
log = "0.4"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
thiserror = "1"
|
||||
axum = { version = "0.7", optional = true }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs"], optional = true }
|
||||
tokio = { version = "1", features = [
|
||||
"rt-multi-thread",
|
||||
"macros",
|
||||
"time",
|
||||
], optional = true }
|
||||
wasm-bindgen = "0.2.93"
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
"dep:axum",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"leptos/ssr",
|
||||
"leptos_meta/ssr",
|
||||
"dep:leptos_axum",
|
||||
"leptos_router/ssr",
|
||||
"dep:axum",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"leptos/ssr",
|
||||
"leptos_meta/ssr",
|
||||
"dep:leptos_axum",
|
||||
"leptos_router/ssr",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
|
||||
@@ -20,7 +20,7 @@ pub fn shell(options: LeptosOptions) -> impl IntoView {
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<AutoReload options=options.clone()/>
|
||||
<AutoReload options=options.clone() />
|
||||
<HydrationScripts options/>
|
||||
<MetaTags/>
|
||||
</head>
|
||||
@@ -64,24 +64,15 @@ pub fn App() -> impl IntoView {
|
||||
<a href="/admin">"Admin"</a>
|
||||
<Transition>
|
||||
<ActionForm action=toggle_admin>
|
||||
<input
|
||||
type="hidden"
|
||||
name="is_admin"
|
||||
value=move || {
|
||||
(!is_admin.get().and_then(|n| n.ok()).unwrap_or_default())
|
||||
.to_string()
|
||||
}
|
||||
<input type="hidden" name="is_admin"
|
||||
value=move || (!is_admin.get().and_then(|n| n.ok()).unwrap_or_default()).to_string()
|
||||
/>
|
||||
|
||||
<button>
|
||||
{move || {
|
||||
if is_admin.get().and_then(Result::ok).unwrap_or_default() {
|
||||
"Log Out"
|
||||
} else {
|
||||
"Log In"
|
||||
}
|
||||
{move || if is_admin.get().and_then(Result::ok).unwrap_or_default() {
|
||||
"Log Out"
|
||||
} else {
|
||||
"Log In"
|
||||
}}
|
||||
|
||||
</button>
|
||||
</ActionForm>
|
||||
</Transition>
|
||||
@@ -140,7 +131,7 @@ fn HomePage() -> impl IntoView {
|
||||
view! {
|
||||
<h1>"My Great Blog"</h1>
|
||||
<Suspense fallback=move || view! { <p>"Loading posts..."</p> }>
|
||||
<p>"number of posts: " {Suspend::new(async move { posts2.await })}</p>
|
||||
<p>"number of posts: " {Suspend(async move { posts2.await })}</p>
|
||||
</Suspense>
|
||||
<Suspense fallback=move || view! { <p>"Loading posts..."</p> }>
|
||||
<ul>
|
||||
@@ -148,15 +139,9 @@ fn HomePage() -> impl IntoView {
|
||||
<li>
|
||||
<a href=format!("/post/{}", post.id)>{post.title.clone()}</a>
|
||||
"|"
|
||||
<a href=format!(
|
||||
"/post_in_order/{}",
|
||||
post.id,
|
||||
)>{post.title.clone()} "(in order)"</a>
|
||||
<a href=format!("/post_in_order/{}", post.id)>{post.title.clone()} "(in order)"</a>
|
||||
"|"
|
||||
<a href=format!(
|
||||
"/post_partially_blocked/{}",
|
||||
post.id,
|
||||
)>{post.title} "(partially blocked)"</a>
|
||||
<a href=format!("/post_partially_blocked/{}", post.id)>{post.title} "(partially blocked)"</a>
|
||||
</li>
|
||||
</For>
|
||||
</ul>
|
||||
@@ -197,7 +182,7 @@ fn Post() -> impl IntoView {
|
||||
}
|
||||
});
|
||||
|
||||
let post_view = Suspend::new(async move {
|
||||
let post_view = Suspend(async move {
|
||||
match post_resource.await {
|
||||
Ok(Ok(post)) => {
|
||||
Ok(view! {
|
||||
@@ -214,16 +199,17 @@ fn Post() -> impl IntoView {
|
||||
_ => Err(PostError::ServerError),
|
||||
}
|
||||
});
|
||||
let comments_view = Suspend::new(async move {
|
||||
let comments_view = Suspend(async move {
|
||||
match comments_resource.await {
|
||||
Ok(comments) => Ok(view! {
|
||||
<h1>"Comments"</h1>
|
||||
<ul>
|
||||
{comments
|
||||
.into_iter()
|
||||
.map(|comment| view! { <li>{comment}</li> })
|
||||
.collect_view()}
|
||||
|
||||
{comments.into_iter()
|
||||
.map(|comment| view! {
|
||||
<li>{comment}</li>
|
||||
})
|
||||
.collect_view()
|
||||
}
|
||||
</ul>
|
||||
}),
|
||||
_ => Err(PostError::ServerError),
|
||||
@@ -251,13 +237,17 @@ fn Post() -> impl IntoView {
|
||||
}
|
||||
}>{post_view}</ErrorBoundary>
|
||||
</Suspense>
|
||||
<Suspense fallback=move || view! { <p>"Loading comments..."</p> }>{comments_view}</Suspense>
|
||||
<Suspense fallback=move || view! { <p>"Loading comments..."</p> }>
|
||||
{comments_view}
|
||||
</Suspense>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn Admin() -> impl IntoView {
|
||||
view! { <p>"You can only see this page if you're logged in."</p> }
|
||||
view! {
|
||||
<p>"You can only see this page if you're logged in."</p>
|
||||
}
|
||||
}
|
||||
|
||||
// Dummy API
|
||||
|
||||
@@ -15,6 +15,6 @@ reactive_stores_macro = { path = "../../reactive_stores_macro" }
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen = "0.2.93"
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
web-sys = "0.3.70"
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
web-sys = "0.3"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use leptos::prelude::*;
|
||||
use reactive_stores::{Field, Store, StoreFieldIterator};
|
||||
use reactive_stores::{
|
||||
AtIndex, Store, StoreField, StoreFieldIterator, Subfield,
|
||||
};
|
||||
use reactive_stores_macro::Store;
|
||||
|
||||
#[derive(Debug, Store)]
|
||||
@@ -59,7 +61,6 @@ pub fn App() -> impl IntoView {
|
||||
};
|
||||
|
||||
view! {
|
||||
<p>"Hello, " {move || store.user().get()}</p>
|
||||
<form on:submit=move |ev| {
|
||||
ev.prevent_default();
|
||||
store.todos().write().push(Todo::new(input_ref.get().unwrap().value()));
|
||||
@@ -76,7 +77,8 @@ pub fn App() -> impl IntoView {
|
||||
fn TodoRow(
|
||||
store: Store<Todos>,
|
||||
idx: usize,
|
||||
#[prop(into)] todo: Field<Todo>,
|
||||
// to be fair, this is gross
|
||||
todo: AtIndex<Subfield<Store<Todos>, Todos, Vec<Todo>>, Vec<Todo>>,
|
||||
) -> impl IntoView {
|
||||
let completed = todo.completed();
|
||||
let title = todo.label();
|
||||
|
||||
@@ -7,26 +7,26 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
actix-files = { version = "0.6.6", optional = true }
|
||||
actix-web = { version = "4.8", optional = true, features = ["macros"] }
|
||||
console_error_panic_hook = "0.1.7"
|
||||
actix-files = { version = "0.6", optional = true }
|
||||
actix-web = { version = "4", optional = true, features = ["macros"] }
|
||||
console_error_panic_hook = "0.1"
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos_actix = { path = "../../integrations/actix", optional = true }
|
||||
leptos_router = { path = "../../router" }
|
||||
log = "0.4.22"
|
||||
wasm-bindgen = "0.2.93"
|
||||
serde = "1.0"
|
||||
tokio = { version = "1.39", features = ["time", "rt"], optional = true }
|
||||
log = "0.4"
|
||||
wasm-bindgen = "0.2"
|
||||
serde = "1.0.159"
|
||||
tokio = { version = "1.29", features = ["time", "rt"], optional = true }
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
"dep:actix-files",
|
||||
"dep:actix-web",
|
||||
"dep:leptos_actix",
|
||||
"leptos/ssr",
|
||||
"leptos_router/ssr",
|
||||
"dep:tokio",
|
||||
"dep:actix-files",
|
||||
"dep:actix-web",
|
||||
"dep:leptos_actix",
|
||||
"leptos/ssr",
|
||||
"leptos_router/ssr",
|
||||
"dep:tokio",
|
||||
]
|
||||
|
||||
[package.metadata.leptos]
|
||||
|
||||
@@ -4,14 +4,14 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0"
|
||||
async-trait = "0.1.81"
|
||||
cucumber = "0.21.1"
|
||||
fantoccini = "0.21.1"
|
||||
pretty_assertions = "1.4"
|
||||
serde_json = "1.0"
|
||||
tokio = { version = "1.39", features = ["macros", "rt-multi-thread", "time"] }
|
||||
url = "2.5"
|
||||
anyhow = "1.0.72"
|
||||
async-trait = "0.1.72"
|
||||
cucumber = "0.19.1"
|
||||
fantoccini = "0.19.3"
|
||||
pretty_assertions = "1.4.0"
|
||||
serde_json = "1.0.104"
|
||||
tokio = { version = "1.29.1", features = ["macros", "rt-multi-thread", "time"] }
|
||||
url = "2.4.0"
|
||||
|
||||
[[test]]
|
||||
name = "app_suite"
|
||||
|
||||
@@ -8,8 +8,8 @@ This example demonstrates e2e testing with Rust using executable requirements.
|
||||
|---|---|---|
|
||||
| [Cucumber](https://github.com/cucumber-rs/cucumber/tree/main) | Test Runner | Run [Gherkin](https://cucumber.io/docs/gherkin/reference/) specifications as Rust tests |
|
||||
| [Fantoccini](https://github.com/jonhoo/fantoccini/tree/main) | Browser Client | Interact with web pages through WebDriver |
|
||||
| [Cargo Leptos](https://github.com/leptos-rs/cargo-leptos) | Build Tool | Compile example and start the server and end-2-end tests |
|
||||
| [chromedriver](https://chromedriver.chromium.org/downloads) | WebDriver | Provide WebDriver for Chrome |
|
||||
| [Cargo Leptos ](https://github.com/leptos-rs/cargo-leptos) | Build Tool | Compile example and start the server and end-2-end tests |
|
||||
| [chromedriver](https://chromedriver.chromium.org/downloads) | WebDriver | Provide WebDriver for Chrome
|
||||
|
||||
## Testing Organization
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ fn NestedResourceInside() -> impl IntoView {
|
||||
<Suspense fallback=|| {
|
||||
"Loading 1..."
|
||||
}>
|
||||
{Suspend::new(async move {
|
||||
{Suspend(async move {
|
||||
_ = one_second.await;
|
||||
let two_second = Resource::new(
|
||||
|| (),
|
||||
@@ -192,7 +192,7 @@ fn NestedResourceInside() -> impl IntoView {
|
||||
<Suspense fallback=|| "Loading 2...">
|
||||
<span id="loaded-2">
|
||||
"Loaded 2 (created inside first suspense)!: "
|
||||
{Suspend::new(async move { format!("{:?}", two_second.await) })}
|
||||
{Suspend(async move { format!("{:?}", two_second.await) })}
|
||||
</span>
|
||||
<button on:click=move |_| set_count.update(|n| *n += 1)>{count}</button>
|
||||
</Suspense>
|
||||
@@ -322,7 +322,7 @@ fn LocalResource() -> impl IntoView {
|
||||
one_second.get().map(|_| view! { <p id="loaded-1">"One Second: Loaded 1!"</p> })
|
||||
}}
|
||||
{move || {
|
||||
Suspend::new(async move {
|
||||
Suspend(async move {
|
||||
let value = local.await;
|
||||
view! { <p id="loaded-2">"One Second: Local Loaded " {value} "!"</p> }
|
||||
})
|
||||
|
||||
@@ -13,15 +13,19 @@ leptos_meta = { path = "../../meta" }
|
||||
leptos_router = { path = "../../router" }
|
||||
|
||||
# dependencies for browser (enable when hydrate set)
|
||||
console_error_panic_hook = { version = "0.1.7", optional = true }
|
||||
wasm-bindgen = { version = "0.2.93", optional = true }
|
||||
console_error_panic_hook = { version = "0.1", optional = true }
|
||||
wasm-bindgen = { version = "0.2", optional = true }
|
||||
|
||||
# dependencies for server (enable when ssr set)
|
||||
actix-files = { version = "0.6.6", optional = true }
|
||||
actix-web = { version = "4.8", features = ["macros"], optional = true }
|
||||
actix-files = { version = "0.6", optional = true }
|
||||
actix-web = { version = "4", features = ["macros"], optional = true }
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate", "dep:wasm-bindgen", "dep:console_error_panic_hook"]
|
||||
hydrate = [
|
||||
"leptos/hydrate",
|
||||
"dep:wasm-bindgen",
|
||||
"dep:console_error_panic_hook",
|
||||
]
|
||||
ssr = [
|
||||
"leptos/ssr",
|
||||
"leptos_meta/ssr",
|
||||
|
||||
@@ -7,35 +7,32 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
axum = { version = "0.7.5", optional = true }
|
||||
console_error_panic_hook = "0.1.7"
|
||||
axum = { version = "0.7", optional = true }
|
||||
console_error_panic_hook = "0.1"
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_axum = { path = "../../integrations/axum", optional = true }
|
||||
leptos_router = { path = "../../router" }
|
||||
tokio = { version = "1.39", features = [
|
||||
"rt-multi-thread",
|
||||
"macros",
|
||||
], optional = true }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
tower-http = { version = "0.5.2", features = ["fs"], optional = true }
|
||||
wasm-bindgen = "0.2.93"
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "macros"], optional = true }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs"], optional = true }
|
||||
wasm-bindgen = "0.2"
|
||||
thiserror = "1.0"
|
||||
tracing = { version = "0.1.40", optional = true }
|
||||
http = "1.1"
|
||||
tracing = { version = "0.1", optional = true }
|
||||
http = "1.0"
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
"dep:axum",
|
||||
"dep:tokio",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:leptos_axum",
|
||||
"leptos/ssr",
|
||||
"leptos_meta/ssr",
|
||||
"leptos_router/ssr",
|
||||
"dep:tracing",
|
||||
"dep:axum",
|
||||
"dep:tokio",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:leptos_axum",
|
||||
"leptos/ssr",
|
||||
"leptos_meta/ssr",
|
||||
"leptos_router/ssr",
|
||||
"dep:tracing",
|
||||
]
|
||||
|
||||
[package.metadata.cargo-all-features]
|
||||
|
||||
@@ -7,5 +7,5 @@ edition = "2021"
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_router = { path = "../../router" }
|
||||
gloo-net = { version = "0.6.0", features = ["http"] }
|
||||
console_error_panic_hook = { version = "0.1.7" }
|
||||
gloo-net = { version = "0.5", features = ["http"] }
|
||||
console_error_panic_hook = { version = "0.1" }
|
||||
|
||||
@@ -8,15 +8,15 @@ codegen-units = 1
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
console_log = "1.0"
|
||||
log = "0.4.22"
|
||||
leptos = { path = "../../leptos" }
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
wasm-bindgen = "0.2.93"
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.70"
|
||||
version = "0.3"
|
||||
features = ["Window"]
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
|
||||
@@ -7,36 +7,36 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
actix-files = { version = "0.6.6", optional = true }
|
||||
actix-web = { version = "4.8", optional = true, features = ["macros"] }
|
||||
anyhow = "1.0"
|
||||
broadcaster = "1.0"
|
||||
console_log = "1.0"
|
||||
actix-files = { version = "0.6.2", optional = true }
|
||||
actix-web = { version = "4.2.1", optional = true, features = ["macros"] }
|
||||
anyhow = "1.0.68"
|
||||
broadcaster = "1.0.0"
|
||||
console_log = "1.0.0"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
futures = "0.3.30"
|
||||
leptos = { path = "../../leptos" }
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
futures = "0.3.25"
|
||||
leptos = { path = "../../leptos"}
|
||||
leptos_actix = { path = "../../integrations/actix", optional = true }
|
||||
log = "0.4.22"
|
||||
simple_logger = "5.0"
|
||||
log = "0.4.17"
|
||||
simple_logger = "4.0.0"
|
||||
gloo = { git = "https://github.com/rustwasm/gloo" }
|
||||
sqlx = { version = "0.8.0", features = [
|
||||
"runtime-tokio-rustls",
|
||||
"sqlite",
|
||||
sqlx = { version = "0.6.2", features = [
|
||||
"runtime-tokio-rustls",
|
||||
"sqlite",
|
||||
], optional = true }
|
||||
wasm-bindgen = "0.2.93"
|
||||
tokio = { version = "1.39", features = ["rt", "time"], optional = true }
|
||||
wasm-bindgen = "0.2"
|
||||
tokio = { version = "1", features = ["rt", "time"], optional = true }
|
||||
server_fn = { path = "../../server_fn", features = ["cbor"] }
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
"dep:actix-files",
|
||||
"dep:actix-web",
|
||||
"dep:sqlx",
|
||||
"leptos/ssr",
|
||||
"leptos_actix",
|
||||
"dep:tokio",
|
||||
"dep:actix-files",
|
||||
"dep:actix-web",
|
||||
"dep:sqlx",
|
||||
"leptos/ssr",
|
||||
"leptos_actix",
|
||||
"dep:tokio",
|
||||
]
|
||||
|
||||
[package.metadata.cargo-all-features]
|
||||
|
||||
@@ -4,14 +4,14 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0"
|
||||
async-trait = "0.1.81"
|
||||
cucumber = "0.21.1"
|
||||
fantoccini = "0.21.1"
|
||||
pretty_assertions = "1.4"
|
||||
serde_json = "1.0"
|
||||
tokio = { version = "1.39", features = ["macros", "rt-multi-thread", "time"] }
|
||||
url = "2.5"
|
||||
anyhow = "1.0.72"
|
||||
async-trait = "0.1.72"
|
||||
cucumber = "0.19.1"
|
||||
fantoccini = "0.19.3"
|
||||
pretty_assertions = "1.4.0"
|
||||
serde_json = "1.0.104"
|
||||
tokio = { version = "1.29.1", features = ["macros", "rt-multi-thread", "time"] }
|
||||
url = "2.4.0"
|
||||
|
||||
[[test]]
|
||||
name = "app_suite"
|
||||
|
||||
@@ -113,7 +113,7 @@ pub fn Todos() -> impl IntoView {
|
||||
);
|
||||
|
||||
let existing_todos = move || {
|
||||
Suspend::new(async move {
|
||||
Suspend(async move {
|
||||
todos
|
||||
.await
|
||||
.map(|todos| {
|
||||
|
||||
@@ -8,35 +8,35 @@ crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
console_log = "1.0"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
futures = "0.3.30"
|
||||
http = "1.1"
|
||||
console_error_panic_hook = "0.1"
|
||||
futures = "0.3"
|
||||
http = "1.0"
|
||||
leptos = { path = "../../leptos", features = ["tracing"] }
|
||||
leptos_axum = { path = "../../integrations/axum", optional = true }
|
||||
log = "0.4.22"
|
||||
simple_logger = "5.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
axum = { version = "0.7.5", optional = true }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
tower-http = { version = "0.5.2", features = ["fs"], optional = true }
|
||||
tokio = { version = "1.39", features = ["full"], optional = true }
|
||||
sqlx = { version = "0.8.0", features = [
|
||||
"runtime-tokio-rustls",
|
||||
"sqlite",
|
||||
log = "0.4"
|
||||
simple_logger = "4.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
axum = { version = "0.7", optional = true }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs"], optional = true }
|
||||
tokio = { version = "1", features = ["full"], optional = true }
|
||||
sqlx = { version = "0.7", features = [
|
||||
"runtime-tokio-rustls",
|
||||
"sqlite",
|
||||
], optional = true }
|
||||
thiserror = "1.0"
|
||||
wasm-bindgen = "0.2.93"
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[features]
|
||||
hydrate = ["leptos/hydrate"]
|
||||
ssr = [
|
||||
"dep:axum",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"dep:sqlx",
|
||||
"leptos/ssr",
|
||||
"dep:leptos_axum",
|
||||
"dep:axum",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"dep:sqlx",
|
||||
"leptos/ssr",
|
||||
"dep:leptos_axum",
|
||||
]
|
||||
|
||||
[package.metadata.cargo-all-features]
|
||||
|
||||
@@ -4,14 +4,14 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0"
|
||||
async-trait = "0.1.81"
|
||||
cucumber = "0.21.1"
|
||||
fantoccini = "0.21.1"
|
||||
pretty_assertions = "1.4"
|
||||
serde_json = "1.0"
|
||||
tokio = { version = "1.39", features = ["macros", "rt-multi-thread", "time"] }
|
||||
url = "2.5"
|
||||
anyhow = "1.0.72"
|
||||
async-trait = "0.1.72"
|
||||
cucumber = "0.19.1"
|
||||
fantoccini = "0.19.3"
|
||||
pretty_assertions = "1.4.0"
|
||||
serde_json = "1.0.104"
|
||||
tokio = { version = "1.29.1", features = ["macros", "rt-multi-thread", "time"] }
|
||||
url = "2.4.0"
|
||||
|
||||
[[test]]
|
||||
name = "app_suite"
|
||||
|
||||
@@ -134,7 +134,7 @@ pub fn Todos() -> impl IntoView {
|
||||
);
|
||||
|
||||
let existing_todos = move || {
|
||||
Suspend::new(async move {
|
||||
Suspend(async move {
|
||||
todos
|
||||
.await
|
||||
.map(|todos| {
|
||||
|
||||
@@ -7,39 +7,39 @@ edition = "2021"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dependencies]
|
||||
console_error_panic_hook = "0.1.7"
|
||||
futures = "0.3.30"
|
||||
console_error_panic_hook = "0.1"
|
||||
futures = "0.3"
|
||||
leptos = { path = "../../leptos" }
|
||||
leptos_axum = { path = "../../integrations/axum", optional = true }
|
||||
leptos_meta = { path = "../../meta" }
|
||||
leptos_meta = { path = "../../meta"}
|
||||
leptos_router = { path = "../../router" }
|
||||
leptos_integration_utils = { path = "../../integrations/utils", optional = true }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
axum = { version = "0.7.5", optional = true }
|
||||
tower = { version = "0.4.13", optional = true }
|
||||
tower-http = { version = "0.5.2", features = ["fs"], optional = true }
|
||||
tokio = { version = "1.39", features = ["full"], optional = true }
|
||||
http = { version = "1.1" }
|
||||
sqlx = { version = "0.8.0", features = [
|
||||
"runtime-tokio-rustls",
|
||||
"sqlite",
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
axum = { version = "0.7", optional = true }
|
||||
tower = { version = "0.4", optional = true }
|
||||
tower-http = { version = "0.5", features = ["fs"], optional = true }
|
||||
tokio = { version = "1", features = ["full"], optional = true }
|
||||
http = { version = "1.0" }
|
||||
sqlx = { version = "0.7", features = [
|
||||
"runtime-tokio-rustls",
|
||||
"sqlite",
|
||||
], optional = true }
|
||||
thiserror = "1.0"
|
||||
wasm-bindgen = "0.2.93"
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[features]
|
||||
csr = ["leptos/csr"]
|
||||
ssr = [
|
||||
"dep:axum",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"dep:sqlx",
|
||||
"leptos/ssr",
|
||||
"leptos_meta/ssr",
|
||||
"leptos_router/ssr",
|
||||
"dep:leptos_axum",
|
||||
"dep:leptos_integration_utils",
|
||||
"dep:axum",
|
||||
"dep:tower",
|
||||
"dep:tower-http",
|
||||
"dep:tokio",
|
||||
"dep:sqlx",
|
||||
"leptos/ssr",
|
||||
"leptos_meta/ssr",
|
||||
"leptos_router/ssr",
|
||||
"dep:leptos_axum",
|
||||
"dep:leptos_integration_utils",
|
||||
]
|
||||
|
||||
[package.metadata.cargo-all-features]
|
||||
|
||||
@@ -4,14 +4,14 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0"
|
||||
async-trait = "0.1.81"
|
||||
cucumber = "0.21.1"
|
||||
fantoccini = "0.21.1"
|
||||
pretty_assertions = "1.4"
|
||||
serde_json = "1.0"
|
||||
tokio = { version = "1.39", features = ["macros", "rt-multi-thread", "time"] }
|
||||
url = "2.5"
|
||||
anyhow = "1.0.72"
|
||||
async-trait = "0.1.72"
|
||||
cucumber = "0.19.1"
|
||||
fantoccini = "0.19.3"
|
||||
pretty_assertions = "1.4.0"
|
||||
serde_json = "1.0.104"
|
||||
tokio = { version = "1.29.1", features = ["macros", "rt-multi-thread", "time"] }
|
||||
url = "2.4.0"
|
||||
|
||||
[[test]]
|
||||
name = "app_suite"
|
||||
|
||||
@@ -134,7 +134,7 @@ pub fn Todos() -> impl IntoView {
|
||||
);
|
||||
|
||||
let existing_todos = move || {
|
||||
Suspend::new(async move {
|
||||
Suspend(async move {
|
||||
todos
|
||||
.await
|
||||
.map(|todos| {
|
||||
|
||||
@@ -8,15 +8,19 @@ codegen-units = 1
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
leptos = { path = "../../leptos" }
|
||||
console_error_panic_hook = "0.1.7"
|
||||
uuid = { version = "1.10", features = ["v4", "js", "serde"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
web-sys = { version = "0.3.70", features = ["Storage"] }
|
||||
uuid = { version = "1", features = ["v4", "js", "serde"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
web-sys = { version = "0.3.60", features = ["Storage"] }
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.42"
|
||||
wasm-bindgen-test = "0.3.0"
|
||||
|
||||
[features]
|
||||
default = ["csr"]
|
||||
csr = ["leptos/csr"]
|
||||
|
||||
[package.metadata.cargo-all-features]
|
||||
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
[package]
|
||||
name = "hydration_context"
|
||||
version = "0.2.0-beta2"
|
||||
edition = "2021"
|
||||
version = "0.2.0-alpha"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
readme = "../README.md"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Utilities for sharing data between web servers and client-side web applications."
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
throw_error = { workspace = true }
|
||||
or_poisoned = { workspace = true }
|
||||
futures = "0.3.30"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
wasm-bindgen = { version = "0.2.93", optional = true }
|
||||
js-sys = { version = "0.3.69", optional = true }
|
||||
once_cell = "1.19"
|
||||
futures = "0.3"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
wasm-bindgen = { version = "0.2", optional = true }
|
||||
js-sys = { version = "0.3", optional = true }
|
||||
once_cell = "1.19.0"
|
||||
pin-project-lite = "0.2.14"
|
||||
|
||||
[features]
|
||||
|
||||
@@ -12,48 +12,42 @@ use wasm_bindgen::{prelude::wasm_bindgen, JsCast};
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(thread_local)]
|
||||
static __RESOLVED_RESOURCES: Array;
|
||||
|
||||
#[wasm_bindgen(thread_local)]
|
||||
static __SERIALIZED_ERRORS: Array;
|
||||
|
||||
#[wasm_bindgen(thread_local)]
|
||||
static __INCOMPLETE_CHUNKS: Array;
|
||||
}
|
||||
|
||||
fn serialized_errors() -> Vec<(SerializedDataId, ErrorId, Error)> {
|
||||
__SERIALIZED_ERRORS.with(|s| {
|
||||
s.iter()
|
||||
.flat_map(|value| {
|
||||
value.dyn_ref::<Array>().map(|value| {
|
||||
let error_boundary_id =
|
||||
value.get(0).as_f64().unwrap() as usize;
|
||||
let error_id = value.get(1).as_f64().unwrap() as usize;
|
||||
let value = value
|
||||
.get(2)
|
||||
.as_string()
|
||||
.expect("Expected a [number, string] tuple");
|
||||
(
|
||||
SerializedDataId(error_boundary_id),
|
||||
ErrorId::from(error_id),
|
||||
Error::from(SerializedError(value)),
|
||||
)
|
||||
})
|
||||
__SERIALIZED_ERRORS
|
||||
.iter()
|
||||
.flat_map(|value| {
|
||||
value.dyn_ref::<Array>().map(|value| {
|
||||
let error_boundary_id = value.get(0).as_f64().unwrap() as usize;
|
||||
let error_id = value.get(1).as_f64().unwrap() as usize;
|
||||
let value = value
|
||||
.get(2)
|
||||
.as_string()
|
||||
.expect("Expected a [number, string] tuple");
|
||||
(
|
||||
SerializedDataId(error_boundary_id),
|
||||
ErrorId::from(error_id),
|
||||
Error::from(SerializedError(value)),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn incomplete_chunks() -> Vec<SerializedDataId> {
|
||||
__INCOMPLETE_CHUNKS.with(|i| {
|
||||
i.iter()
|
||||
.map(|value| {
|
||||
let id = value.as_f64().unwrap() as usize;
|
||||
SerializedDataId(id)
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
__INCOMPLETE_CHUNKS
|
||||
.iter()
|
||||
.map(|value| {
|
||||
let id = value.as_f64().unwrap() as usize;
|
||||
SerializedDataId(id)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// An error that has been serialized across the network boundary.
|
||||
@@ -124,7 +118,7 @@ impl SharedContext for HydrateSharedContext {
|
||||
fn write_async(&self, _id: SerializedDataId, _fut: PinnedFuture<String>) {}
|
||||
|
||||
fn read_data(&self, id: &SerializedDataId) -> Option<String> {
|
||||
__RESOLVED_RESOURCES.with(|r| r.get(id.0 as u32).as_string())
|
||||
__RESOLVED_RESOURCES.get(id.0 as u32).as_string()
|
||||
}
|
||||
|
||||
fn await_data(&self, _id: &SerializedDataId) -> Option<String> {
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
#![deny(missing_docs)]
|
||||
#![forbid(unsafe_code)]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||
|
||||
#[cfg(feature = "browser")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "browser")))]
|
||||
@@ -44,12 +43,6 @@ pub type PinnedStream<T> = Pin<Box<dyn Stream<Item = T> + Send + Sync>>;
|
||||
/// from the server to the client.
|
||||
pub struct SerializedDataId(usize);
|
||||
|
||||
impl From<SerializedDataId> for ErrorId {
|
||||
fn from(value: SerializedDataId) -> Self {
|
||||
value.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Information that will be shared between the server and the client.
|
||||
pub trait SharedContext: Debug {
|
||||
/// Whether the application is running in the browser.
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
[package]
|
||||
name = "leptos_actix"
|
||||
version = { workspace = true }
|
||||
edition = "2021"
|
||||
authors = ["Greg Johnston"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/leptos-rs/leptos"
|
||||
description = "Actix integrations for the Leptos web framework."
|
||||
version = { workspace = true }
|
||||
rust-version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[dependencies]
|
||||
actix-http = "3.8"
|
||||
actix-web = "4.8"
|
||||
futures = "0.3.30"
|
||||
actix-http = "3"
|
||||
actix-web = "4"
|
||||
futures = "0.3"
|
||||
any_spawner = { workspace = true, features = ["tokio"] }
|
||||
hydration_context = { workspace = true }
|
||||
leptos = { workspace = true, features = ["nonce", "ssr"] }
|
||||
@@ -20,14 +20,11 @@ leptos_macro = { workspace = true, features = ["actix"] }
|
||||
leptos_meta = { workspace = true }
|
||||
leptos_router = { workspace = true, features = ["ssr"] }
|
||||
server_fn = { workspace = true, features = ["actix"] }
|
||||
serde_json = "1.0"
|
||||
parking_lot = "0.12.3"
|
||||
tracing = "0.1.40"
|
||||
tokio = { version = "1.39", features = ["rt", "fs"] }
|
||||
serde_json = "1"
|
||||
parking_lot = "0.12.1"
|
||||
tracing = "0.1.37"
|
||||
tokio = { version = "1", features = ["rt", "fs"] }
|
||||
send_wrapper = "0.6.0"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
rustdoc-args = ["--generate-link-to-definition"]
|
||||
|
||||
[features]
|
||||
islands-router = []
|
||||
|
||||
@@ -16,7 +16,6 @@ use actix_web::{
|
||||
};
|
||||
use futures::{stream::once, Stream, StreamExt};
|
||||
use http::StatusCode;
|
||||
use hydration_context::SsrSharedContext;
|
||||
use leptos::{
|
||||
context::{provide_context, use_context},
|
||||
reactive_graph::{computed::ScopedFuture, owner::Owner},
|
||||
@@ -182,20 +181,6 @@ impl ExtendResponse for ActixResponse {
|
||||
|
||||
/// Provides an easy way to redirect the user from within a server function.
|
||||
///
|
||||
/// Calling `redirect` in a server function will redirect the browser in three
|
||||
/// situations:
|
||||
/// 1. A server function that is calling in a [blocking
|
||||
/// resource](leptos::server::Resource::new_blocking).
|
||||
/// 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`](leptos::form::ActionForm) without JS/WASM present.)
|
||||
///
|
||||
/// 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
|
||||
///
|
||||
/// This sets the `Location` header to the URL given.
|
||||
///
|
||||
/// If the route or server function in which this is called is being accessed
|
||||
@@ -316,9 +301,8 @@ pub fn handle_server_fns_with_context(
|
||||
let additional_context = additional_context.clone();
|
||||
|
||||
let path = req.path();
|
||||
let method = req.method();
|
||||
if let Some(mut service) =
|
||||
server_fn::actix::get_server_fn_service(path, method)
|
||||
server_fn::actix::get_server_fn_service(path)
|
||||
{
|
||||
let owner = Owner::new();
|
||||
owner
|
||||
@@ -400,7 +384,7 @@ pub fn handle_server_fns_with_context(
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// use actix_web::{App, HttpServer};
|
||||
/// use leptos::prelude::*;
|
||||
/// use leptos::*;
|
||||
/// use leptos_router::Method;
|
||||
/// use std::{env, net::SocketAddr};
|
||||
///
|
||||
@@ -422,7 +406,11 @@ pub fn handle_server_fns_with_context(
|
||||
/// // the actual routing will be handled by `leptos_router`
|
||||
/// .route(
|
||||
/// "/{tail:.*}",
|
||||
/// leptos_actix::render_app_to_stream(MyApp, Method::Get),
|
||||
/// leptos_actix::render_app_to_stream(
|
||||
/// leptos_options.to_owned(),
|
||||
/// || view! { <MyApp/> },
|
||||
/// Method::Get,
|
||||
/// ),
|
||||
/// )
|
||||
/// })
|
||||
/// .bind(&addr)?
|
||||
@@ -464,7 +452,7 @@ where
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// use actix_web::{App, HttpServer};
|
||||
/// use leptos::prelude::*;
|
||||
/// use leptos::*;
|
||||
/// use leptos_router::Method;
|
||||
/// use std::{env, net::SocketAddr};
|
||||
///
|
||||
@@ -487,7 +475,8 @@ where
|
||||
/// .route(
|
||||
/// "/{tail:.*}",
|
||||
/// leptos_actix::render_app_to_stream_in_order(
|
||||
/// MyApp,
|
||||
/// leptos_options.to_owned(),
|
||||
/// || view! { <MyApp/> },
|
||||
/// Method::Get,
|
||||
/// ),
|
||||
/// )
|
||||
@@ -529,7 +518,7 @@ where
|
||||
/// This can then be set up at an appropriate route in your application:
|
||||
/// ```
|
||||
/// use actix_web::{App, HttpServer};
|
||||
/// use leptos::prelude::*;
|
||||
/// use leptos::*;
|
||||
/// use leptos_router::Method;
|
||||
/// use std::{env, net::SocketAddr};
|
||||
///
|
||||
@@ -551,7 +540,11 @@ where
|
||||
/// // the actual routing will be handled by `leptos_router`
|
||||
/// .route(
|
||||
/// "/{tail:.*}",
|
||||
/// leptos_actix::render_app_async(MyApp, Method::Get),
|
||||
/// leptos_actix::render_app_async(
|
||||
/// leptos_options.to_owned(),
|
||||
/// || view! { <MyApp/> },
|
||||
/// Method::Get,
|
||||
/// ),
|
||||
/// )
|
||||
/// })
|
||||
/// .bind(&addr)?
|
||||
@@ -951,7 +944,7 @@ where
|
||||
{
|
||||
let _ = any_spawner::Executor::init_tokio();
|
||||
|
||||
let owner = Owner::new_root(Some(Arc::new(SsrSharedContext::new())));
|
||||
let owner = Owner::new_root(None);
|
||||
let (mock_meta, _) = ServerMetaContext::new();
|
||||
let routes = owner
|
||||
.with(|| {
|
||||
@@ -1387,21 +1380,18 @@ impl LeptosRoutes for &mut ServiceConfig {
|
||||
///
|
||||
/// Any error that occurs during extraction is converted to a [`ServerFnError`].
|
||||
///
|
||||
/// ```rust
|
||||
/// use leptos::prelude::*;
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// // MyQuery is some type that implements `Deserialize + Serialize`
|
||||
/// #[server]
|
||||
/// pub async fn extract_connection_info() -> Result<String, ServerFnError> {
|
||||
/// use actix_web::dev::ConnectionInfo;
|
||||
/// pub async fn query_extract() -> Result<MyQuery, ServerFnError> {
|
||||
/// use actix_web::web::Query;
|
||||
/// use leptos_actix::*;
|
||||
///
|
||||
/// // this can be any type you can use an Actix extractor with, as long as
|
||||
/// // it works on the head, not the body of the request
|
||||
/// let info: ConnectionInfo = extract().await?;
|
||||
/// let Query(data) = extract().await?;
|
||||
///
|
||||
/// // do something with the data
|
||||
///
|
||||
/// Ok(format!("{info:?}"))
|
||||
/// Ok(data)
|
||||
/// }
|
||||
/// ```
|
||||
pub async fn extract<T>() -> Result<T, ServerFnError>
|
||||
@@ -1409,7 +1399,7 @@ where
|
||||
T: actix_web::FromRequest,
|
||||
<T as FromRequest>::Error: Display,
|
||||
{
|
||||
let req = use_context::<Request>().ok_or_else(|| {
|
||||
let req = use_context::<HttpRequest>().ok_or_else(|| {
|
||||
ServerFnError::new("HttpRequest should have been provided via context")
|
||||
})?;
|
||||
|
||||
|
||||
@@ -1,153 +1,148 @@
|
||||
// TODO these tests relate to trailing-slash logic, which is still TBD for 0.7
|
||||
use leptos::*;
|
||||
use leptos_actix::generate_route_list;
|
||||
use leptos_router::{Route, Router, Routes, TrailingSlash};
|
||||
|
||||
// use leptos::*;
|
||||
// use leptos_actix::generate_route_list;
|
||||
// use leptos_router::{
|
||||
// components::{Route, Router, Routes},
|
||||
// path,
|
||||
// };
|
||||
//
|
||||
// #[component]
|
||||
// fn DefaultApp() -> impl IntoView {
|
||||
// let view = || view! { "" };
|
||||
// view! {
|
||||
// <Router>
|
||||
// <Routes>
|
||||
// <Route path=path!("/foo") view/>
|
||||
// <Route path=path!("/bar/") view/>
|
||||
// <Route path=path!("/baz/:id") view/>
|
||||
// <Route path=path!("/baz/:name/") view/>
|
||||
// <Route path=path!("/baz/*any") view/>
|
||||
// </Routes>
|
||||
// </Router>
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_default_app() {
|
||||
// let routes = generate_route_list(DefaultApp);
|
||||
//
|
||||
// // We still have access to the original (albeit normalized) Leptos paths:
|
||||
// assert_same(
|
||||
// &routes,
|
||||
// |r| r.leptos_path(),
|
||||
// &["/bar", "/baz/*any", "/baz/:id", "/baz/:name", "/foo"],
|
||||
// );
|
||||
//
|
||||
// // ... But leptos-actix has also reformatted "paths" to work for Actix.
|
||||
// assert_same(
|
||||
// &routes,
|
||||
// |r| r.path(),
|
||||
// &["/bar", "/baz/{id}", "/baz/{name}", "/baz/{tail:.*}", "/foo"],
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[component]
|
||||
// fn ExactApp() -> impl IntoView {
|
||||
// let view = || view! { "" };
|
||||
// //let trailing_slash = TrailingSlash::Exact;
|
||||
// view! {
|
||||
// <Router>
|
||||
// <Routes>
|
||||
// <Route path=path!("/foo") view/>
|
||||
// <Route path=path!("/bar/") view/>
|
||||
// <Route path=path!("/baz/:id") view/>
|
||||
// <Route path=path!("/baz/:name/") view/>
|
||||
// <Route path=path!("/baz/*any") view/>
|
||||
// </Routes>
|
||||
// </Router>
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_exact_app() {
|
||||
// let routes = generate_route_list(ExactApp);
|
||||
//
|
||||
// // In Exact mode, the Leptos paths no longer have their trailing slashes stripped:
|
||||
// assert_same(
|
||||
// &routes,
|
||||
// |r| r.leptos_path(),
|
||||
// &["/bar/", "/baz/*any", "/baz/:id", "/baz/:name/", "/foo"],
|
||||
// );
|
||||
//
|
||||
// // Actix paths also have trailing slashes as a result:
|
||||
// assert_same(
|
||||
// &routes,
|
||||
// |r| r.path(),
|
||||
// &[
|
||||
// "/bar/",
|
||||
// "/baz/{id}",
|
||||
// "/baz/{name}/",
|
||||
// "/baz/{tail:.*}",
|
||||
// "/foo",
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// #[component]
|
||||
// fn RedirectApp() -> impl IntoView {
|
||||
// let view = || view! { "" };
|
||||
// //let trailing_slash = TrailingSlash::Redirect;
|
||||
// view! {
|
||||
// <Router>
|
||||
// <Routes>
|
||||
// <Route path=path!("/foo") view/>
|
||||
// <Route path=path!("/bar/") view/>
|
||||
// <Route path=path!("/baz/:id") view/>
|
||||
// <Route path=path!("/baz/:name/") view/>
|
||||
// <Route path=path!("/baz/*any") view/>
|
||||
// </Routes>
|
||||
// </Router>
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[test]
|
||||
// fn test_redirect_app() {
|
||||
// let routes = generate_route_list(RedirectApp);
|
||||
//
|
||||
// assert_same(
|
||||
// &routes,
|
||||
// |r| r.leptos_path(),
|
||||
// &[
|
||||
// "/bar",
|
||||
// "/bar/",
|
||||
// "/baz/*any",
|
||||
// "/baz/:id",
|
||||
// "/baz/:id/",
|
||||
// "/baz/:name",
|
||||
// "/baz/:name/",
|
||||
// "/foo",
|
||||
// "/foo/",
|
||||
// ],
|
||||
// );
|
||||
//
|
||||
// // ... But leptos-actix has also reformatted "paths" to work for Actix.
|
||||
// assert_same(
|
||||
// &routes,
|
||||
// |r| r.path(),
|
||||
// &[
|
||||
// "/bar",
|
||||
// "/bar/",
|
||||
// "/baz/{id}",
|
||||
// "/baz/{id}/",
|
||||
// "/baz/{name}",
|
||||
// "/baz/{name}/",
|
||||
// "/baz/{tail:.*}",
|
||||
// "/foo",
|
||||
// "/foo/",
|
||||
// ],
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// fn assert_same<'t, T, F, U>(
|
||||
// input: &'t Vec<T>,
|
||||
// mapper: F,
|
||||
// expected_sorted_values: &[U],
|
||||
// ) where
|
||||
// F: Fn(&'t T) -> U + 't,
|
||||
// U: Ord + std::fmt::Debug,
|
||||
// {
|
||||
// let mut values: Vec<U> = input.iter().map(mapper).collect();
|
||||
// values.sort();
|
||||
// assert_eq!(values, expected_sorted_values);
|
||||
// }
|
||||
#[component]
|
||||
fn DefaultApp() -> impl IntoView {
|
||||
let view = || view! { "" };
|
||||
view! {
|
||||
<Router>
|
||||
<Routes>
|
||||
<Route path="/foo" view/>
|
||||
<Route path="/bar/" view/>
|
||||
<Route path="/baz/:id" view/>
|
||||
<Route path="/baz/:name/" view/>
|
||||
<Route path="/baz/*any" view/>
|
||||
</Routes>
|
||||
</Router>
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_app() {
|
||||
let routes = generate_route_list(DefaultApp);
|
||||
|
||||
// We still have access to the original (albeit normalized) Leptos paths:
|
||||
assert_same(
|
||||
&routes,
|
||||
|r| r.leptos_path(),
|
||||
&["/bar", "/baz/*any", "/baz/:id", "/baz/:name", "/foo"],
|
||||
);
|
||||
|
||||
// ... But leptos-actix has also reformatted "paths" to work for Actix.
|
||||
assert_same(
|
||||
&routes,
|
||||
|r| r.path(),
|
||||
&["/bar", "/baz/{id}", "/baz/{name}", "/baz/{tail:.*}", "/foo"],
|
||||
);
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn ExactApp() -> impl IntoView {
|
||||
let view = || view! { "" };
|
||||
let trailing_slash = TrailingSlash::Exact;
|
||||
view! {
|
||||
<Router trailing_slash>
|
||||
<Routes>
|
||||
<Route path="/foo" view/>
|
||||
<Route path="/bar/" view/>
|
||||
<Route path="/baz/:id" view/>
|
||||
<Route path="/baz/:name/" view/>
|
||||
<Route path="/baz/*any" view/>
|
||||
</Routes>
|
||||
</Router>
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exact_app() {
|
||||
let routes = generate_route_list(ExactApp);
|
||||
|
||||
// In Exact mode, the Leptos paths no longer have their trailing slashes stripped:
|
||||
assert_same(
|
||||
&routes,
|
||||
|r| r.leptos_path(),
|
||||
&["/bar/", "/baz/*any", "/baz/:id", "/baz/:name/", "/foo"],
|
||||
);
|
||||
|
||||
// Actix paths also have trailing slashes as a result:
|
||||
assert_same(
|
||||
&routes,
|
||||
|r| r.path(),
|
||||
&[
|
||||
"/bar/",
|
||||
"/baz/{id}",
|
||||
"/baz/{name}/",
|
||||
"/baz/{tail:.*}",
|
||||
"/foo",
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn RedirectApp() -> impl IntoView {
|
||||
let view = || view! { "" };
|
||||
let trailing_slash = TrailingSlash::Redirect;
|
||||
view! {
|
||||
<Router trailing_slash>
|
||||
<Routes>
|
||||
<Route path="/foo" view/>
|
||||
<Route path="/bar/" view/>
|
||||
<Route path="/baz/:id" view/>
|
||||
<Route path="/baz/:name/" view/>
|
||||
<Route path="/baz/*any" view/>
|
||||
</Routes>
|
||||
</Router>
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_redirect_app() {
|
||||
let routes = generate_route_list(RedirectApp);
|
||||
|
||||
assert_same(
|
||||
&routes,
|
||||
|r| r.leptos_path(),
|
||||
&[
|
||||
"/bar",
|
||||
"/bar/",
|
||||
"/baz/*any",
|
||||
"/baz/:id",
|
||||
"/baz/:id/",
|
||||
"/baz/:name",
|
||||
"/baz/:name/",
|
||||
"/foo",
|
||||
"/foo/",
|
||||
],
|
||||
);
|
||||
|
||||
// ... But leptos-actix has also reformatted "paths" to work for Actix.
|
||||
assert_same(
|
||||
&routes,
|
||||
|r| r.path(),
|
||||
&[
|
||||
"/bar",
|
||||
"/bar/",
|
||||
"/baz/{id}",
|
||||
"/baz/{id}/",
|
||||
"/baz/{name}",
|
||||
"/baz/{name}/",
|
||||
"/baz/{tail:.*}",
|
||||
"/foo",
|
||||
"/foo/",
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_same<'t, T, F, U>(
|
||||
input: &'t Vec<T>,
|
||||
mapper: F,
|
||||
expected_sorted_values: &[U],
|
||||
) where
|
||||
F: Fn(&'t T) -> U + 't,
|
||||
U: Ord + std::fmt::Debug,
|
||||
{
|
||||
let mut values: Vec<U> = input.iter().map(mapper).collect();
|
||||
values.sort();
|
||||
assert_eq!(values, expected_sorted_values);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user