Compare commits

..

503 Commits

Author SHA1 Message Date
Greg Johnston
11f8453f7c fix: use shell for SSR, and do not create a second <head> 2024-07-12 11:32:10 -04:00
Saber Haj Rabiee
d0f2069f1c chore: leptosfmt 2024-07-11 06:56:25 -07:00
Saber Haj Rabiee
54481223bf fix: hackernews_js_fetch example 2024-07-11 00:48:09 -07:00
Greg Johnston
6ac6fc6a12 feat: iteration over reactive store list 2024-07-10 22:04:45 -04:00
Greg Johnston
a09cb02b31 feat: add arena-allocated/Copy Store 2024-07-10 21:03:48 -04:00
Greg Johnston
1f9ec1b979 docs: initial work on porting docs from 0.6 to 0.7 2024-07-10 20:47:24 -04:00
Greg Johnston
6c72aaf444 feat: initial work on reactive stores 2024-07-10 20:34:50 -04:00
Greg Johnston
899feb0575 fix: improved API for unsync actions that doesn't require SendWrapper on input 2024-07-10 19:33:40 -04:00
Greg Johnston
b0c1bf46af chore: leptosfmt 2024-07-10 19:21:59 -04:00
Greg Johnston
ec4958959c fix: properly handle errors in streaming body responses 2024-07-10 09:11:39 -04:00
Greg Johnston
174a5a1769 fix: invalid p/ul relationship causing hydration issue 2024-07-10 09:11:39 -04:00
Saber Haj Rabiee
ae68435fb6 chore: cargo fmt (#2672) 2024-07-09 08:51:01 -04:00
Greg Johnston
e507945cd1 feat: use codee for shared ser-de codexes with leptos-use (and more possibilities in future) 2024-07-08 21:31:51 -04:00
Greg Johnston
8f6620d06a chore: remove unused dependencies 2024-07-08 19:53:29 -04:00
Greg Johnston
23f433efa4 fix: was disposing of Suspense Owner too early 2024-07-08 19:47:09 -04:00
Greg Johnston
d9502a94c1 fix: rebuilding NodeRef 2024-07-08 19:13:53 -04:00
Greg Johnston
ae0dc13ce7 feat: top-level Suspend without Suspense 2024-07-06 17:46:26 -04:00
Greg Johnston
22b1132340 chore: clippy and clean up unused functions 2024-07-06 12:56:29 -04:00
Greg Johnston
cb7656599e docs: update syntax for Html/Body 2024-07-06 12:51:39 -04:00
Greg Johnston
f40d0c1334 feat: correct HTML rendering for spread attributes on <Body/> and <Html/> 2024-07-06 12:49:16 -04:00
Greg Johnston
8a878eaaa4 feat: attributes on body and html 2024-07-06 09:39:54 -04:00
Greg Johnston
f70702c6c4 feat: move to a channel-based implementation for meta 2024-07-06 08:16:48 -04:00
Greg Johnston
e2d41f91fa feat: support Suspend in attributes 2024-07-06 07:41:07 -04:00
Greg Johnston
dc21e4ff53 feat: local resources with .await 2024-07-04 15:39:42 -04:00
Greg Johnston
d5aecbe705 chore: cfg warnings 2024-07-04 11:42:06 -04:00
Greg Johnston
032faec5bc fix: MaybeProp None case 2024-07-03 21:01:04 -04:00
Greg Johnston
443fca495d reexport SVG and MathML element types 2024-07-03 21:01:04 -04:00
Greg Johnston
c5f0f4a6ed router alpha 3 2024-07-03 21:01:04 -04:00
Greg Johnston
64cdfbd2a8 Form component in 0.7 2024-07-03 21:01:04 -04:00
Greg Johnston
698d7f6f1b fix: don't break Routes SSR now that it uses Suspend 2024-07-03 21:01:04 -04:00
Alicia Garcia-Raboso
8789ed0882 Implement Default trait for signals with a parameter that also implements Default (#2662)
Co-authored-by: alicia.garcia.raboso <alicia.garcia.raboso@bbva.com>
2024-07-03 21:01:04 -04:00
Greg Johnston
fd5a6bebd3 feat: automatically replace Suspense blocks if they are still waiting to be flushed, without JS (replaces PartiallyBlocked) 2024-07-03 21:01:04 -04:00
Greg Johnston
0a081fafe3 blocking resources 2024-07-03 21:01:04 -04:00
Greg Johnston
f8711611b0 macro alpha 2 2024-07-03 21:01:04 -04:00
Greg Johnston
f508f30be9 router alpha 2 2024-07-03 21:01:04 -04:00
Luke Naylor
52261415cd Add missing 'form' attribute for <mo> (#2660)
This attribute seems to be missing in the attribute
table on Mozilla Docs, however does appear in the
compatibility table lower down.
This attribute is also frequently used by temml,
a common generator for mathml content.
2024-07-03 21:01:04 -04:00
Greg Johnston
65b270307d allow Outlet to be called multiple times 2024-07-03 21:01:04 -04:00
Greg Johnston
f2db13da10 fix: prevent panicking if conditionally rendering Outlet 2024-07-03 21:01:03 -04:00
Greg Johnston
1d90b11e81 remove log 2024-07-03 21:01:03 -04:00
Greg Johnston
f0048e4d45 fix: ensure correct ownership chain when passing views through Outlet 2024-07-03 21:01:03 -04:00
Greg Johnston
5c211cf1ce chore: clippy 2024-07-03 21:01:03 -04:00
Greg Johnston
aed4d49537 support MaybeSignal in view 2024-07-03 21:01:03 -04:00
Kajetan Welc
fa15a00288 fix: impl Copy for Callback (#2658) 2024-07-03 21:01:03 -04:00
Greg Johnston
40b383a0f7 fix: update imports and methods 2024-07-03 21:01:03 -04:00
Greg Johnston
cd289ef811 fix: trait import 2024-07-03 21:01:03 -04:00
Greg Johnston
76dcb823d8 impl From<T> for (Arc)Signal<T> 2024-07-03 21:01:03 -04:00
Greg Johnston
88c9742e6c Revert "lazy Future construction for AsyncDerived"
This reverts commit 9e84e1f57c.
2024-07-03 21:01:03 -04:00
Greg Johnston
edc86bbb43 fix: <option> struct generation 2024-07-03 21:01:03 -04:00
Greg Johnston
3fc0a6ff32 fix: <option> struct generation 2024-07-03 21:01:03 -04:00
Lucas Åström
3797a4167a Destructuring let (0.7) (#2655)
* Use `let()` syntax for bindings

This lets users use destructuring when binding more complex values, and we also get better IDE support.

* Update rstml
2024-07-03 21:01:03 -04:00
Greg Johnston
5ffcfc4079 fix: nonexistent feature 2024-07-03 21:01:03 -04:00
Greg Johnston
87f5d95bc3 fix: rebuilding AnyView 2024-07-03 21:01:03 -04:00
Greg Johnston
0597cda70a support wasm-only 2024-07-03 21:01:02 -04:00
Greg Johnston
a2f6ebf3a6 support wasm-only 2024-07-03 21:00:50 -04:00
Greg Johnston
0be5628038 support wasm-only 2024-07-03 21:00:50 -04:00
Greg Johnston
52434ada9d any_spawner tick version 2024-07-03 21:00:50 -04:00
Greg Johnston
ae0b09419d un-break circular dependency 2024-07-03 21:00:50 -04:00
Greg Johnston
2f93b6d147 chore: update test output 2024-07-03 21:00:50 -04:00
Greg Johnston
4cf7dd0e0c chore: unused import 2024-07-03 21:00:50 -04:00
Greg Johnston
2402688493 restore fallback for compressed version 2024-07-03 21:00:50 -04:00
Greg Johnston
36726e9dfc docs: working on memo docs 2024-07-03 21:00:50 -04:00
Greg Johnston
ab886a1258 0.7.0-alpha 2024-07-03 21:00:50 -04:00
Greg Johnston
2d51311362 feat: support reactive and asynchronous ProtectedRoute conditions 2024-07-03 21:00:50 -04:00
Greg Johnston
9262b512e0 fix: correct For behavior when mounting with siblings, and when clearing 2024-07-03 21:00:50 -04:00
Ben Wishovich
28b38329a3 Make get_configuration sync (#2647)
* Made get_configuraiton sync

* Update examples
2024-07-03 21:00:50 -04:00
Greg Johnston
0567aeb5b8 examples: update directives tests 2024-07-03 21:00:50 -04:00
Greg Johnston
f9cd5ca159 chore: cargo fmt 2024-07-03 21:00:50 -04:00
Greg Johnston
9b72efb9c4 make RemoveEventHandler a concrete type 2024-07-03 21:00:50 -04:00
Greg Johnston
61ee451e19 feat: add ElementExt to give access to the same view APIs at runtime that we do at compile time 2024-07-03 21:00:50 -04:00
Greg Johnston
50d4eb2f50 feat: add ElementExt to give access to the same view APIs at runtime that we do at compile time 2024-07-03 21:00:50 -04:00
Greg Johnston
72aa8a6598 chore: cargo fmt 2024-07-03 21:00:50 -04:00
Greg Johnston
06fe32e90b chore: cargo fmt 2024-07-03 21:00:50 -04:00
Greg Johnston
75184a4638 docs: warn on unused RenderEffect 2024-07-03 21:00:50 -04:00
Greg Johnston
29e5396912 chore: missing Debug implementations 2024-07-03 21:00:50 -04:00
Greg Johnston
b8df56afa1 chore: suppress unnecessary .into() warning 2024-07-03 21:00:50 -04:00
Greg Johnston
7d4b7d2ce8 cargo fmt 2024-07-03 21:00:49 -04:00
Greg Johnston
d132c8e338 updated directives example 2024-07-03 21:00:49 -04:00
brofrain
6bf6fb6923 fix: update HtmlViewState & BodyViewState as well 2024-07-03 21:00:49 -04:00
Kajetan Welc
1bda454441 fix: do not accidentally mount things before meta tags in the <head> when updating the DOM v2 2024-07-03 21:00:49 -04:00
Greg Johnston
9aca55f14f remove log 2024-07-03 21:00:49 -04:00
Greg Johnston
f1a007bf15 preliminary work on directives (not useful yet until we have an ElementExt that allows you to do things declaratively from an Element 2024-07-03 21:00:49 -04:00
Greg Johnston
d83c2acded omit () entirely if it is the only child of an HTML element 2024-07-03 21:00:49 -04:00
Greg Johnston
f984197070 fix: don't override a text node's 'next sibling after text' position if it's in Either, now that they don't have separate marker nodes 2024-07-03 21:00:49 -04:00
Greg Johnston
c8491cc709 fix: do not accidentally mount things before meta tags in the <head> when updating the DOM 2024-07-03 21:00:49 -04:00
Greg Johnston
222aed6d11 fix docs for hydrate_islands 2024-07-03 21:00:49 -04:00
Greg Johnston
7d37c60bae hackernews islands example 2024-07-03 21:00:49 -04:00
Greg Johnston
fea3fdb387 update static file serving in Axum examples 2024-07-03 21:00:49 -04:00
Greg Johnston
d57f484502 fix islands ci setup 2024-07-03 21:00:49 -04:00
Greg Johnston
62bd6a244e fix: remove extra comment at end of Suspense now that Either no longer requires it 2024-07-03 21:00:49 -04:00
Greg Johnston
fe147f0c4d feat: provide static file handling/fallback directly in integration 2024-07-03 21:00:49 -04:00
Greg Johnston
3e0d4e4876 islands example 2024-07-03 21:00:49 -04:00
Greg Johnston
9eda75525a remove unused tests and dependencies 2024-07-03 21:00:49 -04:00
Greg Johnston
de1864867b fix: () in templates 2024-07-03 21:00:49 -04:00
Greg Johnston
116d8f072b chore: clippy 2024-07-03 21:00:49 -04:00
Greg Johnston
6097e3cc57 fix js-framework-benchmark for stable 2024-07-03 21:00:49 -04:00
Greg Johnston
59c18d945a update hackernews_axum to 0.7 2024-07-03 21:00:49 -04:00
Greg Johnston
0b750e17b5 fix ErrorBoundary starting in error state in CSR 2024-07-03 21:00:49 -04:00
Greg Johnston
dd6f1f4660 fix example tests 2024-07-03 21:00:49 -04:00
Greg Johnston
de07282b0a remove unnecessary logs 2024-07-03 21:00:49 -04:00
Greg Johnston
f6046fa8a7 update islands example 2024-07-03 21:00:49 -04:00
Greg Johnston
d945e27d72 chore: unused hooks 2024-07-03 21:00:49 -04:00
Greg Johnston
74a2486944 regression test for 7094dee150 2024-07-03 21:00:49 -04:00
Greg Johnston
142a7d64f9 fix: signals mark subscribers dirty, but don't say they're always dirty if they haven't changed 2024-07-03 21:00:49 -04:00
Greg Johnston
f87ce51ff9 make Routes fallback run lazily 2024-07-03 21:00:49 -04:00
Greg Johnston
5f979635a3 make ErrorBoundary fallback run lazily 2024-07-03 21:00:49 -04:00
Greg Johnston
f648bc2e85 examples: errors_axum 2024-07-03 21:00:49 -04:00
Greg Johnston
bcc75d46c0 chore(ci): fix examples 2024-07-03 21:00:49 -04:00
Greg Johnston
2e0d70765b enable reactive-graph hydration when hydration is enabled 2024-07-03 21:00:49 -04:00
Greg Johnston
24f6b6afb5 allow conversion directly from Arc signal types to MaybeSignal 2024-07-03 21:00:49 -04:00
Greg Johnston
ca0b2e6b4d expose Owner::shared_context() 2024-07-03 21:00:49 -04:00
Greg Johnston
4eb8c2a5b1 0.7 Provider component 2024-07-03 21:00:49 -04:00
Greg Johnston
a18de6eb4f fix tests 2024-07-03 21:00:49 -04:00
Greg Johnston
bf8844f040 fix reactive styles 2024-07-03 21:00:49 -04:00
Greg Johnston
da9553cc7a fix: correctly rebuild reactive attributes to avoid stale signals 2024-07-03 21:00:49 -04:00
Greg Johnston
5e3d4ac37a type-erase RenderEffeect functions for binary size improvements 2024-07-03 21:00:49 -04:00
luoxiaozero
4366bc156d feat: Attr exposes PhantomData field (#2641) 2024-07-03 21:00:49 -04:00
Greg Johnston
23bbba0ef8 chore(ci): remove warnings in tests 2024-07-03 21:00:49 -04:00
Greg Johnston
35f86535d0 feat: 0.7 query signals 2024-07-03 21:00:49 -04:00
Greg Johnston
1ca8e082c3 chore(ci): add Makefiles for smaller packages 2024-07-03 21:00:49 -04:00
Greg Johnston
b20542e22d chore(ci): only run semver checks if not labeled 'breaking' 2024-07-03 21:00:49 -04:00
Greg Johnston
abfff8f98d chore: clippy 2024-07-03 21:00:49 -04:00
Greg Johnston
46c89a5862 rename from new_serde to new 2024-07-03 21:00:49 -04:00
Greg Johnston
32518e46df remove most remaining marker/placeholder elements 2024-07-03 21:00:49 -04:00
Greg Johnston
639f801c79 add trait impls and encodings for SharedValue 2024-07-03 21:00:49 -04:00
Greg Johnston
924358d829 default to SerdeJson encoding for resources, use new_str() for Str encoding 2024-07-03 21:00:49 -04:00
Greg Johnston
91e7266103 feat: synchronous serialized values with SharedValue 2024-07-03 21:00:49 -04:00
Greg Johnston
347611ebec whenever we create a new root Owner, set it as the current owner, which will make it the default owner (e.g., during SSR) instead of None 2024-07-03 21:00:49 -04:00
Greg Johnston
424c3a7209 fix: can't memoize JS properties, because they can be set between signal updates by user input 2024-07-03 21:00:49 -04:00
Greg Johnston
4c078e8eb0 fix: correctly escape style and class attributes 2024-07-03 21:00:49 -04:00
Greg Johnston
0ed1420076 chore: clippy 2024-07-03 21:00:49 -04:00
Greg Johnston
5221675946 don't require spawn_local for actios 2024-07-03 21:00:49 -04:00
Greg Johnston
50d4d08b9b catch resource reads inside Signal during Suspense 2024-07-03 21:00:49 -04:00
Greg Johnston
b51215af8f fix CSS file names 2024-07-03 21:00:49 -04:00
Greg Johnston
e37f3ee756 update todo app csr 2024-07-03 21:00:49 -04:00
Greg Johnston
9c949f6d9a fix: correctly escape text nodes, except in script/style tags 2024-07-03 21:00:49 -04:00
Greg Johnston
59d3a9853f chore: clean up examples for CI 2024-07-03 21:00:49 -04:00
Greg Johnston
4df0a6c7e9 fix: provide matched route via context when rebuilding (so <A> works) 2024-07-03 21:00:49 -04:00
Greg Johnston
4560f5e31c unused 2024-07-03 21:00:49 -04:00
Greg Johnston
0887ada9a9 refactor insert_before_this to find parent lazily, and use it for rebuilding reactive components by replacing their whole contents 2024-07-03 21:00:49 -04:00
Greg Johnston
cddbd24eff make sure SendWrapper supports Futures 2024-07-03 21:00:49 -04:00
Greg Johnston
19db6d9388 move several complex examples into projects 2024-07-03 21:00:49 -04:00
Greg Johnston
466cc39411 update js-framework-benchmark example 2024-07-03 21:00:48 -04:00
Greg Johnston
5b39f7d27f fix test text 2024-07-03 21:00:48 -04:00
Greg Johnston
ab18371c32 fix: custom Stream implementation for streaming resource data that supports nested data/multiple polled values, rather than taking it all at once at the beginning 2024-07-03 21:00:48 -04:00
Greg Johnston
9d818d7796 suspense_tests: actually wait for other resource in nested case 2024-07-03 21:00:48 -04:00
Greg Johnston
5316066612 can save a lookup here 2024-07-03 21:00:48 -04:00
Greg Johnston
10af7b81cc remove unused workspace member 2024-07-03 21:00:48 -04:00
Greg Johnston
51b261d202 update workflows 2024-07-03 21:00:48 -04:00
Greg Johnston
b5e0c2b150 remove unused leptos_reactive integration 2024-07-03 21:00:48 -04:00
Greg Johnston
e322fb1b33 remove old router files 2024-07-03 21:00:48 -04:00
Greg Johnston
24c7fd954e fix Cargo.toml after merge 2024-07-03 21:00:42 -04:00
Greg Johnston
a303814d84 re-enable all routes 2024-07-03 21:00:42 -04:00
Greg Johnston
75d1b14e59 chore: clean up warnings and logging 2024-07-03 21:00:42 -04:00
Greg Johnston
3a7dbafda3 reverted Fn()/FnMut() change 2024-07-03 21:00:41 -04:00
Greg Johnston
3271bcda4e Revert "fix: constrain reactive rendering to Fn(), because using dry_resolve() for Suspense requires idempotent render functions so that they can be called once (to register resources) and called a second time to resolve"
This reverts commit 7ec5c77ba3e8f45bae04a7661a56741f95125adb.
2024-07-03 21:00:41 -04:00
Greg Johnston
36e4eca909 progress on updating suspense tests 2024-07-03 21:00:41 -04:00
Greg Johnston
23d1579d23 add server redirects 2024-07-03 21:00:41 -04:00
Greg Johnston
474fba0ab5 fix: relative path resolution 2024-07-03 21:00:41 -04:00
Greg Johnston
8725a329d2 simplifying todo examples 2024-07-03 21:00:41 -04:00
Greg Johnston
ffa0883b48 initial work updating suspense tests 2024-07-03 21:00:41 -04:00
Greg Johnston
b6ed91b81b clarify hydrate/csr warning 2024-07-03 21:00:41 -04:00
Greg Johnston
fdb298f254 export actions in prelude 2024-07-03 21:00:41 -04:00
Greg Johnston
93d0b3fa26 remove Into<_> by default for setting signals, because it interferes with type inference 2024-07-03 21:00:41 -04:00
Greg Johnston
ab57926d8f add support for unsync actions 2024-07-03 21:00:41 -04:00
Greg Johnston
6eeb22f1f0 simplifying and updating server fns example 2024-07-03 21:00:41 -04:00
Greg Johnston
648d96f316 change name to shell 2024-07-03 21:00:41 -04:00
Greg Johnston
a60e5235d7 update control flow components to new Fn() constraint 2024-07-03 21:00:41 -04:00
Greg Johnston
76deab365e fix: constrain reactive rendering to Fn(), because using dry_resolve() for Suspense requires idempotent render functions so that they can be called once (to register resources) and called a second time to resolve 2024-07-03 21:00:41 -04:00
Greg Johnston
b4948745c7 add Debug impl 2024-07-03 21:00:41 -04:00
Greg Johnston
059df60373 fix: actually concatenate nested routes during route generation 2024-07-03 21:00:41 -04:00
Greg Johnston
5f464298b3 reorganize Outlet export 2024-07-03 21:00:41 -04:00
Greg Johnston
9c304d8d75 examples: porting to 0.7 and cleaning up 2024-07-03 21:00:41 -04:00
Greg Johnston
ca909becc1 fix merge 2024-07-03 21:00:41 -04:00
Rakshith Ravi
f231503baf Update import statements in examples (#2625) 2024-07-03 21:00:41 -04:00
Greg Johnston
d1d6238d9b examples: use application 404 page 2024-07-03 21:00:41 -04:00
Greg Johnston
0543b05738 chore: cargo fmt 2024-07-03 21:00:41 -04:00
Greg Johnston
1a09f1f54a chore: cargo fmt 2024-07-03 21:00:41 -04:00
Greg Johnston
3201cacca1 add warnings if correct features not set for browser 2024-07-03 21:00:41 -04:00
Greg Johnston
454d179cf9 use csr feature so that reactivity runs 2024-07-03 21:00:41 -04:00
Greg Johnston
8c73455eeb chore: clippy 2024-07-03 21:00:41 -04:00
Greg Johnston
e8c5a69412 examples: fix input type so tests work, and update text to make the purpose clearer 2024-07-03 21:00:41 -04:00
Greg Johnston
6088da7342 remove leptos_reactive (moved into reactive_graph and leptos_server) 2024-07-03 21:00:41 -04:00
Greg Johnston
ea76a0f74e fix: Clone for ArcResource and default to SerdeJson for Resource 2024-07-03 21:00:31 -04:00
Greg Johnston
5e43d37601 chore: clippy 2024-07-03 21:00:31 -04:00
Greg Johnston
d70ef1178e fix: don't dispose of parent owners before Suspense children have been rendered 2024-07-03 21:00:31 -04:00
Greg Johnston
30556af5f6 warn if trying to use meta on server side without context 2024-07-03 21:00:31 -04:00
Greg Johnston
9255ad1840 only run RenderEffects when effects are enabled 2024-07-03 21:00:31 -04:00
Greg Johnston
e53d139fc1 add set_pending to <Transition/> 2024-07-03 21:00:31 -04:00
Greg Johnston
07f1eed36a simplify FlatRoutes logic by using existing OwnedView infrastructure 2024-07-03 21:00:31 -04:00
Greg Johnston
02587781ac reexport tick() for testing 2024-07-03 21:00:31 -04:00
Greg Johnston
d32d6d8fe8 fix: ensure that leptos_meta and leptos_router are in SSR mode if using one of the server integrations 2024-07-03 21:00:31 -04:00
Greg Johnston
c10a3d251d examples: update hackernews for SSR support 2024-07-03 21:00:31 -04:00
Greg Johnston
8550b54be6 fix: correctly notify multiple subscribers to same AsyncDerived 2024-07-03 21:00:31 -04:00
Greg Johnston
becc1075ab fix: Routes SSR 2024-07-03 21:00:31 -04:00
Greg Johnston
6b5467d451 fix: correct owner for HTML rendering in FlatRoutes 2024-07-03 21:00:31 -04:00
Greg Johnston
3375dbdcbc testing: provide tick() that can be called anywhere in tests 2024-07-03 21:00:30 -04:00
Greg Johnston
4842ef28e0 testing: provide tick() that can be called anywhere in tests 2024-07-03 21:00:30 -04:00
Greg Johnston
8945fc8724 fix portal tests 2024-07-03 21:00:30 -04:00
Greg Johnston
bee37de5c9 fix cleanups in render effects 2024-07-03 21:00:30 -04:00
Greg Johnston
b192136a4b chore: clippy 2024-07-03 21:00:30 -04:00
Greg Johnston
907b9df06e update counters_isomorphic 2024-07-03 21:00:30 -04:00
Greg Johnston
b6a62ab4d9 reexport spawn and spawn_local 2024-07-03 21:00:30 -04:00
Greg Johnston
e36fce4351 ReadSignal from stream 2024-07-03 21:00:30 -04:00
Greg Johnston
76ec0b78c2 refactor to allow rendering Resource directly in view 2024-07-03 21:00:30 -04:00
Greg Johnston
bec33e255d removed AnimatedShow example (duplicates the component docs) 2024-07-03 21:00:30 -04:00
Greg Johnston
cdcfcf6a0e properly serialize errors 2024-07-03 21:00:30 -04:00
Greg Johnston
422de7c8af chore: clear warning 2024-07-03 21:00:30 -04:00
Greg Johnston
662bd4fd78 pick up on server action error in both server and client 2024-07-03 21:00:30 -04:00
Greg Johnston
a4b4e2b3ac fmt and chores in examples 2024-07-03 21:00:30 -04:00
Greg Johnston
4e84a78307 fix: serialize an empty string into HTML so it still works as a text node 2024-07-03 21:00:30 -04:00
Greg Johnston
012535a2d7 fix: make router fallback lazy 2024-07-03 21:00:30 -04:00
Greg Johnston
43c953c4b9 add expect_context 2024-07-03 21:00:30 -04:00
Greg Johnston
143973960c fix attr:class when spreading onto a component 2024-07-03 21:00:30 -04:00
Greg Johnston
8a0f43affe add ServerAction error handling for any error type (closes #2325) 2024-07-03 21:00:30 -04:00
Greg Johnston
b55a19a533 remove unused import 2024-07-03 21:00:30 -04:00
Greg Johnston
21cdadf461 clean up example 2024-07-03 21:00:30 -04:00
Greg Johnston
d95e59a685 add CollectView 2024-07-03 21:00:30 -04:00
Greg Johnston
28468a0bae Actix todo_app_sqlite 2024-07-03 21:00:30 -04:00
Greg Johnston
b183bb981c fix: don't drop Owner in FlatRoutes until route has been rendered (thanks @benwis) 2024-07-03 21:00:30 -04:00
Greg Johnston
ee5e4bc5c0 fix: make sure all resource reads are registered 2024-07-03 21:00:30 -04:00
Greg Johnston
581d5d0469 chore: clippy and unused dependencies in integrations 2024-07-03 21:00:30 -04:00
Greg Johnston
d2bb6d5062 add some tracing and debug info to HTML elements 2024-07-03 21:00:30 -04:00
Greg Johnston
8a419705d8 refactor integrations and add Actix integration 2024-07-03 21:00:30 -04:00
Greg Johnston
0a7b025534 feat: 0.7 nonce support 2024-07-03 20:59:48 -04:00
Greg Johnston
060338e643 ResponseOptions support 2024-07-03 20:59:48 -04:00
Greg Johnston
8dee986164 fix counters tests 2024-07-03 20:59:48 -04:00
Greg Johnston
05166d2cb7 allow .children() on HTML elements 2024-07-03 20:59:48 -04:00
Greg Johnston
40d8cfb04b remove async demo 2024-07-03 20:59:48 -04:00
Greg Johnston
53fbe76761 fix: writing to lock that has a read 2024-07-03 20:59:48 -04:00
Greg Johnston
c3d8d1e828 allow untracking on write guards to support maybe_update 2024-07-03 20:59:48 -04:00
Greg Johnston
4636192fa3 feat: allow .write() on all writeable signals 2024-07-03 20:59:48 -04:00
Greg Johnston
02705dec31 feat: add .by_ref() to create a Future from an AsyncDerived (etc.) that takes a reference, rather than cloning 2024-07-03 20:59:48 -04:00
Greg Johnston
dc09faf7eb use impl trait in props 2024-07-03 20:59:48 -04:00
Greg Johnston
402eb95221 update wasm-bindgen testing approaches 2024-07-03 20:59:48 -04:00
Greg Johnston
d92b430fbf chore: clearing warnings in examples 2024-07-03 20:59:48 -04:00
Greg Johnston
030d06521e additional warnings 2024-07-03 20:59:48 -04:00
Greg Johnston
c8f2ef375b cargo fmt 2024-07-03 20:59:48 -04:00
Greg Johnston
8ed8b5605b chore: clear up... a few warnings 2024-07-03 20:59:48 -04:00
Greg Johnston
7c526cfa52 update sledgehammer integration 2024-07-03 20:59:48 -04:00
Greg Johnston
5e20b8fcca remove signal function setter Send-only implementation (dead code) 2024-07-03 20:59:48 -04:00
Greg Johnston
6b3ccdf2f4 remove signal function call Read implementations (dead code) 2024-07-03 20:59:48 -04:00
Greg Johnston
d7a321aa69 remove leptos_reactive dependency 2024-07-03 20:59:48 -04:00
Greg Johnston
abfa2d02fe oco merge issues 2024-07-03 20:59:48 -04:00
Greg Johnston
7b8edda5ae feat: return an async guard from .await rather than cloning the value every time 2024-07-03 20:59:48 -04:00
Greg Johnston
967bf2fdfc fix return type in async tests 2024-07-03 20:59:48 -04:00
Greg Johnston
274ac2ba34 fix tests that run effects 2024-07-03 20:59:48 -04:00
Greg Johnston
3b10fb54c6 feat: return Option from AsyncDerived.get() instead of AsyncState 2024-07-03 20:59:48 -04:00
Greg Johnston
1274c0890e example: restore ErrorBoundary 2024-07-03 20:59:48 -04:00
Greg Johnston
b05bbb5499 docs for Owner and context 2024-07-03 20:59:48 -04:00
Greg Johnston
77bce6d440 fix tests 2024-07-03 20:59:48 -04:00
Greg Johnston
4f01c4f61e poll AsyncDerived synchronously so that it has the correct value during hydration if it reads from a resource 2024-07-03 20:59:48 -04:00
Greg Johnston
0812f8d850 correct dirty-checking on AsyncDerived 2024-07-03 20:59:48 -04:00
Greg Johnston
059968ca58 fix regular suspense if nothing was read synchronously 2024-07-03 20:59:48 -04:00
Greg Johnston
b67229ca78 missing dry_resolve on Static 2024-07-03 20:59:48 -04:00
Greg Johnston
d59f234d88 feat: support *either* .await or reactive reads inside Suspense 2024-07-03 20:59:48 -04:00
Greg Johnston
1e2815b0a0 feat: 0.7 slots 2024-07-03 20:59:48 -04:00
Greg Johnston
4ae8a6d54c feat: enhanced spreading syntax 2024-07-03 20:59:48 -04:00
Greg Johnston
3c3e97e8b9 fix external navigations 2024-07-03 20:59:48 -04:00
Greg Johnston
83be4167d8 make WindowListenerHandle Send + Sync so it can be remove via on_cleanup 2024-07-03 20:59:48 -04:00
Greg Johnston
691b44baa1 restore ssr/hydration for Routes 2024-07-03 20:59:48 -04:00
Greg Johnston
c58f05e129 get nested Routes working again 2024-07-03 20:59:48 -04:00
Greg Johnston
ddfa4dd76f default to Params::get() giving an owned value (which you want in a derived signal), but use reference in the macro 2024-07-03 20:59:48 -04:00
Greg Johnston
1dd8175aa4 add proper dirty checking on AsyncDerived so it can read from memos properly 2024-07-03 20:59:48 -04:00
Greg Johnston
18c5e4c804 make NavigateOptions pub 2024-07-03 20:59:48 -04:00
Greg Johnston
65a30910b1 feat: owning memo 2024-07-03 20:59:48 -04:00
Greg Johnston
f0b6995f50 remove warnings in tests and only run if effects are enabled 2024-07-03 20:59:48 -04:00
Greg Johnston
ffce98f928 fix: prevent memos that have changed from re-triggering the running effect, by setting the Observer during .update_if_necessary() 2024-07-03 20:59:48 -04:00
Greg Johnston
3b71be89ca feat: add Popover API 2024-07-03 20:59:47 -04:00
Greg Johnston
941ea12420 fix Script children 2024-07-03 20:59:47 -04:00
Greg Johnston
e44504f8ba fix hydration of Suspend by including the missing placeholder it expects during hydration 2024-07-03 20:59:47 -04:00
Greg Johnston
9924f8fef7 add missing marker comments for Result 2024-07-03 20:59:47 -04:00
Greg Johnston
cb2f66a955 include marker comments in html len 2024-07-03 20:59:47 -04:00
Greg Johnston
c43379cb68 unused owner 2024-07-03 20:59:47 -04:00
Greg Johnston
71e34935e5 impl From/Into for Signal/ArcSignal 2024-07-03 20:59:47 -04:00
Greg Johnston
ab9a1d8b0a add ArcSignal::derive() 2024-07-03 20:59:47 -04:00
Greg Johnston
05db18e2b8 routing progress indicator 2024-07-03 20:59:47 -04:00
Greg Johnston
b530b46064 missing min attribute 2024-07-03 20:59:47 -04:00
Greg Johnston
ebeec2c3bd clean up 2024-07-03 20:59:47 -04:00
Greg Johnston
a4304876bf remove log 2024-07-03 20:59:47 -04:00
Greg Johnston
38ca7137e0 relax trait bounds on reactive types where possible 2024-07-03 20:59:47 -04:00
Greg Johnston
9b6108dae7 add SignalSetter 2024-07-03 20:59:47 -04:00
Greg Johnston
6092971f7c use transition between navigations 2024-07-03 20:59:47 -04:00
Greg Johnston
80e5274a88 add async transitions that wait for any AsyncDerived created/triggered under them before resolving 2024-07-03 20:59:47 -04:00
Greg Johnston
0d705c3318 resolve() on OwnedView 2024-07-03 20:59:47 -04:00
Greg Johnston
1c3b157293 restore hydration feature for some of its feature-gating benefits for Resource deserialization 2024-07-03 20:59:47 -04:00
Greg Johnston
ff950daa6e cargo fmt 2024-07-03 20:59:47 -04:00
Greg Johnston
af1cb9fca1 create separate URL/params signals for each route, to prevent updating them and running side effects while navigating away 2024-07-03 20:59:47 -04:00
Greg Johnston
d82e43f526 fmt 2024-07-03 20:59:47 -04:00
Greg Johnston
b95b8ea43d distinguish between dirty and check in effects, so that memos and signals both work correctly 2024-07-03 20:59:47 -04:00
Greg Johnston
077dd85964 remove unused feature 2024-07-03 20:59:47 -04:00
Greg Johnston
f24af45e19 updated future impls 2024-07-03 20:59:47 -04:00
Greg Johnston
ce2390d6d0 check whether ArcAsyncDerived actually needs to run when marked check 2024-07-03 20:59:47 -04:00
Greg Johnston
a82a72400d add ancestry debugging for owners 2024-07-03 20:59:47 -04:00
Greg Johnston
e37ca85bdd lazy Future construction for AsyncDerived 2024-07-03 20:59:47 -04:00
Greg Johnston
de138b397c support Resource in CSR for backward-compat 2024-07-03 20:59:47 -04:00
Greg Johnston
28ae64bc06 allow let: syntax to work 2024-07-03 20:59:47 -04:00
Greg Johnston
95b4cd3841 scope Suspense/Transition correctly within ownership tree 2024-07-03 20:59:47 -04:00
Greg Johnston
6f7522381c upgrading hackernews example 2024-07-03 20:59:47 -04:00
Greg Johnston
d6997bddc5 immediately commit URL signal updates 2024-07-03 20:59:47 -04:00
Greg Johnston
7de95ff99f reexport A from router::components 2024-07-03 20:59:47 -04:00
Greg Johnston
fa28d56928 add IntoAny to tachys prelude 2024-07-03 20:59:47 -04:00
Greg Johnston
3f2cdf77a3 finish support for innerHTML 2024-07-03 20:59:47 -04:00
Greg Johnston
f8500f416f feat: iterating over items in children with ChildrenFragment, ChildrenFragmentFn, ChildrenFragmentMut 2024-07-03 20:59:47 -04:00
Greg Johnston
2f81a81c06 only warn about non-reactive accesses if effects are enabled 2024-07-03 20:59:47 -04:00
Greg Johnston
ffb8e8bea3 only run effects on client 2024-07-03 20:59:47 -04:00
Greg Johnston
6f158a8974 resolve() implementation for AnyView 2024-07-03 20:59:47 -04:00
Greg Johnston
2cc1ec9b3c fix deadlock on nested Signals 2024-07-03 20:59:47 -04:00
Greg Johnston
dbed68e5ba fix FlatRouter SSR/hydration after lazy routes 2024-07-03 20:59:47 -04:00
Greg Johnston
1a1d2e1c07 feat: nested islands with context for 0.7 2024-07-03 20:59:47 -04:00
Greg Johnston
b3871dea75 fix: correct Send + Sync bounds for children 2024-07-03 20:59:47 -04:00
Greg Johnston
eba4711fa7 feat: minimal island support in 0.7 2024-07-03 20:59:47 -04:00
Greg Johnston
e8273348db docs: full docs and doctests for Action/MultiAction 2024-07-03 20:59:47 -04:00
Greg Johnston
af051aa72a remove support for rendering guards directly, as they are !Send and holding onto them in State is also a bad idea 2024-07-03 20:59:47 -04:00
Greg Johnston
e9ec7412fa support nightly static values for style:key="value" 2024-07-03 20:59:47 -04:00
Greg Johnston
e5757c56b7 revert to using .get() for function calls 2024-07-03 20:59:47 -04:00
Greg Johnston
031d78cd5a fix: only rerun effects if they have dirty ancestors (or it's the first run) 2024-07-03 20:59:47 -04:00
Greg Johnston
a0ba356cc1 start working on porting over docs and tests and 0.7... 2024-07-03 20:59:47 -04:00
Greg Johnston
adf6a8e368 fix meta issue with attributes 2024-07-03 20:59:47 -04:00
Greg Johnston
6eed4e8253 fix tracing issue 2024-07-03 20:59:47 -04:00
Greg Johnston
88d311a0c5 chore: get tests in a working state 2024-07-03 20:59:47 -04:00
Greg Johnston
0d7db85e9e fix: make Selector Send/Sync 2024-07-03 20:59:47 -04:00
Greg Johnston
2f77fb1892 docs: runtime warning if you use .track() outside a tracking context 2024-07-03 20:59:47 -04:00
Greg Johnston
a66662397c preliminary tracing for tachys 2024-07-03 20:59:47 -04:00
Greg Johnston
105e2c7686 chore: warnings 2024-07-03 20:59:47 -04:00
Greg Johnston
324bebcf50 examples: router in 0.7 2024-07-03 20:59:47 -04:00
Greg Johnston
e553ad3a68 fix: passing context through router 2024-07-03 20:59:47 -04:00
Greg Johnston
b7ecac308f chore: fix warnings about variable case 2024-07-03 20:59:47 -04:00
Greg Johnston
79ebd416a3 examples: timer in 0.7 2024-07-03 20:59:47 -04:00
Greg Johnston
4e2b9b1878 feat: Portals in 0.7 2024-07-03 20:59:47 -04:00
Greg Johnston
c1a6f2f479 allow either eager or lazy routes 2024-07-03 20:59:47 -04:00
Greg Johnston
fb855cb07f update StoredValue API in callbacks 2024-07-03 20:59:47 -04:00
Greg Johnston
1850231c92 chore: clippy warnings 2024-07-03 20:59:47 -04:00
Greg Johnston
55c7b84a00 smooth out StoredValue APIs 2024-07-03 20:59:47 -04:00
Greg Johnston
4e2646513f MaybeSignal and MaybeProp 2024-07-03 20:59:47 -04:00
Marc-Stefan Cassola
9a75edd34c added a few old deprecated functions to help users port (#2580) 2024-07-03 20:59:47 -04:00
Greg Johnston
81afa8d0c8 implement With(Untracked) for Signal 2024-07-03 20:59:47 -04:00
Greg Johnston
d3919d3568 don't over-rerender nested router 2024-07-03 20:59:47 -04:00
Greg Johnston
5b23fddd02 initial async routing work (to support bundle splitting) 2024-07-03 20:59:47 -04:00
Greg Johnston
8de1f86db3 noop attribute 'spreading' for routers 2024-07-03 20:59:46 -04:00
Greg Johnston
97901bfedb support arbitrary attributes on components in view 2024-07-03 20:59:46 -04:00
Greg Johnston
f6eb7fa8b6 full attribute spreading 2024-07-03 20:59:46 -04:00
Greg Johnston
36ccc3d834 update counter_without_macros imports 2024-07-03 20:59:46 -04:00
Greg Johnston
82ba7195c8 stashing 2024-07-03 20:59:46 -04:00
Greg Johnston
5f7cdb1091 give a route to upgrade any attribute into a cloneable one 2024-07-03 20:59:46 -04:00
Greg Johnston
e3a0f59f4a work on attribute spreading 2024-07-03 20:59:46 -04:00
Greg Johnston
b77e127588 disable AddAnyAttr again now that I remember why it was broken 2024-07-03 20:59:46 -04:00
Greg Johnston
c0d51ede3d reenable AnyAttr 2024-07-03 20:59:46 -04:00
Greg Johnston
49b2b5047e reorganizing exports and updating examples 2024-07-03 20:59:46 -04:00
Greg Johnston
058d357e59 prep for preview release 2024-07-03 20:59:46 -04:00
Greg Johnston
6b0a47ae8a fix reorganized exports 2024-07-03 20:59:46 -04:00
Greg Johnston
49de4bc671 prep for preview release 2024-07-03 20:59:46 -04:00
Greg Johnston
2033ce251e prep for preview release 2024-07-03 20:59:46 -04:00
Greg Johnston
c37a4e02a6 prep for preview release 2024-07-03 20:59:46 -04:00
Greg Johnston
39357bf9a7 module restructuring for 0.7 2024-07-03 20:59:46 -04:00
Greg Johnston
5ead1ec3df let ErrorBoundary own the fallback 2024-07-03 20:59:46 -04:00
Greg Johnston
1826586d03 make Suspend a transparent wrapper 2024-07-03 20:59:46 -04:00
Greg Johnston
ad29695eac provide params properly in FlatRouter 2024-07-03 20:59:46 -04:00
Greg Johnston
76a12a9bf4 clear some warnings 2024-07-03 20:59:46 -04:00
Greg Johnston
8ce815f210 rename TupleBuilder to NextTuple and prep for release 2024-07-03 20:59:46 -04:00
Greg Johnston
e9a05f095e prep for preview release 2024-07-03 20:59:46 -04:00
Greg Johnston
c114df5ebb prep for preview release 2024-07-03 20:59:46 -04:00
Greg Johnston
17977d8fb7 prep for preview release 2024-07-03 20:59:46 -04:00
Greg Johnston
455cbc07a6 prep for preview release 2024-07-03 20:59:46 -04:00
Greg Johnston
272b6da00c rename any_error 2024-07-03 20:59:46 -04:00
Greg Johnston
09cc5df975 prep for preview release 2024-07-03 20:59:46 -04:00
Greg Johnston
106aaaf412 remove twiggy file 2024-07-03 20:59:46 -04:00
Greg Johnston
521172ef5f move router crates 2024-07-03 20:59:46 -04:00
Greg Johnston
51d0ed4735 comparison demo 2024-07-03 20:59:33 -04:00
Greg Johnston
05bd7a6276 SSR optimizations for binary size, and flat router 2024-07-03 20:59:33 -04:00
Greg Johnston
7f911ac26a work on Axum integration and on error boundaries 2024-07-03 20:57:51 -04:00
Greg Johnston
3d0810bb5e stash 2024-07-03 20:57:51 -04:00
Greg Johnston
49f1fce64d feat: add <A> 2024-07-03 20:57:51 -04:00
Greg Johnston
86377d208d add use_navigate and Redirect 2024-07-03 20:57:51 -04:00
Greg Johnston
d07bcb1bb4 preliminary use_navigate work 2024-07-03 20:57:51 -04:00
Greg Johnston
9389195e6b fix fallback => match update 2024-07-03 20:57:51 -04:00
Greg Johnston
b98ba8e2fa add more hooks and primitives to router 2024-07-03 20:57:51 -04:00
Greg Johnston
005766495c nested route CSR working 2024-07-03 20:57:51 -04:00
Greg Johnston
1cb9a82239 continuing on nested routes 2024-07-03 20:57:51 -04:00
Greg Johnston
fcdc5f8b9e continuing on nested routes 2024-07-03 20:57:51 -04:00
Greg Johnston
aa624fccc7 working on reconfiguring nested routing 2024-07-03 20:57:51 -04:00
Greg Johnston
d742179c2f make placeholder-finding code consistent across container types 2024-07-03 20:57:51 -04:00
Greg Johnston
470f7f15fe remove logs 2024-07-03 20:57:51 -04:00
Greg Johnston
4f45b1032e fix Transition hydration 2024-07-03 20:57:51 -04:00
Greg Johnston
5f3623574d remove TryCatch/fallible rendering in favor of better ErrorBoundary model 2024-07-03 20:57:51 -04:00
Greg Johnston
fbde9eaefa finish todo_app_sqlite_axum 2024-07-03 20:57:51 -04:00
Greg Johnston
83067627db fix Vec hydration 2024-07-03 20:57:51 -04:00
Greg Johnston
53d51e03ff add MultiActionForm 2024-07-03 20:57:51 -04:00
Greg Johnston
0205d715c2 add MultiAction/ServerMultiAction 2024-07-03 20:57:51 -04:00
Greg Johnston
05b7e83778 stash 2024-07-03 20:57:51 -04:00
Greg Johnston
4d0339ee05 ErrorBoundary SSR and serialization of errors to support hydration 2024-07-03 20:57:51 -04:00
Greg Johnston
fba207df08 get types working with nested ErrorBoundary/Suspense 2024-07-03 20:57:51 -04:00
Greg Johnston
a16367215c probably as far as I can go with the current SuspenseBoundary approach 2024-07-03 20:57:51 -04:00
Greg Johnston
376b90d60b fix static types 2024-07-03 20:57:51 -04:00
Greg Johnston
20b0894b9f fix cancellation logic for server fn requests 2024-07-03 20:57:51 -04:00
Greg Johnston
c197131b6b only subscribe to memo manually if already loaded 2024-07-03 20:57:51 -04:00
Greg Johnston
1ea18bb3eb Suspense SSR 2024-07-03 20:57:51 -04:00
Greg Johnston
62decfde51 updates toward todo_app_sqlite 2024-07-03 20:57:51 -04:00
Greg Johnston
8f3ecd84b2 fix stable examples 2024-07-03 20:57:51 -04:00
Greg Johnston
6b1f6563d2 implement rendering traits for signals directly on stable 2024-07-03 20:57:51 -04:00
Greg Johnston
b5bfa41400 suspend!() macro 2024-07-03 20:57:51 -04:00
Greg Johnston
018f347673 add Transition 2024-07-03 20:57:51 -04:00
Greg Johnston
ab35ea7d21 loosen requirements for Show 2024-07-03 20:57:51 -04:00
Greg Johnston
cb0a0292d5 working on examples 2024-07-03 20:57:51 -04:00
Greg Johnston
351e42e885 finish TodoMVC example 2024-07-03 20:57:51 -04:00
Greg Johnston
3a89396ccc simplify Suspense: this should still work with hydration 2024-07-03 20:57:51 -04:00
Greg Johnston
32183692c0 working model for Suspense with new version 2024-07-03 20:57:51 -04:00
Greg Johnston
4cf95432b7 probably as far as I can go with the current SuspenseBoundary approach 2024-07-03 20:57:51 -04:00
Greg Johnston
b24e52773f fix ErrorBoundary/Suspense 2024-07-03 20:57:51 -04:00
Greg Johnston
3bcf7c7355 feat: ErrorBoundary and Suspense 2024-07-03 20:57:51 -04:00
Greg Johnston
be971d018a feat: ErrorBoundary 2024-07-03 20:57:51 -04:00
Greg Johnston
1f391d08c0 fix Cargo.toml merge issues 2024-07-03 20:57:51 -04:00
Greg Johnston
8682487650 working on examples 2024-07-03 20:57:50 -04:00
Greg Johnston
3c062e5b3e styling with CSS 2024-07-03 20:57:50 -04:00
Greg Johnston
6117cfa849 example with isomorphic GTK/web design system 2024-07-03 20:57:50 -04:00
Greg Johnston
7344618160 gtk example 2024-07-03 20:57:50 -04:00
Greg Johnston
83696c14da ErrorBoundary component 2024-07-03 20:57:50 -04:00
Greg Johnston
eacaaaec90 Suspense/Transition components 2024-07-03 20:57:50 -04:00
Greg Johnston
c51e8f3569 GTK example for 0.7 2024-07-03 20:57:50 -04:00
Greg Johnston
64fc1b8bd1 add serde-wasm-bindgen encoding for resources 2024-07-03 20:57:50 -04:00
Greg Johnston
1b4ae08943 add typed children 2024-07-03 20:57:50 -04:00
Greg Johnston
eff6aa2459 scope Arena to each request 2024-07-03 20:57:50 -04:00
Greg Johnston
8e6c2e50b4 correctly omit HTML-generating code from AnyView 2024-07-03 20:57:50 -04:00
Greg Johnston
dd9aa9e4cd experimental sledgehammer Renderer backend 2024-07-03 20:57:50 -04:00
Greg Johnston
47e11acf80 fix async context issues, add flat routing 2024-07-03 20:57:50 -04:00
Greg Johnston
3bed48abaa test more dynamic string length work 2024-07-03 20:57:50 -04:00
Greg Johnston
a72221de2a attribute value escaping 2024-07-03 20:57:50 -04:00
Greg Johnston
0243a705fa work related to 0.7 blog port 2024-07-03 20:57:50 -04:00
Greg Johnston
abaab492c0 work related to 0.7 blog port 2024-07-03 20:57:22 -04:00
Greg Johnston
935bdd2d61 completing work on meta 2024-07-03 20:57:09 -04:00
Greg Johnston
c5679b9a2a completing work on meta 2024-07-03 20:57:09 -04:00
Greg Johnston
d2ef1c833e initial work on meta 2024-07-03 20:57:09 -04:00
Greg Johnston
e357ca5d02 initial work on meta 2024-07-03 20:57:09 -04:00
Greg Johnston
e913ad7439 stash 2024-07-03 20:56:37 -04:00
Greg Johnston
6b57437514 fix nested route rebuilding 2024-07-03 20:56:37 -04:00
Greg Johnston
19c965bb35 navigation between nested routes 2024-07-03 20:56:37 -04:00
Greg Johnston
657d0057f2 initial stage for working nested route rendering 2024-07-03 20:56:37 -04:00
Greg Johnston
45f5a4ea39 stash 2024-07-03 20:56:37 -04:00
Greg Johnston
feeab73833 stash 2024-07-03 20:56:37 -04:00
Greg Johnston
10c142a655 get basic routing working 2024-07-03 20:56:37 -04:00
Greg Johnston
d97e72d2f4 stash 2024-07-03 20:56:37 -04:00
Greg Johnston
3952fa4952 reorganize 2024-07-03 20:56:37 -04:00
Greg Johnston
87772466d1 working on nesting routing 2024-07-03 20:56:37 -04:00
Greg Johnston
8479fddf92 reorganize 2024-07-03 20:56:37 -04:00
Greg Johnston
8b738d3a2a stash 2024-07-03 20:56:37 -04:00
Greg Johnston
df7f83165b abstract interface to walk nested routes and to access views 2024-07-03 20:56:37 -04:00
Greg Johnston
f54b4f3d1e reorganize and clean up 2024-07-03 20:56:37 -04:00
Greg Johnston
21a8bd31c7 nested route matching 2024-07-03 20:56:37 -04:00
Greg Johnston
02e9e48d89 stash 2024-07-03 20:56:37 -04:00
Greg Johnston
e0a1b7a813 stash 2024-07-03 20:56:37 -04:00
Greg Johnston
748c600e59 work on routing utils 2024-07-03 20:56:37 -04:00
Greg Johnston
26cacbd379 nested route matching working 2024-07-03 20:56:37 -04:00
Greg Johnston
36df86b3b7 stash 2024-07-03 20:56:37 -04:00
Greg Johnston
57fd178afb use either_of crate 2024-07-03 20:56:37 -04:00
Greg Johnston
ce559e1e22 nested routes take 1 2024-07-03 20:56:37 -04:00
Greg Johnston
ff51f064d4 split EitherOfX into its own crate 2024-07-03 20:56:37 -04:00
Greg Johnston
3379462633 work on routing 2024-07-03 20:56:37 -04:00
Greg Johnston
3e3359bea1 work on routing 2024-07-03 20:56:37 -04:00
Greg Johnston
0702b02011 set up routing 2024-07-03 20:56:37 -04:00
Greg Johnston
5af8ca4202 clear warning 2024-07-03 20:56:37 -04:00
Greg Johnston
17e822c14b chore: clear warnings 2024-07-03 20:56:37 -04:00
Greg Johnston
3db9e627db pass on: to components (and lay basis for passing all other attributes) 2024-07-03 20:56:37 -04:00
Greg Johnston
1cb0c6c5c8 working on AddAttr 2024-07-03 20:56:37 -04:00
Greg Johnston
de81d9d92f remove boilerplate: require that Node, Element, etc. types always be Clone + 'static 2024-07-03 20:56:37 -04:00
Greg Johnston
6a107cfa23 parent_child example 2024-07-03 20:56:37 -04:00
Greg Johnston
93d00ae968 use AnyError for all try_ rendering errors, so that they can compose 2024-07-03 20:56:37 -04:00
Greg Johnston
cd322144f7 support for guards with class: syntax 2024-07-03 20:56:37 -04:00
Greg Johnston
d89025e347 add Borrow implementation to make it easier to abstract over T and Guard<T> 2024-07-03 20:56:37 -04:00
Greg Johnston
ebc7bcd469 finish error boundary (fix last state transition issue) 2024-07-03 20:56:37 -04:00
Greg Johnston
597dc6c625 progress on error boundary that works with nested reactivity 2024-07-03 20:56:37 -04:00
Greg Johnston
45daa770fe progress on error boundary that works with nested reactivity 2024-07-03 20:56:37 -04:00
Greg Johnston
16b282da9e error example 2024-07-03 20:56:37 -04:00
Greg Johnston
dccf5a010d enable event delegation 2024-07-03 20:56:37 -04:00
Greg Johnston
5cdfdf52bd fix release build 2024-07-03 20:56:37 -04:00
Greg Johnston
9fc3b8b52b update TODO.md 2024-07-03 20:56:37 -04:00
Greg Johnston
d4555671e1 store effects in reactive system 2024-07-03 20:56:37 -04:00
Greg Johnston
c83a3b537c todomvc example 2024-07-03 20:56:37 -04:00
Greg Johnston
d09d6acbf1 work on async demo 2024-07-03 20:56:37 -04:00
Greg Johnston
9d93c451a6 clone values for Futures 2024-07-03 20:56:36 -04:00
Greg Johnston
ca298ea3d8 make guard types more nestable/flexible so that we can implement render traits on any of them 2024-07-03 20:56:36 -04:00
Greg Johnston
0339392658 work on async demo 2024-07-03 20:56:36 -04:00
Greg Johnston
ae36060ebe work on async demo 2024-07-03 20:56:36 -04:00
Greg Johnston
46a839bf43 feat: create generic any_spawner crate to share between reactive system and renderer 2024-07-03 20:56:36 -04:00
Greg Johnston
c274518c18 add other methods on Stored 2024-07-03 20:56:36 -04:00
Greg Johnston
b204f569eb work on async demo 2024-07-03 20:56:36 -04:00
Greg Johnston
a3286fd9b6 stash: working on jsfb 2024-07-03 20:56:36 -04:00
Greg Johnston
9fd5a646f1 chore: remove unnecessary log 2024-07-03 20:56:36 -04:00
Greg Johnston
65b2042682 fix: correct owner for rows of For, correct cleanup of arenas 2024-07-03 20:56:36 -04:00
Greg Johnston
c57347edd7 fix: close memory leak in tasks waiting on channels 2024-07-03 20:56:36 -04:00
Greg Johnston
8f7db58b7c feat: typed event targets 2024-07-03 20:56:36 -04:00
Greg Johnston
bae1312f06 working on examples 2024-07-03 20:56:36 -04:00
Greg Johnston
5e9a69a9ca begin migrating to leptos and leptos_dom packages 2024-07-03 20:56:36 -04:00
Greg Johnston
bcfe54b1ca stash 2024-07-03 20:55:53 -04:00
Greg Johnston
2a2a3d1461 stash 2024-07-03 20:55:53 -04:00
Greg Johnston
b70c4da854 chore: remove leptos_reactive and add reactive_graph 2024-07-03 20:55:53 -04:00
Greg Johnston
0436a82c65 feat: improved ergonomics of read guards 2024-07-03 20:55:53 -04:00
Greg Johnston
6260ca49b0 feat: add Readable implementation for all types 2024-07-03 20:55:52 -04:00
Greg Johnston
d045ad335d feat: add no_std support in appropriate crates 2024-07-03 20:55:52 -04:00
Greg Johnston
3bb34b2358 feat: tachys 2024-07-03 20:55:52 -04:00
Greg Johnston
27b2eca74c feat: add Fn traits 2024-07-03 20:55:52 -04:00
Greg Johnston
1a525fe9e7 docs: note re: execution order (see #2261 and #2262) 2024-07-03 20:55:52 -04:00
Greg Johnston
6f24d29bcf feat: modular SharedContext for hydration 2024-07-03 20:55:52 -04:00
Greg Johnston
d2f88f004d chore: split OrPoisoned trait into its own crate for reuse 2024-07-03 20:55:52 -04:00
Greg Johnston
33f0720be1 feat: modular, trait-based, Send/Sync reactive system 2024-07-03 20:55:52 -04:00
353 changed files with 15561 additions and 12786 deletions

View File

@@ -1,13 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "cargo"
directories:
- "/"
- "/examples/*"
- "/benchmarks"
schedule:
interval: "daily"

View File

@@ -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

View File

@@ -49,4 +49,4 @@ jobs:
with:
directory: ${{ matrix.directory }}
cargo_make_task: "ci"
toolchain: nightly-2024-08-01
toolchain: nightly-2024-04-14

View File

@@ -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"

View File

@@ -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/**

View File

@@ -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/**

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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)
}
}

View File

@@ -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"]

View File

@@ -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;

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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"

View File

@@ -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",

View File

@@ -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`.

View File

@@ -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);
}

View File

@@ -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"

View File

@@ -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"/> }
}

View File

@@ -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]

View File

@@ -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>
}

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"] }

View File

@@ -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>
}
}

View File

@@ -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"

View File

@@ -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"]

View File

@@ -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"

View File

@@ -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()

View File

@@ -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"]

View File

@@ -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
}
}

View File

@@ -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};

View File

@@ -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"

View File

@@ -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) => {

View File

@@ -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>

View File

@@ -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]

View File

@@ -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) => {

View File

@@ -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>

View File

@@ -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 = [

View File

@@ -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) => {

View File

@@ -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>

View File

@@ -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 }

View 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()
}

View 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()))
}
}

View File

@@ -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");

View File

@@ -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) => {

View File

@@ -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) => {

View File

@@ -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]

View File

@@ -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"

View File

@@ -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.

View File

@@ -1,4 +0,0 @@
extend = [
{ path = "../cargo-make/main.toml" },
{ path = "../cargo-make/cargo-leptos.toml" },
]

View File

@@ -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

View File

@@ -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);
});

View File

@@ -1,2 +0,0 @@
[toolchain]
channel = "stable" # test change

View File

@@ -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> }
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -1,3 +0,0 @@
.pending {
color: purple;
}

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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>
}
}

View File

@@ -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]

View File

@@ -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()

View File

@@ -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"

View File

@@ -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"]

View File

@@ -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>

View File

@@ -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]

View File

@@ -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

View File

@@ -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"

View File

@@ -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();

View File

@@ -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]

View File

@@ -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"

View File

@@ -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

View File

@@ -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> }
})

View File

@@ -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",

View File

@@ -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]

View File

@@ -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" }

View File

@@ -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"

View File

@@ -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]

View File

@@ -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"

View File

@@ -113,7 +113,7 @@ pub fn Todos() -> impl IntoView {
);
let existing_todos = move || {
Suspend::new(async move {
Suspend(async move {
todos
.await
.map(|todos| {

View File

@@ -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]

View File

@@ -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"

View File

@@ -134,7 +134,7 @@ pub fn Todos() -> impl IntoView {
);
let existing_todos = move || {
Suspend::new(async move {
Suspend(async move {
todos
.await
.map(|todos| {

View File

@@ -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]

View File

@@ -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"

View File

@@ -134,7 +134,7 @@ pub fn Todos() -> impl IntoView {
);
let existing_todos = move || {
Suspend::new(async move {
Suspend(async move {
todos
.await
.map(|todos| {

View File

@@ -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"]]

View File

@@ -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]

View File

@@ -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> {

View File

@@ -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.

View File

@@ -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 = []

View File

@@ -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")
})?;

View File

@@ -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