Compare commits

...

827 Commits

Author SHA1 Message Date
Greg Johnston
9e83acfe63 Make cargo fmt happy 2023-01-10 21:18:03 -05:00
Greg Johnston
46254a18f3 Improve router feature warning 2023-01-10 21:10:27 -05:00
Greg Johnston
7d7a96d9bc Switch logo on color-scheme change 2023-01-10 13:51:52 -05:00
Greg Johnston
ecc24fa65d Create FUNDING.yml
Add GitHub sponsor info
2023-01-10 12:52:39 -05:00
Greg Johnston
1925c5bbe5 Merge pull request #294 from martinfrances107/workflow_cargo_fmt
Policy change ( part 2 ) Added rule of enforcing cargo fmt.
2023-01-10 09:37:38 -05:00
Greg Johnston
1613616008 Merge branch 'main' into workflow_cargo_fmt 2023-01-10 09:36:53 -05:00
Greg Johnston
8a01880ade Merge pull request #293 from benwis/remove-deps
Remove a couple extra deps from the axum integration
2023-01-10 09:36:15 -05:00
Greg Johnston
180ab87ff9 Merge pull request #282 from akesson/workspace-multi-projects
Use envs for workspace config
2023-01-10 09:35:41 -05:00
hakesson
e324fb6e76 Default site-root to '.' 2023-01-10 10:33:53 +01:00
hakesson
0547b4f846 Add missing semi-colon 2023-01-10 10:01:23 +01:00
henrik
75659ce674 Merge branch 'main' into workspace-multi-projects 2023-01-10 09:59:44 +01:00
Martin
190cb162ad Added rustfmt to setup for actions-rs/toolchain. 2023-01-10 08:52:55 +00:00
hakesson
1f556cefb0 Default to serve root 2023-01-10 09:52:21 +01:00
hakesson
6a68ef67f3 Add LEPTOS prefix to OUTPUT_NAME in all files 2023-01-10 09:26:10 +01:00
Martin
23bbd90c81 Policy change ( part 2 ) added rule of enforcing cargo fmt. 2023-01-10 08:20:02 +00:00
benwis
27b8553076 Remove a couple extra deps from the axum integration 2023-01-09 23:46:07 -08:00
hakesson
5bfeb93e3d Make Cargo.toml optional 2023-01-10 08:26:22 +01:00
hakesson
dd9ae1b7b1 Add LEPTOS prefix to OUTPUT_NAME 2023-01-10 08:25:43 +01:00
Greg Johnston
ad34a5d9c6 Update name to leptos-rs/leptos 2023-01-09 21:59:13 -05:00
Greg Johnston
ace5e7cbba Add missing hackernews_axum makefile 2023-01-09 21:59:00 -05:00
Greg Johnston
c8f0988e53 Merge pull request #292 from gbj/router-warnings
Implement `state` and `replace` correctly in `leptos_router` and clear warnings
2023-01-09 21:11:28 -05:00
Greg Johnston
64f0f8879b Implement state and replace correctly in leptos_router and clear warnings 2023-01-09 21:10:42 -05:00
Greg Johnston
b8cafeb650 Merge pull request #289 from gbj/forbid-unsafe
Forbid `unsafe` code in all packages
2023-01-09 20:45:28 -05:00
Greg Johnston
992b218ffe Merge pull request #291 from gbj/correct-axum-query-handling
Correct Axum query handling
2023-01-09 20:44:58 -05:00
Greg Johnston
5df89b0d25 Fix query parsing in Axum integration 2023-01-09 20:44:06 -05:00
Greg Johnston
c050456a47 Use a runtime warning about SVG <a/> instead of a macro warning on all ambiguous tags 2023-01-09 20:31:51 -05:00
Greg Johnston
8a8d7cbe1b Fix forbid_unsafe in a frustratingly-stupid way 2023-01-09 20:07:16 -05:00
Greg Johnston
f5f345e623 Merge pull request #286 from benwis/favicons
FAVICON!
2023-01-09 19:57:27 -05:00
Greg Johnston
4df3687463 Forbid unsafe code in all packages 2023-01-09 19:48:51 -05:00
Greg Johnston
f6622448e9 Update README.md 2023-01-09 19:38:02 -05:00
Greg Johnston
78825401c5 Merge pull request #288 from gbj/new-logo
New logo
2023-01-09 19:34:10 -05:00
Greg Johnston
f2b7ad6244 New logo 2023-01-09 19:33:44 -05:00
Greg Johnston
43f107d9bd New logo 2023-01-09 19:33:38 -05:00
Greg Johnston
a2612ca1fc Merge pull request #275 from martinfrances107/cargo_fmt
Policy change: Workflow now enforce "cargo fmt".
2023-01-09 19:20:57 -05:00
Greg Johnston
a000c84e1a Fix scope disposal code in Router (closes issue #240) 2023-01-09 19:17:37 -05:00
benwis
ee647cba1c Add Favicons to all the examples and standardize on the public folder for public assets 2023-01-09 15:27:52 -08:00
Greg Johnston
1377b823e2 Merge pull request #285 from martinfrances107/version_numbers
simple_logger use version 4.0.0 everywhere.
2023-01-09 18:26:57 -05:00
Martin
4d21f5ac63 simple_logger use version 4.0.0 everywhere. 2023-01-09 21:43:48 +00:00
hakesson
1ec603ee58 Use envs for workspace config 2023-01-09 20:06:43 +01:00
Martin
c56806713e Keeping up with changes to main. 2023-01-09 12:47:50 +00:00
Martin
2f6aa6753d Removed workflow "Cargo fmt" test. 2023-01-09 12:44:35 +00:00
Martin
2544687acd Moved the order of check. 2023-01-09 12:44:35 +00:00
Martin
3d25e86c23 Policy change: Workflow now enforce "cargo fmt". 2023-01-09 12:44:30 +00:00
Greg Johnston
28ec3a6cda Merge pull request #281 from martinfrances107/hackernews_axum
Minor: Clippy fixes related to hackernew_axum.
2023-01-09 07:02:43 -05:00
Greg Johnston
8b92a561a3 Merge pull request #269 from benwis/generated_routes
Generate Routes and pass them to Actix/Axum
2023-01-09 07:02:11 -05:00
Martin
e490c0423f Minor: Clippy fixes related to hackernew_axum. 2023-01-09 09:54:39 +00:00
benwis
b6579a040a Warning Squashing 2023-01-08 19:41:22 -08:00
benwis
01e024b726 One more time! 2023-01-08 19:38:45 -08:00
benwis
6603c44ce2 Minor fixes and revisions 2023-01-08 19:36:24 -08:00
Greg Johnston
977f11b180 Merge pull request #280 from gbj/prevent-panic-in-ssr
Closes #278: Prevent `create_signal_from_stream` from panicking on SSR
2023-01-08 19:52:48 -05:00
Greg Johnston
fb34b29ccf Merge pull request #279 from DPM97/default_prop_values
default prop values in prop macro
2023-01-08 19:52:38 -05:00
benwis
6576d8eda1 Change site_root default to ".". Hope that cargo-leptos has that check 2023-01-08 14:54:32 -08:00
benwis
6b729f9131 Fix hackernews_axum example 2023-01-08 14:51:41 -08:00
benwis
dc60c35b58 Rewrite file handlers for Axum, and update all examples to use the new
generated routes. Fix a few issues in the integrations, and reduce the
number of warnings
2023-01-08 14:18:51 -08:00
Greg Johnston
32ec9cc57e Prevent create_signal_from_stream from panicking on SSR 2023-01-08 17:09:04 -05:00
Dylan Maloy
35601d8284 update abort_opt_message 2023-01-08 16:47:02 -05:00
Dylan Maloy
49bc7d2a27 init 2023-01-08 16:35:43 -05:00
Greg Johnston
aa7c7367dc Merge pull request #277 from martinfrances107/clippy_hackernews
examples/hackernews - Cargo clippy fixes.
2023-01-08 14:10:57 -05:00
Greg Johnston
70808c5262 Merge pull request #272 from DPM97/component_lifetimes
fix component macro lifetime parsing
2023-01-08 14:07:00 -05:00
Martin
67503a108d BugFix. 2023-01-08 15:28:30 +00:00
Martin
ef52a01838 examples/hackernews - Cargo clippy fixes. 2023-01-08 13:33:53 +00:00
Greg Johnston
4cacfe98d8 Merge pull request #273 from martinfrances107/needless_borrow
Minor: Removed Clippy::needless_borrrow issues.
2023-01-08 07:27:02 -05:00
Greg Johnston
52e653316e Merge pull request #270 from gbj/chorse
Chores
2023-01-08 07:26:14 -05:00
Greg Johnston
bf5b6ca9c2 Merge pull request #264 from martinfrances107/Clipp_removed_clone_round_2
Removing clone call where possible(round2).
2023-01-08 07:26:00 -05:00
Martin
8875939a27 Minor: Removed Clippy::needless_borrrow issues. 2023-01-08 10:42:25 +00:00
Martin
b9a83277d9 Removing clone call where possible(round2). 2023-01-08 09:57:19 +00:00
benwis
dad84b5867 Merge branch 'main' into generated_routes 2023-01-07 21:17:18 -08:00
Dylan Maloy
1f29d29947 init 2023-01-08 00:15:00 -05:00
benwis
1b8175e2fa Add missing tokio dep for RwLock 2023-01-07 20:27:05 -08:00
Greg Johnston
dbe3ec015c Fix warning for unused variable. 2023-01-07 22:06:02 -05:00
Greg Johnston
492fa6c6d3 Fix link to Stream in docs. 2023-01-07 22:05:44 -05:00
Greg Johnston
343e8c8abe Update macro docs to reflect newly-available class syntax. 2023-01-07 22:02:23 -05:00
Greg Johnston
656d20cb65 Don't panic in proc macro, use proc_macro_error instead. 2023-01-07 21:32:52 -05:00
Greg Johnston
a0a66b75dd Allow complex class names with ("class-[name]-42", value) syntax. 2023-01-07 21:29:26 -05:00
Greg Johnston
085ba3506c Merge pull request #267 from gbj/adjust-tracing
Adjust tracing
2023-01-07 20:31:54 -05:00
Greg Johnston
63f3780eda Merge pull request #268 from gbj/fnonce-children
`children` should take `FnOnce(Scope) -> Fragment`, to ease need of c…
2023-01-07 20:31:29 -05:00
benwis
c41cf879d1 Formatting 2023-01-07 15:44:35 -08:00
benwis
b34f2070d3 Remove extraneous route 2023-01-07 15:09:49 -08:00
benwis
7fa21defa6 Merge remote-tracking branch 'origin/generated_routes' into generated_routes 2023-01-07 15:08:12 -08:00
benwis
bdd9abc04d Removing some missed code and changing the stylesheet 2023-01-07 15:06:21 -08:00
Ben Wishovich
1d25134213 Merge branch 'main' into generated_routes 2023-01-07 14:58:26 -08:00
benwis
de73622949 Change Axum's "" matching 2023-01-07 14:53:38 -08:00
benwis
5d3cfc6483 Actix seems to be working now, plus applied Henrik's path recommendations 2023-01-07 14:49:25 -08:00
Greg Johnston
6fbbd09000 <Suspense/> and <Transition/> should take Fn for children because they need to use it multiple times 2023-01-07 17:09:50 -05:00
Greg Johnston
f2842cf14e children should take FnOnce(Scope) -> Fragment, to ease need of cloning etc. 2023-01-07 17:04:58 -05:00
Greg Johnston
a6b6864bc5 Merge branch 'adjust-tracing' of https://github.com/gbj/leptos into adjust-tracing 2023-01-07 16:27:33 -05:00
Greg Johnston
063b946cd4 Remove unnecessary log 2023-01-07 16:27:25 -05:00
Greg Johnston
5a2c9ea345 Merge branch 'main' into adjust-tracing 2023-01-07 16:26:20 -05:00
Greg Johnston
808d87598b Tracing for events and elements. 2023-01-07 16:20:00 -05:00
Greg Johnston
0956c48b1e Merge pull request #266 from gbj/fix-meta-panic
Adjust default features for `meta` and `router`
2023-01-07 14:44:23 -05:00
Greg Johnston
8915e2615b Adjust default features for meta and router 2023-01-07 14:43:32 -05:00
Greg Johnston
7f47134058 Merge pull request #265 from martinfrances107/needless_borrowed_reference
Clippy: Minor needless_borrowed_reference.
2023-01-07 14:21:58 -05:00
Greg Johnston
af7b93fa1e Merge pull request #128 from akesson/workspace-features
Workspace features
2023-01-07 14:19:56 -05:00
Greg Johnston
ed940f577a Add tracing for event handlers 2023-01-07 13:32:40 -05:00
Martin
916f30a07b Clippy: Minor needless_borrowed_reference. 2023-01-07 18:28:42 +00:00
Greg Johnston
e01c565de1 Improve tracing formatting 2023-01-07 13:16:30 -05:00
Greg Johnston
dffe195cdc Fix two warnings 2023-01-07 13:16:20 -05:00
Greg Johnston
a5e2587555 Merge pull request #261 from martinfrances107/Clippy_removed_clone_where_possible
Clippy: Removed stray calls to .clone().
2023-01-07 12:47:06 -05:00
Greg Johnston
af8889fab2 Merge pull request #262 from martinfrances107/uninlined_format_args
Minor: Clippy format!() all variables now inlined.
2023-01-07 12:42:56 -05:00
Greg Johnston
267c1cfc34 Merge pull request #263 from martinfrances107/if_let_some
Removed clippy::single_match issue.
2023-01-07 12:40:55 -05:00
Greg Johnston
3498378e60 Merge pull request #260 from jquesada2016/into_signal_traits
added `IntoSignal` and `IntoSignalSetter` helper traits
2023-01-07 12:40:15 -05:00
hakesson
f8c680d14d Integrations with workspace dependencies 2023-01-07 18:05:35 +01:00
hakesson
b852e459a9 Unify workspace dependencies 2023-01-07 18:00:37 +01:00
hakesson
681f10ec8d Workspace-based versioning 2023-01-07 17:35:02 +01:00
Martin
1d480791a1 Removed clippy::single_match issue. 2023-01-07 16:08:17 +00:00
Martin
7acc309f66 Minor: Clippy format!() all variables now inlined. 2023-01-07 15:46:47 +00:00
Martin
9527de15ed Removed stray calls to .clone(). 2023-01-07 14:53:59 +00:00
Jose Quesada
aeb25a715a added IntoSignal and IntoSignalSetter helper traits 2023-01-07 08:20:27 -06:00
Greg Johnston
46e91a538c Merge branch 'main' of https://github.com/gbj/leptos 2023-01-07 08:32:45 -05:00
Greg Johnston
1fe526c99c Remove erroneous log 2023-01-07 08:32:39 -05:00
Greg Johnston
6b05918807 Merge pull request #257 from gbj/ci-disk-space
Improve CI disk space usage
2023-01-07 07:44:10 -05:00
Greg Johnston
05d2eb8ce0 Improve CI disk space usage 2023-01-07 07:43:52 -05:00
Greg Johnston
e12c2d9769 Merge pull request #252 from gbj/additional-meta-tags
Additional meta tags — closes issue #158
2023-01-07 07:37:02 -05:00
Greg Johnston
825245b65f Merge pull request #256 from gbj/router-tests
Fix router tests when no features enabled
2023-01-07 07:36:51 -05:00
Greg Johnston
ef067f18e1 Fix router tests when no features enabled 2023-01-07 07:36:27 -05:00
Greg Johnston
844dc21efd Merge pull request #255 from martinfrances107/#253_cargo_doc_warnings_rename_EachKey_to_Each
#254 Minor: In docs, Rename EachKey to Each.
2023-01-07 07:25:34 -05:00
Greg Johnston
1a00e99a24 Merge pull request #254 from martinfrances107/#253_unbalanced_tags
#254 Minor: Unbalanced tags.
2023-01-07 07:25:03 -05:00
Martin
6c5bcf30ba #254 Minor: In docs, Rename EachKey to Each. 2023-01-07 11:51:52 +00:00
Martin
be8ffe935d #254 Minor: Unbalanced tags. 2023-01-07 11:22:36 +00:00
Greg Johnston
0b80bba4ec Fix tests 2023-01-06 23:04:25 -05:00
Greg Johnston
9cc38988d8 Corrects style docs 2023-01-06 22:56:23 -05:00
Greg Johnston
0d92a5dec8 Add <Script/> and <Style/> components 2023-01-06 22:54:35 -05:00
benwis
677e4f2540 Leptos can now generate routes and provide them to the Axum router. More
testing and Actix version to come
2023-01-06 19:52:38 -08:00
Greg Johnston
0029e1d8f7 Merge pull request #251 from martinfrances107/bump_actions_checkout
Bump actions/checkout to version@3
2023-01-06 17:47:21 -05:00
Greg Johnston
635aa5c681 Merge pull request #250 from jquesada2016/on_mount
added `HtmlElement::on_mount`
2023-01-06 17:46:29 -05:00
Martin
f5c4c9448c Bump actions/checkout to version@3 2023-01-06 22:31:13 +00:00
benwis
63b1837315 First pass of method to generate routelist 2023-01-06 14:08:45 -08:00
Greg Johnston
bc43a9d329 Use builder syntax and refactor tag registration 2023-01-06 16:49:26 -05:00
Greg Johnston
1850c28d3a Add <Link/> and refactor <Stylesheet/> to use it 2023-01-06 16:06:03 -05:00
Greg Johnston
319a058e63 Fix relative route for stylesheet in hackernews 2023-01-06 16:06:03 -05:00
Greg Johnston
678e49268f Merge pull request #248 from gbj/tracing
Adding `tracing` to `leptos_reactive`
2023-01-06 15:18:54 -05:00
Jose Quesada
6df4a6f120 fixed broken compilation within on_mount 2023-01-06 14:17:35 -06:00
Jose Quesada
73c6bbb225 updated to use the equest animation frame method in helpers.rs 2023-01-06 14:02:49 -06:00
Jose Quesada
fa57085946 added HtmlElement::on_mount 2023-01-06 12:24:24 -06:00
Greg Johnston
aef589cd24 Merge pull request #249 from gbj/router-tests
Add all the missing `router` tests
2023-01-06 12:49:44 -05:00
Greg Johnston
05ffd8c989 Add all the missing router tests 2023-01-06 12:48:45 -05:00
Greg Johnston
1125a5f7cb Additional tracing 2023-01-06 12:30:19 -05:00
Greg Johnston
dfba1d9656 Memos 2023-01-06 11:38:03 -05:00
Greg Johnston
96418ed684 Start work on instrumenting leptos_reactive 2023-01-06 11:38:03 -05:00
Greg Johnston
b010233bb4 Merge pull request #242 from jquesada2016/signal_default
impl `Default` for `SignalSetter<T>`
2023-01-06 10:31:29 -05:00
Greg Johnston
7e28f56f01 Merge pull request #247 from gbj/fix-integration-event-name
Correct `leptos_autoreload` event variable name
2023-01-06 09:50:45 -05:00
Greg Johnston
dd35c31db1 Correct leptos_autoreload event variable name 2023-01-06 09:50:29 -05:00
Jose Quesada
c9ac4ed2b5 added Signal::default method 2023-01-06 08:34:15 -06:00
Jose Quesada
7631ce3b09 Revert "added DefaultSignal"
This reverts commit a5988c59ee.
2023-01-06 08:26:10 -06:00
Jose Quesada
a5988c59ee added DefaultSignal 2023-01-05 17:06:06 -06:00
Jose Quesada
9ba807f79b impl Default for SignalSetter<T> 2023-01-05 15:47:31 -06:00
Greg Johnston
9d8627b337 Merge branch 'main' of https://github.com/gbj/leptos 2023-01-05 11:08:11 -05:00
Greg Johnston
64bf01c59e Reduce CI load with skipped feature sets 2023-01-05 11:08:07 -05:00
Greg Johnston
ed023c8970 Merge pull request #239 from gbj/router-off-by-one
Fixes off-by-one error in the router that was causing inappropriate scope disposal
2023-01-05 09:47:39 -05:00
Greg Johnston
13bdef22bd Fixes off-by-one error in the router that was causing inappropriate scope disposal 2023-01-05 09:47:03 -05:00
Greg Johnston
6f49a6c12a Merge pull request #237 from gbj/additional-meta-tags
Better `leptos_meta` component unloading
2023-01-05 08:20:13 -05:00
Greg Johnston
7db292779b Correct on_cleanup import 2023-01-04 22:41:46 -05:00
Greg Johnston
e2496e01d0 Correctly hydrate stylesheets, and correctly clean up stylesheets and metadata 2023-01-04 22:39:54 -05:00
Greg Johnston
d5bda04306 <Outlet/> should dispose of child scopes if it needs to 2023-01-04 22:39:32 -05:00
Greg Johnston
9165242744 Merge pull request #236 from gbj/fix-outlet-hydration-mismatch
Fix `<Outlet/>` hydration mismatch
2023-01-04 22:09:00 -05:00
Greg Johnston
927fe0949f Merge pull request #235 from gbj/effect-cleanup
Signals were not properly registering themselves as sources for their…
2023-01-04 16:57:29 -05:00
Greg Johnston
459216a30e Fix <Outlet/> hydration mismatch 2023-01-04 16:56:47 -05:00
Greg Johnston
c7fa041469 Working on disposing metadata tags 2023-01-04 16:56:04 -05:00
Greg Johnston
cab7360bef Fix hydration mismatch in <Outlet/> 2023-01-04 15:32:39 -05:00
Greg Johnston
159ec4a7bd Signals were not properly registering themselves as sources for their effects, which meant effects were possibly over-running. 2023-01-04 11:29:08 -05:00
Greg Johnston
ae40f3134a Merge pull request #233 from kdwarn/main
Fix links/names to a couple examples
2023-01-04 11:11:04 -05:00
Greg Johnston
3c080e0564 Merge pull request #232 from gbj/custom-events-in-macro
`leptos_macro` improvements to `class:`, `prop:`, `on:`, `:undelegate…
2023-01-04 11:10:19 -05:00
Greg Johnston
e8c1bf5055 #[prop] docs 2023-01-04 11:10:03 -05:00
Greg Johnston
2a4a5f75c9 Remove unused doc_comment crate 2023-01-04 10:42:25 -05:00
Greg Johnston
91b65654d6 Fix typed event docs 2023-01-04 10:40:35 -05:00
Kris Warner
dcca6e4e17 Fix name/link for parent_child 2023-01-04 10:25:41 -05:00
Kris Warner
4550545e4f Fix link/name of counters_stable 2023-01-04 10:18:38 -05:00
Greg Johnston
af1a4492e8 leptos_macro improvements to class:, prop:, on:, :undelegated, and events 2023-01-04 00:25:53 -05:00
Greg Johnston
6b1b4463a0 Fix server docs 2023-01-03 23:22:06 -05:00
Greg Johnston
632267c13a Merge pull request #231 from gbj/router-changes
Close issue #229 and update router docs
2023-01-03 21:51:22 -05:00
Greg Johnston
a349707e1f Merge pull request #230 from gbj/server-docs-and-debug
Improve docs and debugging tools for server functions (closes #225)
2023-01-03 21:51:10 -05:00
Greg Johnston
84fa6cd3a8 Merge pull request #228 from benwis/responseoptions_helpers
Add a redirect() function and some helpful utility functions for ResponseParts and ResponseOptions
2023-01-03 21:51:00 -05:00
Ben Wishovich
05468d3307 You WILL change your doc comments 2023-01-03 17:33:22 -08:00
Greg Johnston
0da88f39cd Improve docs and debugging tools for server functions (closes #225) 2023-01-03 20:05:47 -05:00
Greg Johnston
5dffb0a803 Document how to modularize/externalize route definitions 2023-01-03 19:38:11 -05:00
Greg Johnston
e2a5c2d78f Fix issues with route matching on different sub-routes with same path (closes issue #229) 2023-01-03 19:32:58 -05:00
Greg Johnston
ca679ec496 chore: clear warning 2023-01-03 19:06:59 -05:00
Greg Johnston
10282857fe chore: clear warnings 2023-01-03 18:47:21 -05:00
Greg Johnston
263d5b1d89 Allow path prop on <Route/> to be any type that impl std::fmt::Display 2023-01-03 18:37:43 -05:00
Greg Johnston
6a4cbbf266 Specify html::a to suppress warning 2023-01-03 16:07:51 -05:00
Greg Johnston
8d14972808 Merge branch 'main' of https://github.com/gbj/leptos 2023-01-03 15:52:33 -05:00
Greg Johnston
441eb1697e Reduce CI load by omitting tracing feature from CI testing 2023-01-03 15:52:29 -05:00
Ben Wishovich
64e6eedb4d Add a redirect() function and some helpful utility functions for ResponseParts and ResponseOptions 2023-01-03 10:35:30 -08:00
Greg Johnston
78d965cc91 Merge pull request #220 from jquesada2016/view_on_undelegated
added on:eventname:undelegated support
2023-01-03 13:07:22 -05:00
Jose Quesada
28dce925b0 relaxed parse_event to be undelegated only when :undelegated appears at the end of the event 2023-01-03 08:54:52 -06:00
Greg Johnston
a2943c4649 Fix counters_isomorphic 2023-01-02 18:37:10 -05:00
Greg Johnston
d4b5b958f3 0.1.0-beta 2023-01-02 16:52:18 -05:00
Greg Johnston
9537cafe25 Add version for publishing 2023-01-02 16:49:45 -05:00
Greg Johnston
95dd252c14 Disable for publish 2023-01-02 16:41:08 -05:00
Greg Johnston
755ceb7d75 0.1.0-beta 2023-01-02 16:35:00 -05:00
Greg Johnston
d5b74dacc8 Merge pull request #223 from gbj/build-examples-ci
Add CI back to build examples
2023-01-02 16:34:29 -05:00
Greg Johnston
411fc51ea2 Clean up examples 2023-01-02 16:20:05 -05:00
Greg Johnston
e714cac0ec Add missing makefiles 2023-01-02 16:19:52 -05:00
Greg Johnston
ab0b687943 Merge pull request #222 from gbj/build-examples-ci
Add `build-examples` task to `cargo make` CI
2023-01-02 13:35:45 -05:00
Greg Johnston
7f21ee97a8 Fix counter_isomorphic import 2023-01-02 13:34:56 -05:00
Greg Johnston
0ed56d382d Add build-examples task to cargo make CI 2023-01-02 13:29:37 -05:00
Greg Johnston
a47cac6e3c Merge pull request #221 from gbj/fixing-stable
Finalizing `stable` support
2023-01-02 13:24:27 -05:00
Greg Johnston
edbd3612b3 stable for leptos_macro 2023-01-02 13:04:56 -05:00
Greg Johnston
e2517c99b8 Backtrace not supported on stable 2023-01-02 12:55:26 -05:00
Greg Johnston
2b01bf99b4 enum Default not supported on stable 2023-01-02 12:55:16 -05:00
Greg Johnston
bd5bd71a21 chore: clear warning 2023-01-02 12:55:04 -05:00
Greg Johnston
60187961a0 Merge pull request #219 from jquesada2016/leptos_dom_stable
Stable support for `leptos_dom`
2023-01-02 12:09:48 -05:00
Jose Quesada
1344f113c5 added on:eventname:undelegated support 2023-01-02 10:36:08 -06:00
Greg Johnston
96bbb86346 Merge pull request #218 from gbj/stylesheet-hydration
Correct hydration behavior of `<Stylesheet id=.../>` (necessary for `…
2023-01-02 10:23:35 -05:00
Jose Quesada
7478315970 forgot to commit new dependencies 2023-01-02 09:01:57 -06:00
Jose Quesada
b894444b8d removed drain_filter feature flag 2023-01-02 08:28:05 -06:00
Jose Quesada
9f8bcd6fb1 removed iter_intersperse feature flag` 2023-01-02 08:20:45 -06:00
Jose Quesada
d82781abbd removed thread_local feature flag 2023-01-02 08:18:19 -06:00
Jose Quesada
f8c4cac6d3 removed once_cell feature flag 2023-01-02 07:52:30 -06:00
Greg Johnston
4264b15aab Correct hydration behavior of <Stylesheet id=.../> (necessary for cargo-leptos CSS reloading) 2023-01-01 22:56:17 -05:00
Greg Johnston
168f9d3a45 Merge pull request #217 from gbj/action-docs-ci
Fix `Action` and `create_action` docs to match new API
2023-01-01 21:36:15 -05:00
Greg Johnston
9663555195 Fix Action and create_action docs to match new API 2023-01-01 19:44:50 -05:00
Greg Johnston
e92176029c Merge pull request #216 from gbj/context-warning
Revert confusingly-aggressive shadowed-context warning
2023-01-01 17:40:54 -05:00
Greg Johnston
fe820c48c8 Revert confusingly-aggressive shadowed-context warning 2023-01-01 17:40:39 -05:00
Greg Johnston
87cd4b8f00 Merge pull request #214 from gbj/fix-tailwind-example
Small fixes to Tailwind example
2023-01-01 08:09:36 -05:00
Greg Johnston
3a5e3aea99 Small fixes to Tailwind example 2023-01-01 08:09:24 -05:00
Greg Johnston
9ba06cd604 Merge pull request #213 from gbj/fix-hydration-mismatch
Closes #212
2023-01-01 08:04:10 -05:00
Greg Johnston
e8eb55ca5c Make sure tag names are uppercased in debug assertions where they're uppercased 2023-01-01 08:03:26 -05:00
Greg Johnston
7946df8bfc Merge pull request #209 from benwis/cargo-leptos-release-testing
Update all examples to use cargo-leptos and patch integrations for latest cargo-leptos support
2023-01-01 07:56:41 -05:00
Ben Wishovich
827b787c91 Bugfixes, using cargo-leptos for CSS, and updating READMEs. 2022-12-31 18:39:05 -08:00
Greg Johnston
795270447b Merge pull request #208 from jquesada2016/207
fixes compiler recursion limit on `View::on`
2022-12-31 19:15:28 -05:00
Ben Wishovich
01c00eee6b Update SSR Readmes with new instructions 2022-12-31 16:06:54 -08:00
Ben Wishovich
f45d33db73 Move the examples out of the workspace, and standardize naming. All of the SSR examples now work with cargo-leptos 2022-12-31 15:52:19 -08:00
Jose Quesada
60e2f34456 changed View::on to not require manually boxing the closure 2022-12-31 09:59:48 -06:00
Jose Quesada
7ec82c8df3 boxing View::on closure to fix compiler recursion error 2022-12-31 09:54:13 -06:00
Greg Johnston
d5f8d3a9b7 Merge pull request #206 from jquesada2016/199
fixed components only rendering `<() />` on release
2022-12-31 09:22:09 -05:00
Jose Quesada
2a1b531bd2 fixed components only rendering <() /> on release 2022-12-31 08:08:14 -06:00
Greg Johnston
f5c476cfd5 Merge pull request #205 from gbj/meta-context-warning
Fix warning about MetaContext so it's less misleading.
2022-12-30 20:04:46 -05:00
Greg Johnston
26b28be436 Fix warning about MetaContext so it's less misleading. 2022-12-30 19:30:35 -05:00
Ben Wishovich
60f0bf23fd Merge branch 'main' into cargo-leptos-release-testing 2022-12-30 16:17:50 -08:00
Ben Wishovich
442dc1e041 More changes to the examples 2022-12-30 16:17:17 -08:00
Greg Johnston
c438b46eb1 Merge pull request #200 from gbj/duplicating-text-fix
Fixing duplicating-text-node issue in `DynChild`
2022-12-30 19:11:43 -05:00
Greg Johnston
2a399f05ac Merge pull request #202 from Gentle/detect_tag_type
ambiguous tags inherit the type of their parent (svg/mathml/html)
2022-12-30 19:11:25 -05:00
Greg Johnston
6e1bc42879 Merge pull request #204 from gbj/debug-shadowed-context
Give warning when shadowing a context in debug mode
2022-12-30 19:11:02 -05:00
Greg Johnston
7ad94cc520 Merge pull request #203 from gbj/stored-value
`store_value`
2022-12-30 19:10:25 -05:00
Ramon Klass
c3a7ef0357 ambiguous tags inherit the type of their parent 2022-12-30 23:38:51 +01:00
Greg Johnston
8ee521787e Give warning when shadowing a context in debug mode 2022-12-30 17:11:34 -05:00
Greg Johnston
04c85d6eb0 Fix Axum example 2022-12-30 16:55:50 -05:00
Greg Johnston
71d278927b Update examples to new action APIs 2022-12-30 15:44:25 -05:00
Greg Johnston
cc1d15989e Update router to new action APIs 2022-12-30 15:36:01 -05:00
Greg Johnston
2c614722f4 Make Action and MultiAction Copy by backing them with a StoredValue 2022-12-30 15:29:35 -05:00
Greg Johnston
98d151f5fb Make Signal and SignalSetter Copy by backing them with StoredValue when needed 2022-12-30 15:10:37 -05:00
Greg Johnston
5a9a681d8a Create store_value and StoredValue, allowing you to stash things inside the reactive system in exchange for a Copy + 'static wrapper. 2022-12-30 15:10:28 -05:00
Ben Wishovich
8eaa0b0c15 Merge branch 'main' into cargo-leptos-release-testing 2022-12-30 11:04:43 -08:00
Ben Wishovich
c3fbf13ef3 No leading slashes, and a working todo-app-sqlite example. Improved config section detection 2022-12-30 11:01:01 -08:00
Greg Johnston
54f666c957 Merge pull request #201 from gbj/custom-events-dont-bubble
Fixes issue #178
2022-12-30 12:20:48 -05:00
Greg Johnston
b318449ee7 Issue #178 2022-12-30 11:41:21 -05:00
Greg Johnston
59c291a1e5 Could it be this simple? 2022-12-30 10:47:01 -05:00
Greg Johnston
6c7b20ce77 Merge pull request #197 from luckynumberke7in/patch-2
Fix a few typos in README.md
2022-12-30 08:19:10 -05:00
Ke7in
9a00f7f492 Fix a few typos in README.md
Minor, but I noticed 1 while reading the file and decided to skim the rest of the file.
2022-12-29 23:23:43 -05:00
Greg Johnston
26e90d1959 Merge pull request #196 from gbj/cleanup
Clean up issues relating to `0.1.0` merge
2022-12-29 20:44:31 -05:00
Ben Wishovich
1f1d675d17 Basic cargo-leptos test 2022-12-29 16:42:05 -08:00
Greg Johnston
9bde885b9d Fix suspense in story page 2022-12-29 19:28:10 -05:00
Greg Johnston
383f8a409d Add <Suspense/> to story and user pages 2022-12-29 19:17:35 -05:00
Greg Johnston
b98bacdcab Remove logs 2022-12-29 18:51:39 -05:00
Greg Johnston
d3d71875da FIXME DynChild issue 2022-12-29 18:48:21 -05:00
Greg Johnston
e06946e5a4 stable support for router 2022-12-29 18:40:50 -05:00
Greg Johnston
c485a391ee Update README.md 2022-12-29 18:25:45 -05:00
Greg Johnston
cc48ff72ad Prep for stable support 2022-12-29 18:21:24 -05:00
Greg Johnston
b2cf953c07 Example fix 2022-12-29 18:21:18 -05:00
Greg Johnston
f8af065c0e Adjustments to README 2022-12-29 18:21:08 -05:00
Greg Johnston
333f60cfb7 Changes for stable in router and meta 2022-12-29 18:10:14 -05:00
Greg Johnston
cd9fe66fbb Debug bound 2022-12-29 18:01:47 -05:00
Greg Johnston
3bb9e93c69 Debug bounds 2022-12-29 18:01:01 -05:00
Greg Johnston
f9474def96 Relaxed Debug bounds 2022-12-29 17:43:17 -05:00
Greg Johnston
d7dba85f2d Missing changes re: docs 2022-12-29 17:43:06 -05:00
Greg Johnston
94af8f26ca Fix site-root 2022-12-29 17:39:08 -05:00
Greg Johnston
19dabb6b6a Clear up warnings in the example 2022-12-29 17:39:04 -05:00
Greg Johnston
15b5f7545a Use <Transition/> here for that silky-smooth optimistic UI update 2022-12-29 17:35:46 -05:00
Greg Johnston
9399fc7b4f Removed old/broken fix for hydration under <Suspense/> 2022-12-29 17:30:33 -05:00
Greg Johnston
5d8d5d9910 SocketAddr? I hardly know her! (missing import from merge) 2022-12-29 16:01:37 -05:00
Greg Johnston
e6a1255140 Merge pull request #119 from jquesada2016/leptos_dom_v2
leptos_dom v2
2022-12-29 12:21:13 -05:00
Greg Johnston
528a9d7a6f Fix merge 2022-12-29 12:13:52 -05:00
Greg Johnston
f28da0770f Fix leptos_config version 2022-12-29 12:13:45 -05:00
Jose Quesada
0145b01da5 impl IntoView for &View 2022-12-29 09:55:35 -06:00
Greg Johnston
725ea8a01e Merge branch 'jquesada2016-leptos_dom_v2' 2022-12-29 09:32:35 -05:00
Greg Johnston
70f6297277 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into jquesada2016-leptos_dom_v2 2022-12-29 09:32:12 -05:00
Greg Johnston
e595d35c8b Fix CSS location for hackernews-axum 2022-12-29 08:50:43 -05:00
Greg Johnston
c44693e0a4 Use #[component] macro for leptos_meta to generate docs 2022-12-29 08:46:41 -05:00
Greg Johnston
b86e7f33dc Bump versions for new cargo-leptos compatible integrations 2022-12-29 08:04:22 -05:00
Greg Johnston
a603531409 Typos 2022-12-29 08:02:56 -05:00
Greg Johnston
f47fad3ed5 Merge pull request #177 from benwis/cargo-leptos-beta
Changes to leptos, leptos_meta, leptos_actix/leptos_axum, and leptos_config to support cargo-leptos-beta
2022-12-29 07:48:38 -05:00
Greg Johnston
1cb03914ab Merge pull request #185 from snapbug/stable-build-fix
Fix build errors in `counter-isomorphic` when using `stable`
2022-12-29 07:44:56 -05:00
Jose Quesada
67c5eda099 removed clone bount on the type argument of SignalSetter 2022-12-28 21:14:10 -06:00
Jose Quesada
63e70db736 removed EventHandler trait 2022-12-28 17:49:10 -06:00
Jose Quesada
8acbc579e0 fixed broken undelegated type 2022-12-28 15:38:13 -06:00
Jose Quesada
28bb3f81aa made ev::undelegated lowercase to match the rest of the event names 2022-12-28 15:28:59 -06:00
Greg Johnston
e8424138ce Fix TOML 2022-12-28 15:06:52 -05:00
Greg Johnston
4b1fce4c9c Revert "Merge branch 'main' into pr/119"
This reverts commit 63f680f37d, reversing
changes made to 50ba796f49.
2022-12-28 15:06:46 -05:00
Greg Johnston
fd2a2bd5f4 Fixing merge issues 2022-12-28 14:51:01 -05:00
Greg Johnston
f09ded454d Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into pr/119 2022-12-28 14:48:03 -05:00
Greg Johnston
a2f85feb57 Update Readme 2022-12-28 14:41:19 -05:00
Greg Johnston
d64ca366fc Fix merge 2022-12-28 14:22:03 -05:00
Greg Johnston
63f680f37d Merge branch 'main' into pr/119 2022-12-28 14:21:54 -05:00
Greg Johnston
50ba796f49 Fix leptos_server tests 2022-12-28 13:26:10 -05:00
Jose Quesada
f3b62bcf88 impl HtmlElement::inner_html for SSR 2022-12-28 11:34:27 -06:00
Jose Quesada
57c72c038c impl HtmlElement::inner_html for web targets, SSR still TODO 2022-12-28 11:17:47 -06:00
Jose Quesada
4340fbfc78 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-28 10:52:06 -06:00
Jose Quesada
4e1753fc71 moved #[component] tracing support behind a tracing feature flag 2022-12-28 10:51:55 -06:00
Greg Johnston
f30310a64a Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-28 11:33:29 -05:00
Greg Johnston
e3c4e9f6a4 chores: fix failing tests, update docs, suppress warnings 2022-12-28 11:33:26 -05:00
Jose Quesada
494deef9b6 maybe possibly perhaps fixed broken tracing dep 2022-12-28 09:53:11 -06:00
Jose Quesada
0da8d0113c added clone: to components in view! macro to help with move dilemmaa 2022-12-28 09:24:52 -06:00
Greg Johnston
dac69b9802 Port hackernews-axum 2022-12-28 08:53:05 -05:00
Jose Quesada
3c1e1e12d2 component move fix would break scope continuity 2022-12-28 07:44:41 -06:00
Jose Quesada
0e179d0cb5 component move fix would break scope continuity
This reverts commit 4dd5768a66.
2022-12-28 07:36:05 -06:00
Greg Johnston
55b27f7aec Fix <Meta/> tag hydration lookup 2022-12-28 08:19:56 -05:00
Jose Quesada
4467d060b6 fixed duplicate imports on web 2022-12-27 20:18:46 -06:00
Jose Quesada
4dd5768a66 fixed move dilema on component children 2022-12-27 20:14:10 -06:00
Jose Quesada
a3f090c4df added LazyView to fix view! macro move dilema 2022-12-27 20:12:59 -06:00
Ben Wishovich
5729655657 Merge remote-tracking branch 'origin/cargo-leptos-beta' into cargo-leptos-beta 2022-12-27 13:02:13 -08:00
Ben Wishovich
f2ed521de8 Missing .is_ok() and more examples changes 2022-12-27 13:01:40 -08:00
Ben Wishovich
f8f0d9fae0 Merge branch 'main' into cargo-leptos-beta 2022-12-27 12:49:17 -08:00
Ben Wishovich
e23c05a1df Remove unused derives 2022-12-27 11:01:20 -08:00
Ben Wishovich
be94c1b846 Update examples to camelcase and add missing fields for feature flags. Should be working with cargo-leptos beta again 2022-12-27 10:58:05 -08:00
Jose Quesada
b3c4c77dee now unwrapping type when documenting a field which has #[prop(strip_option)] 2022-12-27 12:20:14 -06:00
Jose Quesada
8b81425b21 explicit handler type to help compiler type inference 2022-12-27 08:46:09 -06:00
Jose Quesada
04e3e7a9a6 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-27 08:33:22 -06:00
Jose Quesada
ab2d554dc3 now only adding event handlers Some(_) and FnMut; called cargo fmt which is why more files were edited 2022-12-27 08:33:09 -06:00
Greg Johnston
c712cc8937 chore: clippy 2022-12-26 17:49:32 -05:00
Greg Johnston
6077966cd7 Streaming SSR for <Suspense/> in release mode 2022-12-26 17:47:26 -05:00
Greg Johnston
3179b2a9e5 Remove duplicate 2022-12-26 17:25:18 -05:00
Greg Johnston
a68d276c90 Merge pull request #188 from tshepang/patch-1
readme: fix indentation of code block
2022-12-26 17:16:03 -05:00
Greg Johnston
bf3bba3794 Merge pull request #176 from ultrasaurus/nightly-readme
info about how to set up nightly -> README
2022-12-26 17:15:30 -05:00
Sarah Allen
17eb571ef3 remove --allow-downgrade option since not required 2022-12-26 11:00:27 -08:00
Greg Johnston
ebd7080149 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-26 11:38:27 -05:00
Greg Johnston
f1a148caf8 Remove errant Clone bound on Signal<T> by implementing explicitly 2022-12-26 11:38:25 -05:00
Jose Quesada
a5351dd33d fixed broken cfg 2022-12-26 09:51:36 -06:00
Jose Quesada
a15b3dd882 now using a shared marker to check if a Each has already been mounted, rather than calling out to JS 2022-12-26 09:42:37 -06:00
Jose Quesada
d42b79b261 now using a shared marker to check if a component has already been mounted, rather than calling out to JS 2022-12-26 09:37:32 -06:00
Jose Quesada
6cd136ec9b Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-26 08:59:11 -06:00
Jose Quesada
85b72f5b68 added support for moving views around in the DOM 2022-12-26 08:58:58 -06:00
Greg Johnston
2bd0c38304 Properly detect and namespace SVG/MathML 2022-12-26 08:21:36 -05:00
Greg Johnston
9dc30da3e9 Fix component children example in docs 2022-12-26 08:03:40 -05:00
Tshepang Mbambo
3436cf7fbf readme: fix indentation of code block 2022-12-26 06:29:12 +02:00
Greg Johnston
38ef93d862 Fix deps 2022-12-25 23:14:10 -05:00
Greg Johnston
0e437cac68 Update README 2022-12-25 23:13:27 -05:00
Greg Johnston
98e3f5a155 Remove dev-deps for publish 2022-12-25 23:11:08 -05:00
Greg Johnston
a55ce8f752 Fix deps 2022-12-25 23:08:00 -05:00
Greg Johnston
469a65ad7a Remove dev-deps for publish 2022-12-25 23:07:42 -05:00
Greg Johnston
8a8c00455e Remove version of dev-deps 2022-12-25 23:06:20 -05:00
Greg Johnston
2048e89109 Remove dev-dependency (for cargo publish reasons) 2022-12-25 23:03:43 -05:00
Greg Johnston
5540bb8e8c Bump version to 0.1.0-alpha 2022-12-25 22:58:07 -05:00
Greg Johnston
86df770dad chores: getting tests fixed, etc. 2022-12-25 22:53:52 -05:00
Greg Johnston
535bd69b2a Merge pull request #186 from luckynumberke7in/patch-1
Update COMMON_BUGS.md to fix typo
2022-12-25 20:48:40 -05:00
Ke7in
1b0200390b Update COMMON_BUGS.md to fix typo
```rust
let (b, set_a) = create_signal(cx, false); // should be set_b
```
2022-12-25 18:27:52 -05:00
Greg Johnston
e05778726b Update docs 2022-12-25 16:06:29 -05:00
Matt Crane
587a85baaf Fix erros in counter-isomorphic with stable 2022-12-24 12:13:35 -08:00
Ben Wishovich
ff0d058a3e leptos_watch is not a bool 2022-12-24 10:30:29 -08:00
Jose Quesada
623bb7cb3f Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-24 08:45:43 -06:00
Jose Quesada
fc062e6829 fixed the type of math elements 2022-12-24 08:45:36 -06:00
Greg Johnston
479c11e3f8 MUCH better solution to hydration mismatch when resources read not under Suspense 2022-12-24 08:24:56 -05:00
Greg Johnston
bf9587c349 Attempt at Transition 2022-12-24 07:39:43 -05:00
Greg Johnston
b3da8a5dba Fix SVG warning fix 2022-12-24 07:39:25 -05:00
Greg Johnston
d3f2cae07a Fix SVG warnings 2022-12-24 07:28:34 -05:00
Greg Johnston
8c4dcbeddc Fix paths for imports 2022-12-23 17:05:52 -05:00
Greg Johnston
a4747596fa Only stream Resources if they're under a Suspense to fix rendering issue 2022-12-23 17:01:22 -05:00
Greg Johnston
af68da0a9a Remove web by default 2022-12-23 17:01:06 -05:00
Greg Johnston
48e1d6cfab Recursive components allowed 2022-12-23 17:00:52 -05:00
Greg Johnston
a4740d6c06 Remove web by default 2022-12-23 17:00:42 -05:00
Jose Quesada
ae506fced6 fixed name mismatch 2022-12-23 14:51:27 -06:00
Jose Quesada
86394105dd fixed name collision within components so that recursion is possible 2022-12-23 14:47:57 -06:00
Jose Quesada
7028dd8b3d fixed math namespace 2022-12-23 14:34:35 -06:00
Jose Quesada
8092bf1962 untoggled wasm32 target 2022-12-23 14:22:16 -06:00
Jose Quesada
2d97790ab9 fixed imports on non-web 2022-12-23 14:17:54 -06:00
Jose Quesada
ef846e7b88 added all math elements 2022-12-23 14:09:46 -06:00
Jose Quesada
d78ee8c3c9 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-23 14:07:01 -06:00
Jose Quesada
d1ece97575 added all svg elements 2022-12-23 14:06:55 -06:00
Greg Johnston
c24958bec4 Fix paths in hackernews example 2022-12-23 14:35:02 -05:00
Greg Johnston
8e1c165427 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-23 14:32:26 -05:00
Greg Johnston
50c9c38b7d Fix JS path 2022-12-23 14:24:59 -05:00
Greg Johnston
232776f9a6 Add example to Cargo.toml 2022-12-23 14:23:52 -05:00
Greg Johnston
629ac01484 merge todo-app-sqlite-axum 2022-12-23 14:23:38 -05:00
Greg Johnston
f20c74fa98 SSR changes to support integrations 2022-12-23 14:23:06 -05:00
Greg Johnston
2499755a9e Merge main integrations in 2022-12-23 14:22:49 -05:00
Greg Johnston
f17f651986 Clean up example 2022-12-23 13:30:22 -05:00
Greg Johnston
c1d6ff51a6 Update meta and router versions 2022-12-23 13:19:51 -05:00
Greg Johnston
4839bfbb29 Tailwind example ported 2022-12-23 13:10:45 -05:00
Greg Johnston
391fe89542 0.0.21 2022-12-23 13:01:15 -05:00
Greg Johnston
f54ffab888 Update integration versions 2022-12-23 12:43:18 -05:00
Jose Quesada
7ee0c01594 fixed non-web builds 2022-12-23 11:19:39 -06:00
Jose Quesada
6ce90fa49d revert default build target 2022-12-23 11:16:28 -06:00
Jose Quesada
c96965ab64 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-23 11:10:01 -06:00
Jose Quesada
5def2a72bc impl View::on and renamed IntoElement to ElementDescriptor 2022-12-23 11:09:55 -06:00
Greg Johnston
a648f084c6 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-23 11:40:59 -05:00
Greg Johnston
590ec40e0c Final Suspense fix? 2022-12-23 11:40:57 -05:00
Greg Johnston
6354b79588 Use Transition in example 2022-12-23 11:34:20 -05:00
Greg Johnston
d95dc1858c Fix merged leptos_reactive so that resources are streamed properly 2022-12-23 11:33:17 -05:00
Greg Johnston
558b13dc0e Fix merged leptos_reactive so that resources are streamed properly 2022-12-23 11:33:05 -05:00
Greg Johnston
43bbd2f33e Merge branch 'main' of https://github.com/gbj/leptos 2022-12-23 10:25:51 -05:00
Greg Johnston
833eee6639 Create shared_context by default in SSR 2022-12-23 10:25:48 -05:00
Greg Johnston
feb7961bd0 Created shared_context by default in SSR 2022-12-23 10:24:44 -05:00
Greg Johnston
8aa05f8f3d Merge pull request #181 from gbj/relax-debug-trait-bounds
Relax the `Debug` trait bounds on various types in `leptos_reactive`
2022-12-23 10:05:49 -05:00
Jose Quesada
fa87bc6f19 added transparent to `<For /> 2022-12-23 08:39:06 -06:00
Greg Johnston
0f31e924a6 Transparent <For/> 2022-12-23 09:34:47 -05:00
Jose Quesada
c89930aed0 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-23 08:19:15 -06:00
Greg Johnston
3d160ed152 Merge in changes to leptos_reactive from main 2022-12-23 09:19:04 -05:00
Jose Quesada
8037915294 reintroduced panic in DynChild 2022-12-23 08:19:02 -06:00
Greg Johnston
b62568b8a4 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-23 08:59:23 -05:00
Jose Quesada
a5d7563a67 fixed DynChild panicking when expected text is not there 2022-12-23 07:54:29 -06:00
Ben Wishovich
fbacfc787c Add missing port to Websockets code 2022-12-22 20:56:47 -08:00
Greg Johnston
0bf52c95bb Make sure --debug is noted in examples so hydration matches 2022-12-22 21:24:36 -05:00
Greg Johnston
89aa02af19 Update counter example 2022-12-22 21:21:17 -05:00
Greg Johnston
21af940c61 Merge pull request #175 from ultrasaurus/counter-example
fix warning, set initial value of counter
2022-12-22 21:08:49 -05:00
Greg Johnston
46c939ba28 Relax all the Debug trait bounds on various types in leptos_reactive 2022-12-22 21:07:38 -05:00
Greg Johnston
d158c34d24 Transition back to Transition in hackernews 2022-12-22 20:55:38 -05:00
Greg Johnston
42eef284e6 Fix Transition in new hydration model 2022-12-22 20:55:17 -05:00
Greg Johnston
6cf5d0a403 <Route element=... => view=... 2022-12-22 20:54:52 -05:00
Greg Johnston
79ac501302 Make <Suspense/> properly reactive again (i.e., shows fallback between states) 2022-12-22 20:45:51 -05:00
Greg Johnston
fdf17af7ab Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-22 20:21:17 -05:00
Greg Johnston
ac16d34985 Fix scoping issue by manually creating Component in Suspense 2022-12-22 20:21:14 -05:00
Jose Quesada
aa9f8f24b0 renamed element to view on <Route /> and RouteDefinition 2022-12-22 17:41:01 -06:00
Jose Quesada
d2ba8f5d46 exporting everything from matching 2022-12-22 17:30:30 -06:00
Greg Johnston
7c25cd9200 Use #[component] macro for core components, deleting leptos_core package 2022-12-22 16:46:48 -05:00
Jose Quesada
34b4917837 updated component doc formatting 2022-12-22 13:10:41 -06:00
Ben Wishovich
ac489e7523 Who let me near the computer before coffee? 2022-12-22 08:42:16 -08:00
Ben Wishovich
0909f60e55 Remove redundant env check and add path option to get_configuration() 2022-12-22 08:39:04 -08:00
Ben Wishovich
5ec76682a7 Fix Websockets Code and re-enable optimizations in tailwind. Remove watch as a param 2022-12-21 23:54:48 -08:00
Ben Wishovich
428999fd14 Updated all the examples to use the new leptos_options, and make cargo-leptos porting easy. Refactored the Tailwind example to bring it closer to leptos norms 2022-12-21 23:08:39 -08:00
Greg Johnston
ce84632c39 Update NodeRef to be generic over typed HTML elements 2022-12-21 21:15:48 -05:00
Greg Johnston
351389c2bf Correct types in SSR 2022-12-21 20:47:30 -05:00
Greg Johnston
532f5c5b83 Add types for HTML elements 2022-12-21 20:37:15 -05:00
Ben Wishovich
0d314224c9 Make tests pass, and do small tweaks/cleanup 2022-12-21 11:51:29 -08:00
Ben Wishovich
b4897f7a61 Fix dumb typos and add an option for an id to Stylesheet 2022-12-21 10:15:42 -08:00
Sarah Allen
49e93278b5 info about how to set up nightly -> README 2022-12-21 07:19:43 -08:00
Sarah Allen
cd59bf5a10 fix warning, set initial value of counter 2022-12-21 07:11:15 -08:00
Greg Johnston
66ac7d2a9d Fix hydration of <Routes/> 2022-12-21 07:58:26 -05:00
Greg Johnston
ae82395100 Remove some hydration key element increments 2022-12-21 07:58:08 -05:00
Greg Johnston
e57b6e0ccf Tidy up <Suspense/> 2022-12-21 07:57:44 -05:00
Greg Johnston
2f218e7428 Small changes to examples 2022-12-21 07:56:33 -05:00
Ben Wishovich
f2e9d6f4c3 More small tweaks to support config 2022-12-20 17:56:38 -08:00
Ben Wishovich
ee379bb405 Add errors to leptos_config and more changes to support beta 2022-12-20 12:14:42 -08:00
Ben Wishovich
d5fbeb9474 WIP Implementation of expanded LeptosOptions, which interop with the cargo-leptos beta and allow configuration of Leptos. Adds id option to <Stylesheet/> 2022-12-20 12:14:05 -08:00
Greg Johnston
7ca131c5b8 Work on hydration examples 2022-12-19 22:45:12 -05:00
Greg Johnston
79712ac4ef Fixes for <Suspense/> hydration 2022-12-19 22:45:00 -05:00
Greg Johnston
065d6b3c19 Fix workspace 2022-12-19 22:44:41 -05:00
Greg Johnston
9a2035f1e1 Relocate view-tests into leptos_dom 2022-12-19 20:11:25 -05:00
Greg Johnston
df8e50e85a Update TodoMVC example 2022-12-19 20:10:15 -05:00
Greg Johnston
58748af63b Fix _ref API in macro 2022-12-19 20:10:09 -05:00
Greg Johnston
36099c19c3 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-19 16:25:26 -05:00
Greg Johnston
8be33ccd7c Updating todo-app-sqlite example (todo: fix hydration) 2022-12-19 16:25:24 -05:00
Greg Johnston
d6920847ca Fix tests in counter example 2022-12-19 16:14:46 -05:00
Jose Quesada
f2553c117b changed from using <template /> to using custom element names and fixed EachItem on release 2022-12-19 08:57:09 -06:00
Greg Johnston
c63c8728a7 Clear warnings in router example 2022-12-19 07:41:50 -05:00
Greg Johnston
557bd25e2c Clear warnings 2022-12-19 07:39:30 -05:00
Greg Johnston
5ee8b20770 Clear warnings 2022-12-19 07:35:18 -05:00
Greg Johnston
da4b46e359 Clear warnings and improve #[cfg] readability 2022-12-19 07:34:10 -05:00
Greg Johnston
51b0ec3204 Clear warnings in view macro 2022-12-19 07:26:31 -05:00
Greg Johnston
c103c8f05b Suppress warnings about unused Scope variable in components 2022-12-19 07:22:25 -05:00
Greg Johnston
83c8f8b0cb Clear warnings in #[component] macro 2022-12-19 07:20:55 -05:00
Jose Quesada
eccbc424a2 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-18 16:52:23 -06:00
Jose Quesada
9d370776d2 printing html as it is being streamed to client 2022-12-18 16:52:12 -06:00
Greg Johnston
fc8921445e Update parent-child example 2022-12-18 17:12:06 -05:00
Greg Johnston
c635adb426 Fix Suspense & Transition, hopefully for last time (lol) 2022-12-18 17:01:56 -05:00
Greg Johnston
a845bf12e6 Clear warnings 2022-12-18 16:27:19 -05:00
Greg Johnston
eb573bf242 Remove HydrationKey from leptos_reactive 2022-12-18 16:23:04 -05:00
Greg Johnston
e8aaa77160 Remove now-unused hydration stuff from Scope 2022-12-18 16:20:44 -05:00
Greg Johnston
c0a407b0cd Fix --release builds 2022-12-18 16:15:18 -05:00
Jose Quesada
d79d4c4f86 fixed Fragment::lazy that should take `FnOnce 2022-12-18 13:29:46 -06:00
Greg Johnston
3195ab4ffc Get Suspense/Transition hydration working 2022-12-18 07:38:51 -05:00
Greg Johnston
80287f7a61 Merge pull request #174 from nim65s/main
Fix example tailwind
2022-12-17 19:43:52 -05:00
Guilhem Saurel
218faed341 Fix example tailwind
fix:
╰─>$ cargo leptos watch
Error: at `…/cargo-leptos-0.0.9/src/main.rs@104:58`

Caused by:
    no css/sass/scss file found at: "style/output.css"
2022-12-17 23:33:18 +01:00
Jose Quesada
d071a7c1e0 added HydrationCtx helper methods for forcebly adding leptos-hk, only helpers though, still need to update component lookup logic as well as element and template creation to include these 2022-12-17 12:38:40 -06:00
Jose Quesada
234e1cda4e Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-17 11:57:25 -06:00
Jose Quesada
e140549755 now removing id and leptos-hk from elements 2022-12-17 11:57:14 -06:00
Greg Johnston
df41e4dbc2 FIxes for Suspense/Hydration 2022-12-17 08:46:09 -05:00
Greg Johnston
9c6aaed0a8 Fix issue of <Routes/> mismatch 2022-12-17 08:28:22 -05:00
Greg Johnston
eaf4bbb068 Merge pull request #173 from benwis/ssr-headers
Allow Headers and Status to be set by components and Server Fns during initial SSR Load
2022-12-17 07:04:32 -05:00
Ben Wishovich
186e2454b0 Fix DBs 2022-12-16 17:37:17 -08:00
Ben Wishovich
6fa15a5584 Cleanup of testing files 2022-12-16 17:35:32 -08:00
Jose Quesada
aa71e1f66c Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-16 16:38:06 -06:00
Jose Quesada
ae16c2f96d prepending :: to leptos imports 2022-12-16 16:37:47 -06:00
Greg Johnston
4e8ad641ec Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-16 17:35:57 -05:00
Greg Johnston
64c29b1787 Remove unused import 2022-12-16 16:43:07 -05:00
Greg Johnston
df517ea9bb Add transition support 2022-12-16 16:42:27 -05:00
Ben Wishovich
2d289dd2b6 Actix version, but the issue is the same 2022-12-16 13:18:35 -08:00
Greg Johnston
702a785ca0 Fix context tests 2022-12-16 15:28:10 -05:00
Jose Quesada
abc117b9bf annotated For with #[component] 2022-12-16 14:13:51 -06:00
Greg Johnston
4823e0eb8d Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-16 12:17:49 -05:00
Greg Johnston
d65fde1ed4 Fix Link in SSR 2022-12-16 12:17:41 -05:00
Jose Quesada
6cfd2ba04e added prop docs to props builder 2022-12-16 08:51:07 -06:00
Jose Quesada
cd178c5c85 using format_ident instead of Ident::new 2022-12-16 08:25:52 -06:00
Jose Quesada
5a44f9eb4b Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-16 07:57:00 -06:00
Jose Quesada
688b0a6b73 started fine-tunning view macro spans 2022-12-16 07:30:13 -06:00
Greg Johnston
ef84d77e12 Merge branch 'main' of https://github.com/gbj/leptos 2022-12-16 07:20:59 -05:00
Greg Johnston
924b632fd3 Improve docs for provide_context and use_context 2022-12-16 07:20:54 -05:00
Ben Wishovich
2658e158df HERE BE DRAGONS 2022-12-15 22:31:47 -08:00
Ben Wishovich
21274c08bf Hmmmm 2022-12-15 22:07:11 -08:00
Greg Johnston
b83cf4dc51 Clean up Suspense SSR 2022-12-15 21:58:11 -05:00
Greg Johnston
1826d4bab2 Remove extra logging 2022-12-15 21:56:11 -05:00
Greg Johnston
e6e71cb8e6 Remove extra logging 2022-12-15 21:55:21 -05:00
Greg Johnston
01252b841d Fix <Suspense/> SSR 2022-12-15 21:54:43 -05:00
Greg Johnston
c6d30a710a FIx issues I introduced to SSR while logging this 2022-12-15 21:04:55 -05:00
Greg Johnston
fefca82d16 Minimal tracing to show order of rendering 2022-12-15 20:56:52 -05:00
Greg Johnston
a253d224ac Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-15 20:18:44 -05:00
Greg Johnston
04f331d444 Fix missing HTML 2022-12-15 20:18:41 -05:00
Ben Wishovich
2fb3515e62 Cursed, it is 2022-12-15 16:03:07 -08:00
Ben Wishovich
7a8b08d149 Broken in a new way 2022-12-15 15:57:41 -08:00
Ben Wishovich
0bc29b5f26 Closer maybe? 2022-12-15 14:12:54 -08:00
Ben Wishovich
f9bda65dbe WIP impl of SSR Header/Status setting 2022-12-15 13:14:02 -08:00
Jose Quesada
a591d54a22 changed router to directly return children, rather than a closure to not break tracing continuity 2022-12-15 13:53:39 -06:00
Jose Quesada
3e508b16f3 impl #[component(transparent)] 2022-12-15 13:40:58 -06:00
Jose Quesada
5603fac109 ported Route 2022-12-15 13:07:09 -06:00
Jose Quesada
8adf9108c5 ported Routes 2022-12-15 13:00:53 -06:00
Jose Quesada
610e38a967 fixed Coutlet from being a double component 2022-12-15 12:52:46 -06:00
Jose Quesada
34697b74a0 fixed form components to take children(cx) directly instead of a closure 2022-12-15 12:51:43 -06:00
Jose Quesada
0a8b516182 ported A 2022-12-15 12:50:00 -06:00
Jose Quesada
5405dcd09d ported MultiActionForm 2022-12-15 12:40:41 -06:00
Jose Quesada
1aaacbaf5b ported ActionForm 2022-12-15 12:37:19 -06:00
Jose Quesada
ce9aec2520 started porting router to #[component] 2022-12-15 12:31:53 -06:00
Jose Quesada
422233eecf removed some HydrationCtx things and improved tracing for DynChild 2022-12-15 12:05:17 -06:00
Jose Quesada
3b99d2d4fd added tracing support to component macro 2022-12-15 12:01:16 -06:00
Jose Quesada
9eadac9f2c added HydrationCtx helpers and fixed a couple bugs with the hydration example 2022-12-15 10:04:44 -06:00
Greg Johnston
416e1a617b Change start to hydrate in example 2022-12-15 08:39:19 -05:00
Greg Johnston
1b0aa4d903 Disable macro SSR until I've added IDs 2022-12-15 08:36:46 -05:00
Greg Johnston
01013b00e5 Implement classes in SSR macro path 2022-12-15 07:56:31 -05:00
Greg Johnston
3ef64bd372 <Suspense/> streaming and hydration issue 2022-12-14 23:18:54 -05:00
Greg Johnston
c463579faa Round 1 of next_hydration_key() 2022-12-14 20:38:37 -05:00
Greg Johnston
67de5685bb Merge pull request #167 from benwis/axum-context
Give Axum access to Request and allow server functions to set status/headers/cookies
2022-12-14 15:47:54 -05:00
Ben Wishovich
8a85d4261a Fix Todo DB 2022-12-14 11:20:53 -08:00
Jose Quesada
218c4d3c90 moved body back inside itself to allow forwarding attributes 2022-12-14 12:57:43 -06:00
Ben Wishovich
90849cc6e3 Add working example of Actix/Axum Header and Status Setting 2022-12-14 10:55:05 -08:00
Jose Quesada
5f95776a08 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-14 12:24:16 -06:00
Jose Quesada
adee33a08e initial impl of #[prop()] 2022-12-14 12:15:41 -06:00
Greg Johnston
e3e0460371 Disable SSR macr until node ID generation is done 2022-12-14 10:57:37 -05:00
Greg Johnston
6e4448dae6 SSR work with missing node IDs 2022-12-14 10:56:48 -05:00
Greg Johnston
fee0f5490b Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-14 09:06:20 -05:00
Greg Johnston
e1836af6bd Fix .wasm location in integration 2022-12-14 09:06:10 -05:00
Jose Quesada
b37a36a003 allowing clippy lint for too many arguments on components 2022-12-14 07:34:31 -06:00
Greg Johnston
e865f609ee Merge pull request #166 from gbj/component-macro-docs
Add more entry-level docs for `#[component]` macro
2022-12-14 07:49:33 -05:00
Greg Johnston
621122adf7 Fix Suspense/Transition SSR 2022-12-14 07:12:43 -05:00
Greg Johnston
f6acecd3ad Fix Wasm import URL in integrations 2022-12-14 07:12:36 -05:00
Greg Johnston
f17c7fdb90 Remove duplicated window_event_listener 2022-12-14 07:00:56 -05:00
Greg Johnston
21178b1682 Correct definitions of is_browser and is_server 2022-12-14 06:57:35 -05:00
Ben Wishovich
9f97497e48 Working impl of Request access and Response cookies for Axum 2022-12-13 22:07:15 -08:00
Ben Wishovich
70f2b3b4d3 More fiddling, still no dice 2022-12-13 16:05:31 -08:00
Ben Wishovich
181a15cf66 WIP axum acces to request 2022-12-13 15:23:47 -08:00
Jose Quesada
a7a35857bb now tracking scope name 2022-12-13 14:33:34 -06:00
Jose Quesada
caa919b257 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-13 14:15:42 -06:00
Jose Quesada
4c123884de reverted to redeclaring the component fn within itself 2022-12-13 14:15:23 -06:00
Greg Johnston
5e06eb1a99 Correct use of cx 2022-12-13 15:14:41 -05:00
Greg Johnston
cc0bf20c9d Use the correct identifier for cx here 2022-12-13 15:06:21 -05:00
Jose Quesada
5aab8e40c2 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-13 13:24:06 -06:00
Jose Quesada
eeaccfc815 moved fn block into Component::new 2022-12-13 13:23:51 -06:00
Greg Johnston
cac1187346 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-13 14:21:06 -05:00
Greg Johnston
4134d2f924 Working on router example 2022-12-13 14:20:58 -05:00
Jose Quesada
39e809f686 initial impl of component macro with inline doc comments and TypedBuilder overrides 2022-12-13 12:44:30 -06:00
Greg Johnston
896812c8d6 Merge pull request #165 from Gentle/update_returning
update_returning handlers
2022-12-13 12:54:40 -05:00
Jose Quesada
286c95136f Merge branch 'leptos_dom_v2' into leptos_dom_v2_component 2022-12-13 07:38:51 -06:00
Greg Johnston
5ca169ac06 Properly handle Scope when creating component children 2022-12-13 07:42:14 -05:00
Greg Johnston
8efb28826f Properly set hydration key 2022-12-12 21:17:51 -05:00
Greg Johnston
10799c33b7 Properly dispose 2022-12-12 21:17:38 -05:00
Greg Johnston
657de9df33 Remove log 2022-12-12 20:57:18 -05:00
Greg Johnston
069fc88042 Update SSR support for Suspense/Transition 2022-12-12 20:56:19 -05:00
Greg Johnston
92335989b7 Don't overwrite MetaContext from integration 2022-12-12 20:55:57 -05:00
Greg Johnston
58d2ce113d Use Scope-based hydration key generation 2022-12-12 20:55:41 -05:00
Greg Johnston
e499c88288 Consolidating hydration key generation 2022-12-12 20:55:28 -05:00
Ramon Klass
fea462c90a update_returning handlers 2022-12-13 02:19:58 +01:00
Jose Quesada
a75cbee133 started working on component macro 2022-12-12 18:33:12 -06:00
Jose Quesada
99ff73c721 applied fix per gbj's suggested 2022-12-12 16:23:15 -06:00
Jose Quesada
2c9eff3659 impl IntoView for all std types that made sense 2022-12-12 14:45:10 -06:00
Jose Quesada
ce5355d73f impl IntoView for `Vec<impl IntoView> 2022-12-12 13:52:41 -06:00
Jose Quesada
582cd7d729 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-12 13:39:57 -06:00
Jose Quesada
e2ef293d19 added IntoFragment trait for all IntoIterator and also impl FromIterator for Fragment 2022-12-12 13:39:41 -06:00
Greg Johnston
b06a4ba805 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-12 13:40:13 -05:00
Greg Johnston
6b6c54e8ff Updating hackernews example 2022-12-12 13:40:05 -05:00
Greg Johnston
8a0e56aff5 Properly namespace Fragment when used 2022-12-12 13:39:50 -05:00
Greg Johnston
1804a65857 Merge in updates to meta package 2022-12-12 13:39:30 -05:00
Greg Johnston
035f929d3b Merge class prop back into A component 2022-12-12 13:39:19 -05:00
Jose Quesada
0b11a8dda6 fixed compilation on non-CSR targets 2022-12-12 12:26:11 -06:00
Jose Quesada
5881fb9064 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-12 12:18:29 -06:00
Jose Quesada
9dbbb26100 made is_server and helpers const fn and added View::into_html_element helper 2022-12-12 12:18:15 -06:00
Greg Johnston
9c0d813697 Resolve issue with scope disposal panicking because it can't find runtime (because runtime already dropped) 2022-12-12 10:25:20 -05:00
Greg Johnston
4a1d16b641 Properly reset ID in streaming 2022-12-12 10:24:55 -05:00
Greg Johnston
c4eeb4f39f Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-12 09:49:22 -05:00
Greg Johnston
37ab7b34f9 Fix imports when in SSR mode so we don't run wasm-bindgen code 2022-12-12 09:49:15 -05:00
Greg Johnston
fcae17eab7 Streamline streaming SSR 2022-12-12 09:48:45 -05:00
Greg Johnston
c4cc3e944b Merge in changes from main 2022-12-12 09:26:46 -05:00
Greg Johnston
c481e465b0 Update counter-isomorphic 2022-12-12 09:26:13 -05:00
Greg Johnston
073bd759b0 Add .gitignore 2022-12-12 09:25:57 -05:00
Greg Johnston
88435af844 Update counter-isomorphicexample 2022-12-12 09:25:47 -05:00
Jose Quesada
ff21f38626 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-12 07:29:51 -06:00
Jose Quesada
9bc8492245 removed impl of IntoView for &str and replaced with &'static str for Cow<'static, str> opt 2022-12-12 07:29:35 -06:00
Greg Johnston
2389cec5f7 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-11 20:21:35 -05:00
Greg Johnston
86d5f4c2e4 Update <For/> in example 2022-12-11 20:21:07 -05:00
Jose Quesada
811449d664 stopped DynChild from panicking when nested DynChild run within the same signal trigger but the parent runs before this child 2022-12-11 17:36:19 -06:00
Greg Johnston
109863c59a Update SSR benchmark code to new APIs 2022-12-11 17:42:15 -05:00
Greg Johnston
b9e8777bb1 Update <For/> API 2022-12-11 17:35:46 -05:00
Jose Quesada
d44c7f121b remove Transition DynChild workaround 2022-12-11 13:37:45 -06:00
Jose Quesada
9b1c4e42bd added missing generic and removed workaround for Suspense DynChild 2022-12-11 13:33:11 -06:00
Jose Quesada
ff026ea953 addressed clippy lints in release mode 2022-12-11 13:27:52 -06:00
Jose Quesada
9eb1f2fdf8 addressed clippy lints 2022-12-11 13:22:01 -06:00
Jose Quesada
06538ba021 fixed DynChild when changing from Text to anything else 2022-12-11 13:06:54 -06:00
Jose Quesada
14c6dcf902 now surrounding View::Text with quotes 2022-12-11 12:57:54 -06:00
Jose Quesada
a15dedb82d impl new fmt::Debug repr for View 2022-12-11 12:43:58 -06:00
Greg Johnston
43ffa1bcd7 Use Fn() -> Fragment for component children, and update router and Suspense/Transition 2022-12-10 22:12:08 -05:00
Greg Johnston
d30de9abce Add Transparent type to pass arbitrary data inside a View 2022-12-10 22:11:39 -05:00
Greg Johnston
f459253cdb Clear warning here and add explanation 2022-12-10 21:05:13 -05:00
Greg Johnston
a53f7ccdb7 Update Suspense and Transition with new impl IntoView pattern 2022-12-10 19:51:41 -05:00
Greg Johnston
b7bd4fc69c Update Counters example 2022-12-10 19:51:30 -05:00
Greg Johnston
9d43eb5503 Tweak handling of component children 2022-12-10 19:42:08 -05:00
Greg Johnston
335c040702 Implement IntoView for same set of primitive types 2022-12-10 19:33:56 -05:00
Greg Johnston
a4e5bf03d8 Start implementing IntoView for primitives 2022-12-10 19:28:28 -05:00
Greg Johnston
90de653a60 Concrete return types work 2022-12-10 19:28:11 -05:00
Greg Johnston
359feebccf Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-10 19:21:51 -05:00
Greg Johnston
6c29d85b8d Remove into_view in view and component macros 2022-12-10 19:21:46 -05:00
Jose Quesada
315407b866 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-10 15:32:51 -06:00
Jose Quesada
d22fa3c5e7 removed IntoChild 2022-12-10 15:32:36 -06:00
Greg Johnston
6d24af7748 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-10 16:22:55 -05:00
Greg Johnston
18bd2162cf Docs in component macro 2022-12-10 16:21:58 -05:00
Jose Quesada
74ea50a293 fixed Component::new to take anything that impl IntoView 2022-12-10 13:50:05 -06:00
Greg Johnston
4a9f906571 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-10 14:09:43 -05:00
Greg Johnston
4b970b3f1c Fix rerendering issue 2022-12-10 14:06:49 -05:00
Greg Johnston
6db086c0a6 Meant to delete this, not comment it out 2022-12-10 14:06:42 -05:00
Greg Johnston
a7da8232a7 I was wrong -- these will be automatically disposed by the parent scope in the correct order, and actually shouldn't be done manually 2022-12-10 14:06:18 -05:00
Jose Quesada
a5f868915a added trait for converting impl AsRef<web_sys::Element> to HtmlElement<AnyElement> 2022-12-10 12:16:08 -06:00
Jose Quesada
237bacc2da addressed all clippy lints 2022-12-10 10:50:01 -06:00
Jose Quesada
e09f5665ca Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-10 09:54:56 -06:00
Jose Quesada
11720302a2 addressed all clippy lints for web targets 2022-12-10 09:54:49 -06:00
Jose Quesada
e097ec84c2 started addressing clippy lints and fixed an undiscovered bug 2022-12-10 08:40:24 -06:00
Greg Johnston
bcb130deca Working on router 2022-12-10 09:15:05 -05:00
Greg Johnston
c4af033f2c Remove logging 2022-12-10 09:12:11 -05:00
Greg Johnston
5bdd150347 Get router working with new renderer 2022-12-10 08:32:58 -05:00
Greg Johnston
f9cc57acb9 Fix attributes in view macro 2022-12-10 08:32:30 -05:00
Greg Johnston
000d796149 Update router example 2022-12-10 08:32:19 -05:00
Greg Johnston
a7c16c9b09 Implement PartialEq and Eq for View 2022-12-10 07:37:07 -05:00
Greg Johnston
ad01d69540 <Suspense/> and <Transition/> 2022-12-09 22:52:30 -05:00
Greg Johnston
7959f5b324 Add signal helpers from main that are needed for <Transition/> 2022-12-09 22:52:14 -05:00
Greg Johnston
46e77d72ea Add transition 2022-12-09 22:23:42 -05:00
Greg Johnston
1b8db4d4f4 "Implement Clone on View and its affiliates. Necessary for <Transition/> and some routing features. No significant changes needed, every type involved could already derive Clone. 2022-12-09 22:17:26 -05:00
Greg Johnston
7264d902c6 RIP map_keyed and old <For/> component 2022-12-09 22:07:07 -05:00
Jose Quesada
8017b416fb Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-09 18:58:58 -06:00
Jose Quesada
dd16890021 Component now creating child scope, forgot about this 2022-12-09 18:58:38 -06:00
Jose Quesada
a17651fe02 removed the workspace override 2022-12-09 18:00:06 -06:00
Greg Johnston
ba34a9644e Work on Suspense 2022-12-09 18:27:32 -05:00
Jose Quesada
094492f076 impl IntoChild for tuples up to 26 in size 2022-12-09 17:13:37 -06:00
Jose Quesada
6d5994f72e removed TopoId 2022-12-09 17:08:11 -06:00
Jose Quesada
641a064200 removed IntoEach until we can come up with a better game plan 2022-12-09 17:04:32 -06:00
Jose Quesada
c83f29be1b fix DynChild saving it's old child, rather than the new one 2022-12-09 16:46:02 -06:00
Jose Quesada
bd3cc0b5ec fix DynChild trying to render old child rather than new one 2022-12-09 16:17:37 -06:00
Greg Johnston
f6eceaeaf9 Update counters exaple 2022-12-09 14:56:50 -05:00
Greg Johnston
9a114eb595 Avoid name conflicts between functions to create elements and local variables 2022-12-09 14:36:25 -05:00
Jose Quesada
1ee9c2432b impl IntoView for tuples of up to 26 fields as well as for (Scope, T) 2022-12-09 11:29:46 -06:00
Jose Quesada
b0c27c48f6 updated example to work with new Each 2022-12-09 10:49:15 -06:00
Jose Quesada
c74a8274f2 removed child scope creation within Each 2022-12-09 10:44:05 -06:00
Jose Quesada
2ceb7f8934 fixed Fragment which would try mounting it's children while hydrating 2022-12-09 10:03:08 -06:00
Jose Quesada
16af593277 added render_to_string entry point and fixed bug where id counter would not be reset on every server render call 2022-12-09 09:34:25 -06:00
Jose Quesada
51c8d85528 custom user id's on HtmlElement is now supported during hydration 2022-12-09 09:15:37 -06:00
Jose Quesada
4ffc53a1dc not panicking when elements/components cannot be found 2022-12-09 08:47:53 -06:00
Jose Quesada
b7eeba77a0 fixed DynChild on release to prevent it merging with surrounding text 2022-12-09 08:25:39 -06:00
Jose Quesada
a8fb2720b9 removed a sneaky c that was in the SSR id generation for components, as well as fixed an extra id call count that wasn't supposed to be there 2022-12-08 22:40:49 -06:00
Jose Quesada
a50f1c58f7 fixed Each optimizations 2022-12-08 20:38:59 -06:00
Jose Quesada
6528aadb90 removed debug statement 2022-12-08 19:18:23 -06:00
Jose Quesada
dcd9842fca Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-08 18:42:55 -06:00
Jose Quesada
5a976525c0 fixed Each moving items it did not need to move 2022-12-08 18:42:36 -06:00
Greg Johnston
b8559d4335 Transition counter example to use View 2022-12-08 19:33:01 -05:00
Greg Johnston
eb40f9f7c7 Remove leptos_dom/ssr dependencies 2022-12-08 19:32:46 -05:00
Greg Johnston
d0fa9b89bf Remove my logs 2022-12-08 19:25:50 -05:00
Greg Johnston
fbfd1a4f60 Fix other dependencies on leptos_dom/csr and leptos_dom/hydrate 2022-12-08 19:24:36 -05:00
Jose Quesada
21716ea59d fixed panic on DynChild for double taking an option 2022-12-08 18:15:57 -06:00
Jose Quesada
e641108ed3 fixed error compiling 2022-12-08 18:01:06 -06:00
Jose Quesada
c3b4945c7e removed all cfgs that depend on anything but web and wasm32 2022-12-08 17:56:52 -06:00
Jose Quesada
95c535290d Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-08 17:48:45 -06:00
Jose Quesada
6af0b1a8ed hydration is now determained at runtime startup 2022-12-08 17:48:30 -06:00
Greg Johnston
9928abf36d Fix closing-node creation in Each in release 2022-12-08 18:45:27 -05:00
Greg Johnston
f0257222f8 Fix cx injection in macro 2022-12-08 18:29:44 -05:00
Greg Johnston
135317b7b8 Method, not a field 2022-12-08 18:26:44 -05:00
Jose Quesada
6b24135070 fixed subtle bug when hydrating from a text node would cause DynChild to not unmount correctly 2022-12-08 17:00:55 -06:00
Jose Quesada
e08808c2ab fixed SSR compilation errors 2022-12-08 16:13:12 -06:00
Jose Quesada
a932f72a4f DynChild now creating child scopes 2022-12-08 16:07:44 -06:00
Jose Quesada
75befde788 now creating child scopes for Each 2022-12-08 15:17:12 -06:00
Jose Quesada
adac34790e now creating child scopes for Each items, still not cleaning them up, however 2022-12-08 11:50:22 -06:00
Jose Quesada
838d0d27c9 fixed DynChild not removing the text generated on SSR 2022-12-08 11:10:34 -06:00
Jose Quesada
d29d29c1d4 fixed .into_view(cx) calling order to match between SSR and CSR 2022-12-08 10:41:28 -06:00
Jose Quesada
61e206c227 corrected DynChild to now mount children on SSR 2022-12-08 09:19:00 -06:00
Jose Quesada
70ae60d4d5 fixed broken compilation 2022-12-08 08:56:53 -06:00
Greg Johnston
56457bc3ad Generate HydrationKey with Scope 2022-12-07 15:57:53 -05:00
Greg Johnston
45395fe580 Fix off-by-one issue 2022-12-07 15:46:09 -05:00
Jose Quesada
3a90ed6c21 added debug aids to find the off-by-one error 2022-12-07 12:33:39 -06:00
Jose Quesada
55b691e1b0 marker hydration fixed, but we have an off-by-one error on id generation 2022-12-07 12:05:12 -06:00
Jose Quesada
c9b57ffa85 changed the value to bind to another input while I fix text 2022-12-07 10:43:10 -06:00
Jose Quesada
c239716170 updated the example to work with hydartion 2022-12-07 10:04:54 -06:00
Jose Quesada
46ef1bcf5d initial impl of eager hydration 2022-12-07 09:36:36 -06:00
Jose Quesada
5ac06251d4 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-07 07:24:53 -06:00
Jose Quesada
395cfe6bf1 fixed SSR and CSR cfg features 2022-12-07 07:24:35 -06:00
Greg Johnston
963ff85a5f Get basic SSR example working 2022-12-06 23:04:48 -05:00
Greg Johnston
dcbdbc8925 <template/> doesn't work as a self-closing tag 2022-12-06 23:03:33 -05:00
Jose Quesada
c290d1e9d6 started impl hydration for HtmlElement 2022-12-06 20:14:35 -06:00
Jose Quesada
51e5c6ba62 fixed TopoId not having a sum field 2022-12-06 11:35:31 -06:00
Jose Quesada
ee470b37bb removed starting_offset when calculating children ids 2022-12-06 10:26:19 -06:00
Jose Quesada
74c716e0f6 fixed attrs that start with an empty value from not having a space 2022-12-06 10:12:14 -06:00
Jose Quesada
00c25b5605 fixed EachItem not getting <template /> markers, as well as Unit 2022-12-06 09:55:02 -06:00
Jose Quesada
280f7a7735 removed cx param from all helper methods 2022-12-06 07:32:49 -06:00
Jose Quesada
f02405b649 fixed IntoProperty from disconnection from overwritten Scope 2022-12-06 07:24:21 -06:00
Jose Quesada
d6ef65daf6 fixed IntoClass from not disconnecting from overwritten Scope 2022-12-06 07:21:14 -06:00
Jose Quesada
98414ac192 removed overzelus use of Scope in Attribute 2022-12-06 07:15:39 -06:00
Jose Quesada
8b7728096a fixed IntoChild to not disconnect from overwritten Scope 2022-12-05 20:51:00 -06:00
Greg Johnston
aec289e384 Get SSR benchmarks running again 2022-12-05 20:34:29 -05:00
Greg Johnston
432eda8d6d Add some often-used helper functions 2022-12-05 20:00:27 -05:00
Greg Johnston
aa10ab861a Fix new cx-passing API for Attribute 2022-12-05 16:09:22 -05:00
Greg Johnston
870d8f3542 Different form for passing in cx 2022-12-05 16:07:25 -05:00
Greg Johnston
166df8d4c4 Merge changes to remove cx everywhere 2022-12-05 16:05:12 -05:00
Greg Johnston
666269539d Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-05 16:04:54 -05:00
Greg Johnston
0230b1ffa5 Deal w/ merge issues and get SSR working 2022-12-05 16:04:02 -05:00
Jose Quesada
3dd789f0c2 fixed IntoAttribute from disconnecting from it's overwritten Scope 2022-12-05 14:30:21 -06:00
Greg Johnston
dbb0fca1cb Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-05 15:12:09 -05:00
Greg Johnston
b8bd3bef13 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-05 15:11:17 -05:00
Jose Quesada
59f753cebb impl all the macro helper traits for (Scope, T) 2022-12-05 14:09:39 -06:00
Greg Johnston
d5f91e67a5 First pass at SSR 2022-12-05 15:09:04 -05:00
Greg Johnston
1b854ed787 Warn if you re-set a NodeRef 2022-12-05 14:24:33 -05:00
Jose Quesada
13f8006162 added HtmlElement::node_ref 2022-12-05 13:19:34 -06:00
Jose Quesada
b3d813d0c1 renamed IntoNode to IntoView and Node to View, and fixed broken doc links 2022-12-05 12:39:42 -06:00
Jose Quesada
1fbe8bd790 fixed the example to show undelegated 2022-12-05 12:28:14 -06:00
Jose Quesada
eba8af3b38 fixed event names and removed superfluous debug stmt 2022-12-05 12:23:53 -06:00
Jose Quesada
589f2585cc added small list of events that don't bubble 2022-12-05 11:43:18 -06:00
Jose Quesada
b69119f11f added all events I could find 2022-12-05 11:12:31 -06:00
Greg Johnston
f893dca39b This should handle the disposal correctly, when the parent scope disposes, instead of on Drop (which is immediate.) 2022-12-05 09:24:52 -05:00
Greg Johnston
64722604b5 Move Component::new() invocation inside the #[component] macro to allow for things like the <Route/> component 2022-12-05 08:45:27 -05:00
Greg Johnston
b6a90f154f Remove useless attempt at better Intellisense 2022-12-04 23:04:06 -05:00
Greg Johnston
2ef8032110 The event names shouldn't actually start with "on" — that's the HTML attribute form 2022-12-04 23:03:54 -05:00
Greg Johnston
3992febbfc Restored these events so they can be used, just typed as Event 2022-12-04 23:03:19 -05:00
Greg Johnston
982cec9507 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-04 22:59:57 -05:00
Greg Johnston
4a5b3b3cc5 Use new event system 2022-12-04 22:59:45 -05:00
Jose Quesada
18ff334f70 disabled non-existant web_sys event types 2022-12-04 21:38:23 -06:00
Jose Quesada
d2b4ae30d1 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-04 21:30:55 -06:00
Jose Quesada
abed797027 added HtmlElement::prop to the builder 2022-12-04 21:30:48 -06:00
Greg Johnston
a4ca863d42 Should insert the actual event type instead of MouseEvent! 2022-12-04 22:26:28 -05:00
Jose Quesada
6737413103 made Undelegated inner field public so users can just wrap any event with it to force it undelegated 2022-12-04 21:23:16 -06:00
Greg Johnston
33c3851d5b Fix fake assignment 2022-12-04 22:13:07 -05:00
Greg Johnston
7c298272d3 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-04 22:11:00 -05:00
Greg Johnston
71a2a24d09 Working components in view! macro 2022-12-04 22:10:56 -05:00
Jose Quesada
cffdc56062 added Custom event helper type for events not included 2022-12-04 20:45:58 -06:00
Jose Quesada
c29c15e1b7 removed on_delegated, as this can be done through Delegated<E>` type 2022-12-04 20:36:18 -06:00
Jose Quesada
fe417d50af Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-04 17:22:24 -06:00
Jose Quesada
cc538f8427 added more events 2022-12-04 17:22:03 -06:00
Jose Quesada
07db7ae62b started the grooling process of adding typed events 2022-12-04 09:13:20 -06:00
Greg Johnston
09d2a56672 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-03 21:29:22 -05:00
Greg Johnston
8ea7e20dfb Builder-compatible view! macro 2022-12-03 21:28:39 -05:00
Greg Johnston
02c982c80f Missing cfg causing non-CSR builds to break; I may have removed this accidentally or somethign 2022-12-03 21:27:53 -05:00
Jose Quesada
a5b157f14f uncommented (presumably) accidental comment of components import 2022-12-03 17:58:51 -06:00
Jose Quesada
5d439ceee8 fixed merge conflict 2022-12-03 16:52:57 -06:00
Jose Quesada
282ece2fab fixed Each when moving to take into account backshift 2022-12-03 16:50:29 -06:00
Greg Johnston
205abd4cbc Add _prop macro helper 2022-12-03 14:47:39 -05:00
Greg Johnston
fbb372e618 Add is_server and is_dev helper macros 2022-12-03 14:47:31 -05:00
Greg Johnston
b4679ea688 Fix NodeRef on stable 2022-12-03 14:28:33 -05:00
Greg Johnston
d2f68d8a0a Add helpers for simple logging 2022-12-03 14:22:19 -05:00
Greg Johnston
ebe872ca57 Add NodeRef 2022-12-03 14:21:42 -05:00
Greg Johnston
bce1ed8d67 Add NodeRef 2022-12-03 14:21:36 -05:00
Greg Johnston
a87ffd6d5c Make it possible for macro to specify event types automatically by reducing to one generic 2022-12-03 14:20:18 -05:00
Greg Johnston
c0d2dde53a _class helper for macro 2022-12-03 14:05:59 -05:00
Greg Johnston
cd93ecb5ab Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-03 13:43:14 -05:00
Greg Johnston
4beee7f924 Fix bounds check -- was panicking on remove because added_delta was -1 2022-12-03 13:43:05 -05:00
Jose Quesada
234260a784 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-03 12:29:45 -06:00
Jose Quesada
e82d4d492b revert EachItem lazy text fill 2022-12-03 12:29:28 -06:00
Greg Johnston
aa0271a493 Add _attr helper for macro 2022-12-03 13:06:15 -05:00
Greg Johnston
29db252411 Remove fill_if_text since eager now 2022-12-03 13:06:06 -05:00
Jose Quesada
aa5caaf4f1 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-03 10:38:47 -06:00
Jose Quesada
718b5f8ae1 forgot to fill child text nodes of EachItem 2022-12-03 10:34:36 -06:00
Greg Johnston
48e4e01e24 Fast path for Text -> Text. I think this is probably broken at the moment (if you replace Text with something else) but can fix 2022-12-03 11:29:53 -05:00
Greg Johnston
7948a1914a Fill Text node eagerly 2022-12-03 10:54:38 -05:00
Greg Johnston
1fa023ee08 Merge branch 'leptos_dom_v2' of https://github.com/jquesada2016/leptos into leptos_dom_v2 2022-12-03 10:35:58 -05:00
Greg Johnston
cc1c264548 ._child() helper for macro (merges child and dyn_child) 2022-12-03 10:34:27 -05:00
Jose Quesada
11960efb1b impl Deref<Target = web_sys::HtmlElement> for HtmlElement<El>` 2022-12-03 08:45:29 -06:00
Jose Quesada
16706233c7 fixed Each move requiring backshifting all items 2022-12-02 21:17:27 -06:00
Jose Quesada
c49ed49580 refactored a bit and left the premise for fixing Move in Each 2022-12-01 23:14:30 -06:00
Greg Johnston
a0e0194475 FxHashSet uses a faster hashing algorithm than the default SipHash 2022-12-01 17:22:35 -05:00
Greg Johnston
d266943a8f id isn't necessary in the browser version, right? 2022-12-01 17:22:05 -05:00
Jose Quesada
86acd8a461 now reusing text nodes 2022-12-01 14:31:47 -06:00
Jose Quesada
786b7abcb7 fixed Each opts to handle more edge casses 2022-12-01 07:58:28 -06:00
Jose Quesada
05adbda4ca fixed panic when trying to get parent node 2022-11-30 20:31:09 -06:00
Jose Quesada
6db59d526f fixed panic when dropping components 2022-11-30 20:12:13 -06:00
Jose Quesada
0149ce1be1 removed need for 2 marker nodes 2022-11-30 13:29:51 -06:00
Jose Quesada
b058e68e4e addressed errors and clippy lints 2022-11-30 09:01:16 -06:00
Greg Johnston
0ef0417b5a Separate SSR + browser implementations, with eager creation in browser (+ string interning) 2022-11-29 22:15:27 -05:00
Jose Quesada
649378ffbe now using Range only for potentially large groups of nodes 2022-11-29 20:08:54 -06:00
Jose Quesada
060f8d7a6a usine clone_node on cached nodes 2022-11-29 17:00:42 -06:00
Jose Quesada
b8c125cd14 initial impl of eager builder 2022-11-29 16:50:52 -06:00
Jose Quesada
33afcf6b17 impl eager setting of attr 2022-11-29 15:49:32 -06:00
Jose Quesada
bbb188d2f6 added some more small opts, including using only a single Range obj 2022-11-29 13:44:03 -06:00
Jose Quesada
d8f8673ad3 tuned append opt to include the limit 2022-11-29 13:11:00 -06:00
Jose Quesada
a73c71842a added Each append opt 2022-11-29 12:49:46 -06:00
Jose Quesada
d59ce5aebf fixed replace all items opt 2022-11-29 12:01:19 -06:00
Jose Quesada
5b14aa98e9 Comment markers are now being created by cloning a reference 2022-11-29 11:15:29 -06:00
Jose Quesada
f78400a955 fixed merge conflict 2022-11-29 07:44:47 -06:00
Jose Quesada
488856fdcc removed broken debug assertions 2022-11-29 07:37:33 -06:00
Greg Johnston
42659e20cd Fast path for clearing 2022-11-28 21:51:23 -05:00
Greg Johnston
54b7b780c8 (Some of?) these debug assertions seem to break the release build 2022-11-28 21:37:47 -05:00
Jose Quesada
a638c3d39a removed superfluous console::log 2022-11-28 19:13:46 -06:00
Jose Quesada
ebb50cff6c fixed building on non-browser targets 2022-11-28 19:04:00 -06:00
Jose Quesada
9424c293d7 fixed ops conflicting with each other 2022-11-28 18:49:06 -06:00
Jose Quesada
0b72c5550b fixed Each clear opt 2022-11-28 17:26:48 -06:00
Jose Quesada
698527ddf6 fixed building in release 2022-11-28 15:02:09 -06:00
Jose Quesada
af067361a9 checking to make sure children is not empty before applying replace opt 2022-11-28 14:19:31 -06:00
Jose Quesada
04aa1585fa optimized the case of replacing all items in an Each 2022-11-28 14:04:14 -06:00
Jose Quesada
9e84a2c273 Each now optimized for clearing 2022-11-28 13:30:37 -06:00
Jose Quesada
9050572c68 EachItem is now removing it's direct children 2022-11-28 13:21:13 -06:00
Jose Quesada
40c6081256 DynChild is now responsible for removing it's direct children rather than relying on WebSysNode 2022-11-28 13:12:22 -06:00
Jose Quesada
484e6796c0 Component now creating a child scope` 2022-11-28 08:59:35 -06:00
Greg Johnston
fdef43c2fc Small performance optimizations: wasm-bindgen string interning and cached document() (+ a function to mount to any parent) 2022-11-28 08:45:09 -05:00
Greg Johnston
90854e38e6 Add event system 2022-11-27 19:42:37 -05:00
Jose Quesada
8fac1c5b3a greatly improved tracing visibility 2022-11-27 17:17:24 -06:00
Jose Quesada
6439964ef6 made children field of Component pub and added Component example to examples/test-bench 2022-11-27 11:57:35 -06:00
Jose Quesada
5b612d8084 fixed Component not mounting children on into_node calls 2022-11-27 11:46:36 -06:00
Jose Quesada
b2d9bc4aa8 removed duplicate value, as duplicate keys are invalid 2022-11-27 11:34:35 -06:00
Jose Quesada
f615dae87c applied new rustfmt config and added HtmlElement::dyn_attr 2022-11-27 11:32:18 -06:00
Jose Quesada
79058e1535 impl IntoNode for [Node; N] and `[HtmlElement<El>; N] 2022-11-27 09:49:57 -06:00
Jose Quesada
a51c12d152 added HtmlElement::attr_bool helper method 2022-11-27 09:45:38 -06:00
Jose Quesada
8999a24ec3 can now set id and attrs 2022-11-27 09:34:19 -06:00
Jose Quesada
da1916e35a renamed Each to EachKey 2022-11-27 07:29:17 -06:00
Jose Quesada
b1987648cf addressed most clippy lints 2022-11-27 07:20:33 -06:00
Jose Quesada
001323c058 fixed compilation on non-browser targets 2022-11-27 07:09:07 -06:00
Jose Quesada
55633560e7 Each is now fully working 2022-11-26 20:59:54 -06:00
Jose Quesada
be60713b13 updated prepare_for_move to use Range 2022-11-26 19:36:25 -06:00
Jose Quesada
000a4bf62d initial (broken move) impl of Each 2022-11-26 18:49:51 -06:00
Jose Quesada
68938054ca removed name and rename from DynChild 2022-11-26 09:37:56 -06:00
Jose Quesada
368b96424d refactored components to not render as many comments in prod 2022-11-26 09:33:57 -06:00
Jose Quesada
c5da652ac1 renamed Fragment representation from <Frgament> to <> 2022-11-26 07:17:12 -06:00
Jose Quesada
38f71a3cc9 impl Default for all HTML tags 2022-11-26 07:16:15 -06:00
Jose Quesada
2d21146665 basic CSR is working 2022-11-25 17:39:42 -06:00
Jose Quesada
24b1fc01ca added impl IntoNode for most types IntoChild supported 2022-11-25 14:37:47 -06:00
Jose Quesada
fbfdb9fd15 now collecting Scope only on `IntoNode::into_node 2022-11-25 13:10:51 -06:00
Jose Quesada
54074409ab only std::prelude clashing structs should have a trailing _ 2022-11-25 07:39:15 -06:00
Jose Quesada
e738c5c41f forgot to redirect docs to the builder fn 2022-11-24 21:37:46 -06:00
Jose Quesada
d3ec86ab18 added all HTML elements 2022-11-24 21:35:40 -06:00
Jose Quesada
ce5b8f95e7 forgot to insert opening and closing component marker nodes into the document fragment 2022-11-24 16:57:44 -06:00
Jose Quesada
6bb20aed15 initial API design 2022-11-24 14:45:31 -06:00
Jose Quesada
9b3c9eb90b clean slate 2022-11-24 09:16:57 -06:00
287 changed files with 16287 additions and 8345 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These are supported funding model platforms
github: gbj

View File

@@ -21,13 +21,14 @@ jobs:
- ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setup Rust
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
override: true
components: rustfmt
- name: Setup cargo-make
uses: davidB/rust-cargo-make@v1
@@ -35,6 +36,9 @@ jobs:
- name: Cargo generate-lockfile
run: cargo generate-lockfile
- name: Run Rustfmt
run: cargo fmt -- --check
- name: Cargo cache
uses: actions/cache@v3
with:

1
.gitignore vendored
View File

@@ -6,4 +6,3 @@ blob.rs
Cargo.lock
**/*.rs.bk
.DS_Store
.leptos.kdl

View File

@@ -3,7 +3,6 @@ members = [
# core
"leptos",
"leptos_dom",
"leptos_core",
"leptos_config",
"leptos_macro",
"leptos_reactive",
@@ -17,28 +16,25 @@ members = [
"meta",
"router",
# examples
"examples/counter",
"examples/counter-isomorphic",
"examples/counters",
"examples/counters-stable",
"examples/fetch",
"examples/hackernews",
"examples/hackernews-axum",
"examples/parent-child",
"examples/router",
"examples/todomvc",
"examples/todo-app-sqlite",
"examples/todo-app-sqlite-axum",
"examples/todo-app-cbor",
"examples/view-tests",
# book
"docs/book/project/ch02_getting_started",
"docs/book/project/ch03_building_ui",
"docs/book/project/ch04_reactivity",
]
exclude = ["benchmarks"]
exclude = ["benchmarks", "examples"]
[workspace.package]
version = "0.1.0-beta"
[workspace.dependencies]
leptos = { path = "./leptos", default-features = false, version = "0.1.0-beta" }
leptos_dom = { path = "./leptos_dom", default-features = false, version = "0.1.0-beta" }
leptos_macro = { path = "./leptos_macro", default-features = false, version = "0.1.0-beta" }
leptos_reactive = { path = "./leptos_reactive", default-features = false, version = "0.1.0-beta" }
leptos_server = { path = "./leptos_server", default-features = false, version = "0.1.0-beta" }
leptos_config = { path = "./leptos_config", default-features = false, version = "0.1.0-beta" }
leptos_router = { path = "./router", version = "0.1.0-beta" }
leptos_meta = { path = "./meta", default-feature = false, version = "0.1.0-beta" }
[profile.release]
codegen-units = 1
@@ -46,29 +42,4 @@ lto = true
opt-level = 'z'
[workspace.metadata.cargo-all-features]
skip_feature_sets = [
[
"csr",
"ssr",
],
[
"csr",
"hydrate",
],
[
"ssr",
"hydrate",
],
[
"serde",
"serde-lite",
],
[
"serde-lite",
"miniserde",
],
[
"serde",
"miniserde",
],
]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]

View File

@@ -8,7 +8,7 @@
default_to_workspace = false
[tasks.ci]
dependencies = ["build", "test"]
dependencies = ["build", "build-examples", "test"]
[tasks.build]
clear = true
@@ -19,6 +19,24 @@ command = "cargo"
args = ["+nightly", "build-all-features"]
install_crate = "cargo-all-features"
[tasks.build-examples]
clear = true
dependencies = [
{ name = "build", path = "examples/counter" },
{ name = "build", path = "examples/counter_isomorphic" },
{ name = "build", path = "examples/counters" },
{ name = "build", path = "examples/counters_stable" },
{ name = "build", path = "examples/fetch" },
{ name = "build", path = "examples/hackernews" },
{ name = "build", path = "examples/hackernews_axum" },
{ name = "build", path = "examples/parent_child" },
{ name = "build", path = "examples/router" },
{ name = "build", path = "examples/tailwind" },
{ name = "build", path = "examples/todo_app_sqlite" },
{ name = "build", path = "examples/todo_app_sqlite_axum" },
{ name = "build", path = "examples/todomvc" },
]
[tasks.test]
clear = true
dependencies = ["test-all"]

100
README.md
View File

@@ -1,6 +1,9 @@
**Please note:** This framework is in active development. I'm keeping it in a cycle of 0.0.x releases at the moment to indicate that its not even ready for its 0.1.0. Active work is being done on documentation and features, and APIs should not necessarily be considered stable. At the same time, it is more than a toy project or proof of concept, and I am actively using it for my own application development.
**NOTE: We're in the middle of merging changes and making fixes to support our upcoming `0.1.0` release. Some of the examples may be in a broken state. You can continue using the `0.0` releases with no issues.**
<img src="https://raw.githubusercontent.com/gbj/leptos/main/docs/logos/logo.svg" alt="Leptos Logo" style="width: 100%; height: auto; display: block; margin: auto;">
<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>
[![crates.io](https://img.shields.io/crates/v/leptos.svg)](https://crates.io/crates/leptos)
[![docs.rs](https://docs.rs/leptos/badge.svg)](https://docs.rs/leptos)
@@ -12,7 +15,7 @@
use leptos::*;
#[component]
pub fn SimpleCounter(cx: Scope, initial_value: i32) -> Element {
pub fn SimpleCounter(cx: Scope, initial_value: i32) -> impl IntoView {
// create a reactive signal with the initial value
let (value, set_value) = create_signal(cx, initial_value);
@@ -22,7 +25,7 @@ pub fn SimpleCounter(cx: Scope, initial_value: i32) -> Element {
let decrement = move |_| set_value.update(|value| *value -= 1);
let increment = move |_| set_value.update(|value| *value += 1);
// this JSX is compiled to an HTML template string for performance
// create user interfaces with the declarative `view!` macro
view! {
cx,
<div>
@@ -51,20 +54,9 @@ Leptos is a full-stack, isomorphic Rust web framework leveraging fine-grained re
- **Isomorphic**: Leptos provides primitives to write isomorphic server functions, i.e., functions that can be called with the “same shape” on the client or server, but only run on the server. This means you can write your server-only logic (database requests, authentication etc.) alongside the client-side components that will consume it, and call server functions as if they were running in the browser.
- **Web**: Leptos is built on the Web platform and Web standards. The router is designed to use Web fundamentals (like links and forms) and build on top of them rather than trying to replace them.
- **Framework**: Leptos provides most of what you need to build a modern web app: a reactive system, templating library, and a router that works on both the server and client side.
- **Fine-grained reactivity**: The entire framework is build from reactive primitives. This allows for extremely performant code with minimal overhead: when a reactive signals value changes, it can update a single text node, toggle a single class, or remove an element from the DOM without any other code running. (_So, no virtual DOM!_)
- **Fine-grained reactivity**: The entire framework is built from reactive primitives. This allows for extremely performant code with minimal overhead: when a reactive signals value changes, it can update a single text node, toggle a single class, or remove an element from the DOM without any other code running. (_So, no virtual DOM!_)
- **Declarative**: Tell Leptos how you want the page to look, and let the framework tell the browser how to do it.
## Getting Started
The best way to get started with a Leptos project right now is to use the [`cargo-leptos`](https://github.com/akesson/cargo-leptos) build tool and our [starter template](https://github.com/leptos-rs/start).
```bash
cargo install cargo-leptos
cargo leptos new --git https://github.com/leptos-rs/start
cd [your project name]
cargo leptos watch
```
## Learn more
Here are some resources for learning more about Leptos:
@@ -76,43 +68,34 @@ Here are some resources for learning more about Leptos:
## `nightly` Note
Most of the examples assume youre using `nightly` Rust. If youre on stable, note the following:
Most of the examples assume youre using `nightly` Rust.
1. You need to enable the `"stable"` flag in `Cargo.toml`: `leptos = { version = "0.0", features = ["stable"] }`
To set up your Rust toolchain using `nightly` (and add the ability to compile Rust to WebAssembly, if you havent already)
```
rustup toolchain install nightly
rustup default nightly
rustup target add wasm32-unknown-unknown
```
If youre on `stable`, note the following:
1. You need to enable the `"stable"` flag in `Cargo.toml`: `leptos = { version = "0.1.0-alpha", features = ["stable"] }`
2. `nightly` enables the function call syntax for accessing and setting signals. If youre using `stable`,
youll just call `.get()`, `.set()`, or `.update()` manually. Check out the
[`counters-stable` example](https://github.com/gbj/leptos/blob/main/examples/counters-stable/src/main.rs)
for examples of the correct API.
## Benchmarks
## `cargo-leptos`
### Server-Side Rendering
[`cargo-leptos`](https://github.com/akesson/cargo-leptos) is a build tool that's designed to make it easy to build apps that run on both the client and the server, with seamless integration. The best way to get started with a real Leptos project right now is to use `cargo-leptos` and our [starter template](https://github.com/leptos-rs/start).
Ive created a benchmark comparing Leptoss HTML rendering on the server to [Tera](https://github.com/Keats/tera), [Yew](https://github.com/yewstack/yew), and [Sycamore](https://github.com/sycamore-rs/sycamore). You can find the benchmark [here](https://github.com/gbj/leptos/tree/main/benchmarks) and run it yourself using `cargo bench`. Leptos renders HTML roughly as fast as Tera, and scales well as templates become larger. It's significantly faster than the server-side HTML rendering done by similar frameworks.
<details>
<summary>Click to show results</summary>
<table>
<thead>
<tr><td><em>ns/iter</em></td><td>Tera</td><td>Leptos</td><td>Yew</td><td>Sycamore</td></tr>
</thead>
<tbody>
<tr><td>3 Counters</td><td align="right">3,454</td><td align="right">5,666</td><td align="right">34,984</td><td align="right">32,412</td></tr>
<tr><td>TodoMVC (no todos)</td><td align="right">2,396</td><td align="right">5,561</td><td align="right">38,725</td><td align="right">68,749</td></tr>
<tr><td>TodoMVC (1000 todos)</td><td align="right">3,829,447</td><td align="right">3,077,907</td><td align="right">5,125,639</td><td align="right">19,448,900</td></tr>
<tr><td><em>Average</em></td><td align="right">1.08</td><td align="right">1.65</td><td align="right">6.25</td><td align="right">9.36</td></tr>
</tbody>
</table>
</details>
### Client-Side Rendering
The gold standard for testing raw rendering performance for front-end web frameworks is the [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark). The official results list Leptos as the fastest Rust/Wasm framework, slightly slower than SolidJS and significantly faster than popular JS frameworks like Svelte, Preact, and React.
<details>
<summary>Click to show results</summary>
<img width="913" alt="js-framework-benchmark results" src="https://user-images.githubusercontent.com/286622/198388168-d21e938b-5d59-4000-b373-91b48f1ec4d3.png">
</details>
```bash
cargo install cargo-leptos
cargo leptos new --git https://github.com/leptos-rs/start
cd [your project name]
cargo leptos watch
```
## FAQs
@@ -133,7 +116,7 @@ On the surface level, these libraries may seem similar. Yew is, of course, the m
- **VDOM vs. fine-grained:** Yew is built on the virtual DOM (VDOM) model: state changes cause components to re-render, generating a new virtual DOM tree. Yew diffs this against the previous VDOM, and applies those patches to the actual DOM. Component functions rerun whenever state changes. Leptos takes an entirely different approach. Components run once, creating (and returning) actual DOM nodes and setting up a reactive system to update those DOM nodes.
- **Performance:** This has huge performance implications: Leptos is simply _much_ faster at both creating and updating the UI than Yew is.
- **Mental model:** Adopting fine-grained reactivity also tends to simplify the mental model. There are no surprising components re-renders because there are no re-renders. Your app can be divided into components based on what makes sense for your app, because they have no performance implications.
- **Mental model:** Adopting fine-grained reactivity also tends to simplify the mental model. There are no surprising component re-renders because there are no re-renders. Your app can be divided into components based on what makes sense for your app, because they have no performance implications.
### How is this different from Sycamore?
@@ -147,17 +130,16 @@ There are some practical differences that make a significant difference:
- **Read-write segregation:** Leptos, like Solid, encourages read-write segregation between signal getters and setters, so you end up accessing signals with tuples like `let (count, set_count) = create_signal(cx, 0);` _(If you prefer or if it's more convenient for your API, you can use `create_rw_signal` to give a unified read/write signal.)_
- **Signals are functions:** In Leptos, you can call a signal to access it rather than calling a specific method (so, `count()` instead of `count.get()`) This creates a more consistent mental model: accessing a reactive value is always a matter of calling a function. For example:
```rust
let (count, set_count) = create_signal(cx, 0); // a signal
let double_count = move || count() * 2; // a derived signal
let memoized_count = create_memo(cx, move |_| count() * 3); // a memo
// all are accessed by calling them
assert_eq!(count(), 0);
assert_eq!(double_count(), 0);
assert_eq!(memoized_count(), 0);
```rust
let (count, set_count) = create_signal(cx, 0); // a signal
let double_count = move || count() * 2; // a derived signal
let memoized_count = create_memo(cx, move |_| count() * 3); // a memo
// all are accessed by calling them
assert_eq!(count(), 0);
assert_eq!(double_count(), 0);
assert_eq!(memoized_count(), 0);
// this function can accept any of those signals
fn do_work_on_signal(my_signal: impl Fn() -> i32) { ... }
```
// this function can accept any of those signals
fn do_work_on_signal(my_signal: impl Fn() -> i32) { ... }
```
- **Signals and scopes are `'static`:** Both Leptos and Sycamore ease the pain of moving signals in closures (in particular, event listeners) by making them `Copy`, to avoid the `{ let count = count.clone(); move |_| ... }` that's very familiar in Rust UI code. Sycamore does this by using bump allocation to tie the lifetimes of its signals to its scopes: since references are `Copy`, `&'a Signal<T>` can be moved into a closure. Leptos does this by using arena allocation and passing around indices: types like `ReadSignal<T>`, `WriteSignal<T>`, and `Memo<T>` are actually wrapper for indices into an arena. This means that both scopes and signals are both `Copy` and `'static` in Leptos, which means that they can be moved easily into closures without adding lifetime complexity.
- **Signals and scopes are `'static`:** Both Leptos and Sycamore ease the pain of moving signals in closures (in particular, event listeners) by making them `Copy`, to avoid the `{ let count = count.clone(); move |_| ... }` that's very familiar in Rust UI code. Sycamore does this by using bump allocation to tie the lifetimes of its signals to its scopes: since references are `Copy`, `&'a Signal<T>` can be moved into a closure. Leptos does this by using arena allocation and passing around indices: types like `ReadSignal<T>`, `WriteSignal<T>`, and `Memo<T>` are actually wrappers for indices into an arena. This means that both scopes and signals are both `Copy` and `'static` in Leptos, which means that they can be moved easily into closures without adding lifetime complexity.

View File

@@ -2,12 +2,12 @@ use test::Bencher;
#[bench]
fn leptos_ssr_bench(b: &mut Bencher) {
use leptos::*;
b.iter(|| {
use leptos::*;
_ = create_scope(create_runtime(), |cx| {
#[component]
fn Counter(cx: Scope, initial: i32) -> Element {
fn Counter(cx: Scope, initial: i32) -> impl IntoView {
let (value, set_value) = create_signal(cx, initial);
view! {
cx,
@@ -28,16 +28,16 @@ fn leptos_ssr_bench(b: &mut Bencher) {
<Counter initial=2/>
<Counter initial=3/>
</main>
};
}.into_view(cx).render_to_string(cx);
assert_eq!(
rendered,
"<main data-hk=\"0-0\"><h1>Welcome to our benchmark page.</h1><p>Here's some introductory text.</p><!--#--><div data-hk=\"0-2-0\"><button>-1</button><span>Value: <!--#-->1<!--/-->!</span><button>+1</button></div><!--/--><!--#--><div data-hk=\"0-3-0\"><button>-1</button><span>Value: <!--#-->2<!--/-->!</span><button>+1</button></div><!--/--><!--#--><div data-hk=\"0-4-0\"><button>-1</button><span>Value: <!--#-->3<!--/-->!</span><button>+1</button></div><!--/--></main>"
"<main><h1>Welcome to our benchmark page.</h1><p>Here's some introductory text.</p><div><button>-1</button><span>Value: <!>1<template id=\"_3\"></template>!</span><button>+1</button></div><template id=\"_1\"></template><div><button>-1</button><span>Value: <!>2<template id=\"_2\"></template>!</span><button>+1</button></div><template id=\"_0\"></template><div><button>-1</button><span>Value: <!>3<template id=\"_2\"></template>!</span><button>+1</button></div><template id=\"_0\"></template></main>"
);
});
});
}
/*
#[bench]
fn tera_ssr_bench(b: &mut Bencher) {
use tera::*;
@@ -194,3 +194,4 @@ fn yew_ssr_bench(b: &mut Bencher) {
});
});
}
*/

View File

@@ -1,4 +1,4 @@
use leptos::*;
pub use leptos::*;
use miniserde::*;
use web_sys::HtmlInputElement;
@@ -8,314 +8,320 @@ pub struct Todos(pub Vec<Todo>);
const STORAGE_KEY: &str = "todos-leptos";
impl Todos {
pub fn new(cx: Scope) -> Self {
Self(vec![])
}
pub fn new(cx: Scope) -> Self {
Self(vec![])
}
pub fn new_with_1000(cx: Scope) -> Self {
let todos = (0..1000)
.map(|id| Todo::new(cx, id, format!("Todo #{id}")))
.collect();
Self(todos)
}
pub fn new_with_1000(cx: Scope) -> Self {
let todos = (0..1000)
.map(|id| Todo::new(cx, id, format!("Todo #{id}")))
.collect();
Self(todos)
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn add(&mut self, todo: Todo) {
self.0.push(todo);
}
pub fn add(&mut self, todo: Todo) {
self.0.push(todo);
}
pub fn remove(&mut self, id: usize) {
self.0.retain(|todo| todo.id != id);
}
pub fn remove(&mut self, id: usize) {
self.0.retain(|todo| todo.id != id);
}
pub fn remaining(&self) -> usize {
self.0.iter().filter(|todo| !(todo.completed)()).count()
}
pub fn remaining(&self) -> usize {
self.0.iter().filter(|todo| !(todo.completed)()).count()
}
pub fn completed(&self) -> usize {
self.0.iter().filter(|todo| (todo.completed)()).count()
}
pub fn completed(&self) -> usize {
self.0.iter().filter(|todo| (todo.completed)()).count()
}
pub fn toggle_all(&self) {
// if all are complete, mark them all active instead
if self.remaining() == 0 {
for todo in &self.0 {
if todo.completed.get() {
(todo.set_completed)(false);
}
}
}
// otherwise, mark them all complete
else {
for todo in &self.0 {
(todo.set_completed)(true);
}
pub fn toggle_all(&self) {
// if all are complete, mark them all active instead
if self.remaining() == 0 {
for todo in &self.0 {
if todo.completed.get() {
(todo.set_completed)(false);
}
}
}
// otherwise, mark them all complete
else {
for todo in &self.0 {
(todo.set_completed)(true);
}
}
}
fn clear_completed(&mut self) {
self.0.retain(|todo| !todo.completed.get());
}
fn clear_completed(&mut self) {
self.0.retain(|todo| !todo.completed.get());
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Todo {
pub id: usize,
pub title: ReadSignal<String>,
pub set_title: WriteSignal<String>,
pub completed: ReadSignal<bool>,
pub set_completed: WriteSignal<bool>,
pub id: usize,
pub title: ReadSignal<String>,
pub set_title: WriteSignal<String>,
pub completed: ReadSignal<bool>,
pub set_completed: WriteSignal<bool>,
}
impl Todo {
pub fn new(cx: Scope, id: usize, title: String) -> Self {
Self::new_with_completed(cx, id, title, false)
}
pub fn new(cx: Scope, id: usize, title: String) -> Self {
Self::new_with_completed(cx, id, title, false)
}
pub fn new_with_completed(cx: Scope, id: usize, title: String, completed: bool) -> Self {
let (title, set_title) = create_signal(cx, title);
let (completed, set_completed) = create_signal(cx, completed);
Self {
id,
title,
set_title,
completed,
set_completed,
}
pub fn new_with_completed(
cx: Scope,
id: usize,
title: String,
completed: bool,
) -> Self {
let (title, set_title) = create_signal(cx, title);
let (completed, set_completed) = create_signal(cx, completed);
Self {
id,
title,
set_title,
completed,
set_completed,
}
}
pub fn toggle(&self) {
self.set_completed
.update(|completed| *completed = !*completed);
}
pub fn toggle(&self) {
self
.set_completed
.update(|completed| *completed = !*completed);
}
}
const ESCAPE_KEY: u32 = 27;
const ENTER_KEY: u32 = 13;
#[component]
pub fn TodoMVC(cx: Scope, todos: Todos) -> Element {
let mut next_id = todos
pub fn TodoMVC(cx: Scope,todos: Todos) -> impl IntoView {
let mut next_id = todos
.0
.iter()
.map(|todo| todo.id)
.max()
.map(|last| last + 1)
.unwrap_or(0);
let (todos, set_todos) = create_signal(cx, todos);
provide_context(cx, set_todos);
let (mode, set_mode) = create_signal(cx, Mode::All);
window_event_listener("hashchange", move |_| {
let new_mode = location_hash().map(|hash| route(&hash)).unwrap_or_default();
set_mode(new_mode);
});
let add_todo = move |ev: web_sys::KeyboardEvent| {
let target = event_target::<HtmlInputElement>(&ev);
ev.stop_propagation();
let key_code = ev.unchecked_ref::<web_sys::KeyboardEvent>().key_code();
if key_code == ENTER_KEY {
let title = event_target_value(&ev);
let title = title.trim();
if !title.is_empty() {
let new = Todo::new(cx, next_id, title.to_string());
set_todos.update(|t| t.add(new));
next_id += 1;
target.set_value("");
}
}
};
let filtered_todos = create_memo::<Vec<Todo>>(cx, move |_| {
todos.with(|todos| match mode.get() {
Mode::All => todos.0.to_vec(),
Mode::Active => todos
.0
.iter()
.map(|todo| todo.id)
.max()
.map(|last| last + 1)
.unwrap_or(0);
.filter(|todo| !todo.completed.get())
.cloned()
.collect(),
Mode::Completed => todos
.0
.iter()
.filter(|todo| todo.completed.get())
.cloned()
.collect(),
})
});
let (todos, set_todos) = create_signal(cx, todos);
provide_context(cx, set_todos);
let (mode, set_mode) = create_signal(cx, Mode::All);
window_event_listener("hashchange", move |_| {
let new_mode = location_hash().map(|hash| route(&hash)).unwrap_or_default();
set_mode(new_mode);
});
let add_todo = move |ev: web_sys::KeyboardEvent| {
let target = event_target::<HtmlInputElement>(&ev);
ev.stop_propagation();
let key_code = ev.unchecked_ref::<web_sys::KeyboardEvent>().key_code();
if key_code == ENTER_KEY {
let title = event_target_value(&ev);
let title = title.trim();
if !title.is_empty() {
let new = Todo::new(cx, next_id, title.to_string());
set_todos.update(|t| t.add(new));
next_id += 1;
target.set_value("");
}
}
};
let filtered_todos = create_memo::<Vec<Todo>>(cx, move |_| {
todos.with(|todos| match mode.get() {
Mode::All => todos.0.to_vec(),
Mode::Active => todos
.0
.iter()
.filter(|todo| !todo.completed.get())
.cloned()
.collect(),
Mode::Completed => todos
.0
.iter()
.filter(|todo| todo.completed.get())
.cloned()
.collect(),
})
});
// effect to serialize to JSON
// this does reactive reads, so it will automatically serialize on any relevant change
create_effect(cx, move |_| {
if let Ok(Some(storage)) = window().local_storage() {
let objs = todos
.get()
.0
.iter()
.map(TodoSerialized::from)
.collect::<Vec<_>>();
let json = json::to_string(&objs);
if storage.set_item(STORAGE_KEY, &json).is_err() {
log::error!("error while trying to set item in localStorage");
}
}
});
view! { cx,
<main>
<section class="todoapp">
<header class="header">
<h1>"todos"</h1>
<input class="new-todo" placeholder="What needs to be done?" autofocus on:keydown=add_todo />
</header>
<section class="main" class:hidden={move || todos.with(|t| t.is_empty())}>
<input id="toggle-all" class="toggle-all" type="checkbox"
prop:checked={move || todos.with(|t| t.remaining() > 0)}
on:input=move |_| set_todos.update(|t| t.toggle_all())
/>
<label for="toggle-all">"Mark all as complete"</label>
<ul class="todo-list">
<For each=filtered_todos key=|todo| todo.id>
{move |cx, todo: &Todo| view! { cx, <Todo todo=todo.clone() /> }}
</For>
</ul>
</section>
<footer class="footer" class:hidden={move || todos.with(|t| t.is_empty())}>
<span class="todo-count">
<strong>{move || todos.with(|t| t.remaining().to_string())}</strong>
{move || if todos.with(|t| t.remaining()) == 1 {
" item"
} else {
" items"
}}
" left"
</span>
<ul class="filters">
<li><a href="#/" class="selected" class:selected={move || mode() == Mode::All}>"All"</a></li>
<li><a href="#/active" class:selected={move || mode() == Mode::Active}>"Active"</a></li>
<li><a href="#/completed" class:selected={move || mode() == Mode::Completed}>"Completed"</a></li>
</ul>
<button
class="clear-completed hidden"
class:hidden={move || todos.with(|t| t.completed() == 0)}
on:click=move |_| set_todos.update(|t| t.clear_completed())
>
"Clear completed"
</button>
</footer>
</section>
<footer class="info">
<p>"Double-click to edit a todo"</p>
<p>"Created by "<a href="http://todomvc.com">"Greg Johnston"</a></p>
<p>"Part of "<a href="http://todomvc.com">"TodoMVC"</a></p>
</footer>
</main>
// effect to serialize to JSON
// this does reactive reads, so it will automatically serialize on any relevant change
create_effect(cx, move |_| {
if let Ok(Some(storage)) = window().local_storage() {
let objs = todos
.get()
.0
.iter()
.map(TodoSerialized::from)
.collect::<Vec<_>>();
let json = json::to_string(&objs);
if storage.set_item(STORAGE_KEY, &json).is_err() {
log::error!("error while trying to set item in localStorage");
}
}
});
view! { cx,
<main>
<section class="todoapp">
<header class="header">
<h1>"todos"</h1>
<input class="new-todo" placeholder="What needs to be done?" autofocus="" on:keydown=add_todo />
</header>
<section class="main" class:hidden={move || todos.with(|t| t.is_empty())}>
<input id="toggle-all" class="toggle-all" type="checkbox"
prop:checked={move || todos.with(|t| t.remaining() > 0)}
on:input=move |_| set_todos.update(|t| t.toggle_all())
/>
<label for="toggle-all">"Mark all as complete"</label>
<ul class="todo-list">
<For
each=filtered_todos
key=|todo| todo.id
view=move |todo: Todo| view! { cx, <Todo todo=todo.clone() /> }
/>
</ul>
</section>
<footer class="footer" class:hidden={move || todos.with(|t| t.is_empty())}>
<span class="todo-count">
<strong>{move || todos.with(|t| t.remaining().to_string())}</strong>
{move || if todos.with(|t| t.remaining()) == 1 {
" item"
} else {
" items"
}}
" left"
</span>
<ul class="filters">
<li><a href="#/" class="selected" class:selected={move || mode() == Mode::All}>"All"</a></li>
<li><a href="#/active" class:selected={move || mode() == Mode::Active}>"Active"</a></li>
<li><a href="#/completed" class:selected={move || mode() == Mode::Completed}>"Completed"</a></li>
</ul>
<button
class="clear-completed hidden"
class:hidden={move || todos.with(|t| t.completed() == 0)}
on:click=move |_| set_todos.update(|t| t.clear_completed())
>
"Clear completed"
</button>
</footer>
</section>
<footer class="info">
<p>"Double-click to edit a todo"</p>
<p>"Created by "<a href="http://todomvc.com">"Greg Johnston"</a></p>
<p>"Part of "<a href="http://todomvc.com">"TodoMVC"</a></p>
</footer>
</main>
}.into_view(cx)
}
#[component]
pub fn Todo(cx: Scope, todo: Todo) -> Element {
let (editing, set_editing) = create_signal(cx, false);
let set_todos = use_context::<WriteSignal<Todos>>(cx).unwrap();
let input = NodeRef::new(cx);
pub fn Todo(cx: Scope, todo: Todo) -> impl IntoView {
let (editing, set_editing) = create_signal(cx, false);
let set_todos = use_context::<WriteSignal<Todos>>(cx).unwrap();
//let input = NodeRef::new(cx);
let save = move |value: &str| {
let value = value.trim();
if value.is_empty() {
set_todos.update(|t| t.remove(todo.id));
} else {
(todo.set_title)(value.to_string());
}
set_editing(false);
};
let save = move |value: &str| {
let value = value.trim();
if value.is_empty() {
set_todos.update(|t| t.remove(todo.id));
} else {
(todo.set_title)(value.to_string());
}
set_editing(false);
};
let tpl = view! { cx,
<li
class="todo"
class:editing={editing}
class:completed={move || (todo.completed)()}
_ref=input
>
<div class="view">
<input
class="toggle"
type="checkbox"
prop:checked={move || (todo.completed)()}
view! { cx,
<li
class="todo"
class:editing={editing}
class:completed={move || (todo.completed)()}
//_ref=input
>
<div class="view">
<input
class="toggle"
type="checkbox"
prop:checked={move || (todo.completed)()}
/>
<label on:dblclick=move |_| set_editing(true)>
{move || todo.title.get()}
</label>
<button class="destroy" on:click=move |_| set_todos.update(|t| t.remove(todo.id))/>
</div>
{move || editing().then(|| view! { cx,
<input
class="edit"
class:hidden={move || !(editing)()}
prop:value={move || todo.title.get()}
on:focusout=move |ev| save(&event_target_value(&ev))
on:keyup={move |ev| {
let key_code = ev.unchecked_ref::<web_sys::KeyboardEvent>().key_code();
if key_code == ENTER_KEY {
save(&event_target_value(&ev));
} else if key_code == ESCAPE_KEY {
set_editing(false);
}
}}
/>
})
}
</li>
};
tpl
/>
<label on:dblclick=move |_| set_editing(true)>
{move || todo.title.get()}
</label>
<button class="destroy" on:click=move |_| set_todos.update(|t| t.remove(todo.id))/>
</div>
{move || editing().then(|| view! { cx,
<input
class="edit"
class:hidden={move || !(editing)()}
prop:value={move || todo.title.get()}
on:focusout=move |ev| save(&event_target_value(&ev))
on:keyup={move |ev| {
let key_code = ev.unchecked_ref::<web_sys::KeyboardEvent>().key_code();
if key_code == ENTER_KEY {
save(&event_target_value(&ev));
} else if key_code == ESCAPE_KEY {
set_editing(false);
}
}}
/>
})
}
</li>
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mode {
Active,
Completed,
All,
Active,
Completed,
All,
}
impl Default for Mode {
fn default() -> Self {
Mode::All
}
fn default() -> Self {
Mode::All
}
}
pub fn route(hash: &str) -> Mode {
match hash {
"/active" => Mode::Active,
"/completed" => Mode::Completed,
_ => Mode::All,
}
match hash {
"/active" => Mode::Active,
"/completed" => Mode::Completed,
_ => Mode::All,
}
}
#[derive(Serialize, Deserialize)]
pub struct TodoSerialized {
pub id: usize,
pub title: String,
pub completed: bool,
pub id: usize,
pub title: String,
pub completed: bool,
}
impl TodoSerialized {
pub fn into_todo(self, cx: Scope) -> Todo {
Todo::new_with_completed(cx, self.id, self.title, self.completed)
}
pub fn into_todo(self, cx: Scope) -> Todo {
Todo::new_with_completed(cx, self.id, self.title, self.completed)
}
}
impl From<&Todo> for TodoSerialized {
fn from(todo: &Todo) -> Self {
Self {
id: todo.id,
title: todo.title.get(),
completed: (todo.completed)(),
}
fn from(todo: &Todo) -> Self {
Self {
id: todo.id,
title: todo.title.get(),
completed: (todo.completed)(),
}
}
}

View File

@@ -7,15 +7,14 @@ mod yew;
#[bench]
fn leptos_todomvc_ssr(b: &mut Bencher) {
use self::leptos::*;
use ::leptos::*;
b.iter(|| {
use crate::todomvc::leptos::*;
_ = create_scope(create_runtime(), |cx| {
let rendered = view! {
cx,
<TodoMVC todos=Todos::new(cx)/>
};
}.into_view(cx).render_to_string(cx);
assert!(rendered.len() > 1);
});
@@ -59,15 +58,15 @@ fn yew_todomvc_ssr(b: &mut Bencher) {
#[bench]
fn leptos_todomvc_ssr_with_1000(b: &mut Bencher) {
use self::leptos::*;
use ::leptos::*;
b.iter(|| {
use self::leptos::*;
use ::leptos::*;
_ = create_scope(create_runtime(), |cx| {
let rendered = view! {
cx,
<TodoMVC todos=Todos::new_with_1000(cx)/>
};
}.into_view(cx).render_to_string(cx);
assert!(rendered.len() > 1);
});

View File

@@ -10,7 +10,7 @@ This document is intended as a running list of common issues, with example code
```rust
let (a, set_a) = create_signal(cx, 0);
let (b, set_a) = create_signal(cx, false);
let (b, set_b) = create_signal(cx, false);
create_effect(cx, move |_| {
if a() > 5 {

View File

@@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../../../leptos" }
leptos = "0.0.18"

View File

@@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../../../leptos" }
leptos = "0.0.18"

View File

@@ -4,7 +4,7 @@ fn main() {
mount_to_body(|cx| {
let name = "gbj";
let userid = 0;
let _input_element = NodeRef::new(cx);
let _input_element: Element;
view! {
cx,

View File

@@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies]
leptos = { path = "../../../../leptos" }
leptos = "0.0.18"

BIN
docs/logos/Leptos_logo_RGB.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

64
docs/logos/Leptos_logo_RGB.svg Executable file
View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 437.4294 209.6185" style="enable-background:new 0 0 437.4294 209.6185;" xml:space="preserve">
<path style="fill:none;" d="M130.0327,79.3931c-11.4854-0.23-22.52,9.3486-24.5034,21.0117l49.1157,0.0293
c-2.1729-10.418-11.1821-21.0449-24.1987-21.0449C130.3081,79.3892,130.1714,79.3907,130.0327,79.3931z"/>
<path style="fill:#181139;" d="M95.1109,128.1089H58.6797V65.6861c0-1.5234-0.8169-2.4331-2.1855-2.4331h-3.1187
c-1.3159,0-2.2349,1.0005-2.2349,2.4331v67.4297c0,1.4521,0.8145,2.2852,2.2349,2.2852h41.7353c1.4844,0,2.4819-0.9375,2.4819-2.333
v-2.7744C97.5928,128.9253,96.6651,128.1089,95.1109,128.1089z"/>
<path style="fill:#181139;" d="M146.4561,77.1739c-4.8252-3.001-10.3037-4.5249-16.2837-4.5288c-0.0068,0-0.0137,0-0.0205,0
c-5.7349,0-11.1377,1.4639-16.0566,4.3511c-4.916,2.8853-8.8721,6.8364-11.7593,11.7456
c-2.8975,4.9248-4.3687,10.332-4.3721,16.0713c-0.0034,5.7188,1.4966,11.0654,4.4565,15.8887
c2.9893,4.9209,6.8789,8.7334,11.8887,11.6514c4.8657,2.8633,10.2397,4.3174,15.9717,4.3203c0.0073,0,0.0146,0,0.022,0
c8.123,0,14.7441-2.5869,21.4683-8.3906c0.5493-0.4805,0.8516-1.1201,0.8516-1.8008c0.001-0.6074-0.1743-1.1035-0.5205-1.4756
l-1.3569-1.8428l-0.0732-0.0859c-0.2637-0.2637-0.6929-0.6152-1.3716-0.6152c-0.6421,0-1.2549,0.2217-1.7124,0.6143
c-1.9346,1.585-3.5459,2.8008-4.7969,3.6182c-1.7979,1.208-5.8218,3.2314-12.5986,3.2314c-0.0073,0-0.0142,0-0.021,0
c-0.1357,0.0029-0.269,0.0039-0.4043,0.0039c-12.2642,0-23.4736-10.3262-24.5088-22.4814l53.0127,0.0322c0.0015,0,0.0024,0,0.0034,0
c2.2373,0,3.4697-1.1621,3.4712-3.2715c0.0034-5.2588-1.3574-10.3945-4.0464-15.2705
C155.0015,84.0953,151.2188,80.1363,146.4561,77.1739z M154.6451,100.4341l-49.1157-0.0293
c1.9834-11.6631,13.0181-21.2417,24.5034-21.0117c0.1387-0.0024,0.2754-0.0039,0.4136-0.0039
C143.4629,79.3892,152.4722,90.0162,154.6451,100.4341z"/>
<path style="fill:#181139;" d="M204.0386,136.6382c5.7319,0,11.1069-1.4502,15.9746-4.3115
c4.938-2.9014,8.75-6.7129,11.6533-11.6533c2.8608-4.8672,4.311-10.2578,4.311-16.0244c0-5.7324-1.4502-11.1064-4.311-15.9746
c-2.9019-4.9385-6.7134-8.75-11.6533-11.6533c-4.8687-2.8618-10.2437-4.3125-15.9746-4.3125
c-9.938,0-19.2021,4.7583-24.3516,12.3174v-9.438c0-0.5946-0.1465-1.0788-0.411-1.4511c-0.3815-0.5369-1.0157-0.834-1.8727-0.834
h-2.6738c-1.4521,0-2.2852,0.833-2.2852,2.2852v5.6964v46.4791v23.9676c0,1.2568,0.7808,2.0371,2.0371,2.0371h3.3667
c0.9209,0,1.6421-0.6992,1.6421-1.5908v-17.098v-10.984C185.0884,131.8892,194.2749,136.6382,204.0386,136.6382z M186.6358,122.5591
c-4.9346-4.9346-7.6831-11.4932-7.542-18.0254c-0.1367-6.3506,2.5439-12.751,7.3545-17.5605
c4.8521-4.8521,11.3037-7.5547,17.7383-7.417c4.3691,0,8.4863,1.1465,12.2314,3.4043c3.7344,2.2979,6.7456,5.4053,8.9492,9.2354
c2.1699,3.9072,3.2695,8.0967,3.2695,12.4697c0.1396,6.4619-2.5967,12.9844-7.5083,17.8955
c-4.7617,4.7617-11.0469,7.3857-17.2544,7.2803C197.6856,129.9712,191.396,127.3208,186.6358,122.5591z"/>
<path style="fill:#181139;" d="M241.8955,80.3975h7.5669v42.0259c0,6.8174,4.5674,12.1309,11.0825,12.9189
c0.6836,0.1055,1.8379,0.1572,3.5303,0.1572c2.0078,0,3.0273-0.3535,3.0273-2.2842v-2.377c0-1.7891-1.334-2.0371-2.7568-2.0371
c0,0-0.001,0-0.002,0l-1.7871-0.0488c-2.0117-0.0439-3.4883-0.7627-4.3896-2.1367c-0.9697-1.4805-1.4619-3.1738-1.4619-5.0352
V80.3975h10.0928c1.3076,0,2.2852-1.3628,2.2852-2.5815v-1.9312c0-1.3999-0.8359-2.2354-2.2354-2.2354h-10.1426V60.6861
c0-1.4619-0.7969-2.4829-1.9375-2.4829c-0.1865,0-0.4121,0-0.6392,0.0884l-2.6489,0.6865
c-1.2109,0.3682-2.0171,0.9263-2.0171,2.4507v12.2207h-7.5669c-1.4185,0-2.335,0.897-2.335,2.2852v1.8813
C239.5606,79.2393,240.6079,80.3975,241.8955,80.3975z"/>
<path style="fill:#181139;" d="M379.1182,106.2691c-4.0488-2.9219-8.8545-5.0293-14.291-6.2646
c-6.5049-1.3975-13.4473-5.2129-13.3203-10.3066c0-7.5225,6.6367-10.1914,12.3203-10.1914c5.3574,0,10.2207,3.002,13.001,8.0146
c0.6729,1.2861,1.4785,1.9375,2.3955,1.9375c0.3311,0,0.7061-0.1113,0.9922-0.2832l2.2021-1.1523
c0.5947-0.3408,0.9229-0.9414,0.9229-1.6924c0-0.5205-0.0908-0.9541-0.2617-1.292c-3.6367-8.2466-10.0967-12.4282-19.2021-12.4282
c-11.7305,0-19.6123,6.9263-19.6123,17.2349c0,4.3125,1.8438,7.9746,5.4756,10.8809c3.4482,2.7979,7.9121,4.8623,13.2705,6.1377
c4.5859,1.085,8.3193,2.5654,11.0977,4.4023c1.4159,0.9354,2.4412,2.0535,3.106,3.3672c0.6053,1.1962,0.9135,2.5535,0.9135,4.1005
c0.0742,2.3857-0.79,4.5176-2.5684,6.3389c-3.1445,3.2178-8.4053,4.6689-12.0205,4.6689c-0.0361,0-0.0723,0-0.1074,0
c-3.4268,0-6.4893-0.8438-9.1035-2.5068c-2.5918-1.6484-4.2363-3.8076-5.0293-6.6064c-0.3203-1.0996-0.751-2.1738-2.1553-2.1738
c-0.0742,0-0.2109,0.0146-0.4062,0.0449c-0.1133,0.0166-0.2559,0.0381-0.5088,0.0742l-1.8818,0.4463l-0.1045,0.0332
c-1.0244,0.4082-1.6113,1.1846-1.6113,2.1309c0,0.2285,0.0625,0.6592,0.2178,1.1094c1.9707,8.5801,10.2432,14.3447,20.5732,14.3447
c0.125,0.002,0.249,0.002,0.374,0.002c6.5947,0,12.6748-2.3193,16.7275-6.3945c3.1895-3.208,4.8311-7.2363,4.748-11.6357
c0-2.8187-0.6185-5.3109-1.8062-7.481C382.4437,109.2624,381.0062,107.631,379.1182,106.2691z"/>
<path style="fill:#EF3939;" d="M348.9043,45.7325c0-6.3157-3.2826-11.8699-8.2238-15.0756
c-2.811-1.8237-6.1537-2.8947-9.7469-2.8947c-9.9092,0-17.9707,8.0615-17.9707,17.9702c0,4.7659,1.8775,9.0925,4.9157,12.3123
c-3.6619,4.3709-6.6334,9.3336-8.7663,14.7186c-1.5873-0.2422-3.2123-0.3683-4.8662-0.3683
c-17.7158,0-32.1289,14.4131-32.1289,32.1289c0,14.6854,9.9077,27.0922,23.3869,30.9101
c-6.7762,17.3461-23.6572,29.6719-43.3742,29.6719c-16.8195,0-31.583-8.9662-39.7656-22.369
c-2.4778,0.5446-5.0429,0.8519-7.6721,0.9023c9.0226,16.99,26.8969,28.5917,47.4377,28.5917
c23.2646,0,43.1121-14.8788,50.5461-35.6179c0.5204,0.0251,1.0435,0.0398,1.5701,0.0398c17.7158,0,32.1289-14.4131,32.1289-32.1289
c0-13.557-8.4446-25.1712-20.3465-29.8811c1.9001-4.5678,4.5115-8.7646,7.6888-12.4641c0.9996,0.4404,2.0479,0.785,3.1324,1.0384
c1.3144,0.3071,2.6773,0.486,4.0839,0.486C340.8428,63.7032,348.9043,55.6416,348.9043,45.7325z M304.2461,129.5279
c-13.7871,0-25.0039-11.2168-25.0039-25.0039s11.2168-25.0039,25.0039-25.0039S329.25,90.7369,329.25,104.524
S318.0332,129.5279,304.2461,129.5279z M330.9336,34.8872c0.645,0,1.2737,0.0671,1.8881,0.1755
c5.0818,0.8974,8.9576,5.3347,8.9576,10.6697c0,5.9805-4.8652,10.8457-10.8457,10.8457s-10.8457-4.8652-10.8457-10.8457
c0-1.3967,0.2746-2.7282,0.7576-3.9555C322.4306,37.7496,326.35,34.8872,330.9336,34.8872z"/>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 437.4294 209.6185" style="enable-background:new 0 0 437.4294 209.6185;" xml:space="preserve">
<path d="M95.1109,128.1089H58.6797V65.6861c0-1.5234-0.8169-2.4331-2.1855-2.4331h-3.1187c-1.3159,0-2.2349,1.0005-2.2349,2.4331
v67.4297c0,1.4521,0.8145,2.2852,2.2349,2.2852h41.7353c1.4844,0,2.4819-0.9375,2.4819-2.333v-2.7744
C97.5928,128.9253,96.6651,128.1089,95.1109,128.1089z"/>
<path d="M146.4561,77.1739c-4.8252-3.001-10.3037-4.5249-16.2837-4.5288c-0.0068,0-0.0137,0-0.0205,0
c-5.7349,0-11.1377,1.4639-16.0566,4.3511c-4.916,2.8853-8.8721,6.8364-11.7593,11.7456
c-2.8975,4.9248-4.3687,10.332-4.3721,16.0713c-0.0034,5.7188,1.4966,11.0654,4.4565,15.8887
c2.9893,4.9209,6.8789,8.7334,11.8887,11.6514c4.8657,2.8633,10.2397,4.3174,15.9717,4.3203c0.0073,0,0.0146,0,0.022,0
c8.123,0,14.7441-2.5869,21.4683-8.3906c0.5493-0.4805,0.8516-1.1201,0.8516-1.8008c0.001-0.6074-0.1743-1.1035-0.5205-1.4756
l-1.3569-1.8428l-0.0732-0.0859c-0.2637-0.2637-0.6929-0.6152-1.3716-0.6152c-0.6421,0-1.2549,0.2217-1.7124,0.6143
c-1.9346,1.585-3.5459,2.8008-4.7969,3.6182c-1.7979,1.208-5.8218,3.2314-12.5986,3.2314c-0.0073,0-0.0142,0-0.021,0
c-0.1357,0.0029-0.269,0.0039-0.4043,0.0039c-12.2642,0-23.4736-10.3262-24.5088-22.4814l53.0127,0.0322c0.0015,0,0.0024,0,0.0034,0
c2.2373,0,3.4697-1.1621,3.4712-3.2715c0.0034-5.2588-1.3574-10.3945-4.0464-15.2705
C155.0015,84.0953,151.2188,80.1363,146.4561,77.1739z M154.6451,100.4341l-49.1157-0.0293
c1.9834-11.6631,13.0181-21.2417,24.5034-21.0117c0.1387-0.0024,0.2754-0.0039,0.4136-0.0039
C143.4629,79.3892,152.4722,90.0162,154.6451,100.4341z"/>
<path d="M204.0386,136.6382c5.7319,0,11.1069-1.4502,15.9746-4.3115c4.938-2.9014,8.75-6.7129,11.6533-11.6533
c2.8608-4.8672,4.311-10.2578,4.311-16.0244c0-5.7324-1.4502-11.1064-4.311-15.9746c-2.9019-4.9385-6.7134-8.75-11.6533-11.6533
c-4.8687-2.8618-10.2437-4.3125-15.9746-4.3125c-9.938,0-19.2021,4.7583-24.3516,12.3174v-9.438
c0-0.5946-0.1465-1.0788-0.411-1.4511c-0.3815-0.5369-1.0157-0.834-1.8727-0.834h-2.6738c-1.4521,0-2.2852,0.833-2.2852,2.2852
v5.6964v46.4791v23.9676c0,1.2568,0.7808,2.0371,2.0371,2.0371h3.3667c0.9209,0,1.6421-0.6992,1.6421-1.5908v-17.098v-10.984
C185.0884,131.8892,194.2749,136.6382,204.0386,136.6382z M186.6358,122.5591c-4.9346-4.9346-7.6831-11.4932-7.542-18.0254
c-0.1367-6.3506,2.5439-12.751,7.3545-17.5605c4.8521-4.8521,11.3037-7.5547,17.7383-7.417c4.3691,0,8.4863,1.1465,12.2314,3.4043
c3.7344,2.2979,6.7456,5.4053,8.9492,9.2354c2.1699,3.9072,3.2695,8.0967,3.2695,12.4697
c0.1396,6.4619-2.5967,12.9844-7.5083,17.8955c-4.7617,4.7617-11.0469,7.3857-17.2544,7.2803
C197.6856,129.9712,191.396,127.3208,186.6358,122.5591z"/>
<path d="M241.8955,80.3975h7.5669v42.0259c0,6.8174,4.5674,12.1309,11.0825,12.9189c0.6836,0.1055,1.8379,0.1572,3.5303,0.1572
c2.0078,0,3.0273-0.3535,3.0273-2.2842v-2.377c0-1.7891-1.334-2.0371-2.7568-2.0371c0,0-0.001,0-0.002,0l-1.7871-0.0488
c-2.0117-0.0439-3.4883-0.7627-4.3896-2.1367c-0.9697-1.4805-1.4619-3.1738-1.4619-5.0352V80.3975h10.0928
c1.3076,0,2.2852-1.3628,2.2852-2.5815v-1.9312c0-1.3999-0.8359-2.2354-2.2354-2.2354h-10.1426V60.6861
c0-1.4619-0.7969-2.4829-1.9375-2.4829c-0.1865,0-0.4121,0-0.6392,0.0884l-2.6489,0.6865
c-1.2109,0.3682-2.0171,0.9263-2.0171,2.4507v12.2207h-7.5669c-1.4185,0-2.335,0.897-2.335,2.2852v1.8813
C239.5606,79.2393,240.6079,80.3975,241.8955,80.3975z"/>
<path d="M379.1182,106.2691c-4.0488-2.9219-8.8545-5.0293-14.291-6.2646c-6.5049-1.3975-13.4473-5.2129-13.3203-10.3066
c0-7.5225,6.6367-10.1914,12.3203-10.1914c5.3574,0,10.2207,3.002,13.001,8.0146c0.6729,1.2861,1.4785,1.9375,2.3955,1.9375
c0.3311,0,0.7061-0.1113,0.9922-0.2832l2.2021-1.1523c0.5947-0.3408,0.9229-0.9414,0.9229-1.6924
c0-0.5205-0.0908-0.9541-0.2617-1.292c-3.6367-8.2466-10.0967-12.4282-19.2021-12.4282c-11.7305,0-19.6123,6.9263-19.6123,17.2349
c0,4.3125,1.8438,7.9746,5.4756,10.8809c3.4482,2.7979,7.9121,4.8623,13.2705,6.1377c4.5859,1.085,8.3193,2.5654,11.0977,4.4023
c1.4159,0.9354,2.4412,2.0535,3.106,3.3672c0.6053,1.1962,0.9135,2.5535,0.9135,4.1005c0.0742,2.3857-0.79,4.5176-2.5684,6.3389
c-3.1445,3.2178-8.4053,4.6689-12.0205,4.6689c-0.0361,0-0.0723,0-0.1074,0c-3.4268,0-6.4893-0.8438-9.1035-2.5068
c-2.5918-1.6484-4.2363-3.8076-5.0293-6.6064c-0.3203-1.0996-0.751-2.1738-2.1553-2.1738c-0.0742,0-0.2109,0.0146-0.4062,0.0449
c-0.1133,0.0166-0.2559,0.0381-0.5088,0.0742l-1.8818,0.4463l-0.1045,0.0332c-1.0244,0.4082-1.6113,1.1846-1.6113,2.1309
c0,0.2285,0.0625,0.6592,0.2178,1.1094c1.9707,8.5801,10.2432,14.3447,20.5732,14.3447c0.125,0.002,0.249,0.002,0.374,0.002
c6.5947,0,12.6748-2.3193,16.7275-6.3945c3.1895-3.208,4.8311-7.2363,4.748-11.6357c0-2.8187-0.6185-5.3109-1.8062-7.481
C382.4437,109.2624,381.0062,107.631,379.1182,106.2691z"/>
<path d="M348.9043,45.7325c0-6.3157-3.2826-11.8699-8.2238-15.0756c-2.811-1.8237-6.1537-2.8947-9.7469-2.8947
c-9.9092,0-17.9707,8.0615-17.9707,17.9702c0,4.7659,1.8775,9.0925,4.9157,12.3123c-3.6619,4.3709-6.6334,9.3336-8.7663,14.7186
c-1.5873-0.2422-3.2123-0.3683-4.8662-0.3683c-17.7158,0-32.1289,14.4131-32.1289,32.1289c0,14.6854,9.9077,27.0922,23.3869,30.9101
c-6.7762,17.3461-23.6572,29.6719-43.3742,29.6719c-16.8195,0-31.583-8.9662-39.7656-22.369
c-2.4778,0.5446-5.0429,0.8519-7.6721,0.9023c9.0226,16.99,26.8969,28.5917,47.4377,28.5917
c23.2646,0,43.1121-14.8788,50.5461-35.6179c0.5204,0.0251,1.0435,0.0398,1.5701,0.0398c17.7158,0,32.1289-14.4131,32.1289-32.1289
c0-13.557-8.4446-25.1712-20.3465-29.8811c1.9001-4.5678,4.5115-8.7646,7.6888-12.4641c0.9996,0.4404,2.0479,0.785,3.1324,1.0384
c1.3144,0.3071,2.6773,0.486,4.0839,0.486C340.8428,63.7032,348.9043,55.6416,348.9043,45.7325z M304.2461,129.5279
c-13.7871,0-25.0039-11.2168-25.0039-25.0039s11.2168-25.0039,25.0039-25.0039S329.25,90.7369,329.25,104.524
S318.0332,129.5279,304.2461,129.5279z M330.9336,34.8872c0.645,0,1.2737,0.0671,1.8881,0.1755
c5.0818,0.8974,8.9576,5.3347,8.9576,10.6697c0,5.9805-4.8652,10.8457-10.8457,10.8457s-10.8457-4.8652-10.8457-10.8457
c0-1.3967,0.2746-2.7282,0.7576-3.9555C322.4306,37.7496,326.35,34.8872,330.9336,34.8872z"/>
</svg>

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 437.4294 209.6185" style="enable-background:new 0 0 437.4294 209.6185;" xml:space="preserve">
<path style="fill:#FFFFFF;" d="M95.1109,128.1089H58.6797V65.6861c0-1.5234-0.8169-2.4331-2.1855-2.4331h-3.1187
c-1.3159,0-2.2349,1.0005-2.2349,2.4331v67.4297c0,1.4521,0.8145,2.2852,2.2349,2.2852h41.7353c1.4844,0,2.4819-0.9375,2.4819-2.333
v-2.7744C97.5928,128.9253,96.6651,128.1089,95.1109,128.1089z"/>
<path style="fill:#FFFFFF;" d="M146.4561,77.1739c-4.8252-3.001-10.3037-4.5249-16.2837-4.5288c-0.0068,0-0.0137,0-0.0205,0
c-5.7349,0-11.1377,1.4639-16.0566,4.3511c-4.916,2.8853-8.8721,6.8364-11.7593,11.7456
c-2.8975,4.9248-4.3687,10.332-4.3721,16.0713c-0.0034,5.7188,1.4966,11.0654,4.4565,15.8887
c2.9893,4.9209,6.8789,8.7334,11.8887,11.6514c4.8657,2.8633,10.2397,4.3174,15.9717,4.3203c0.0073,0,0.0146,0,0.022,0
c8.123,0,14.7441-2.5869,21.4683-8.3906c0.5493-0.4805,0.8516-1.1201,0.8516-1.8008c0.001-0.6074-0.1743-1.1035-0.5205-1.4756
l-1.3569-1.8428l-0.0732-0.0859c-0.2637-0.2637-0.6929-0.6152-1.3716-0.6152c-0.6421,0-1.2549,0.2217-1.7124,0.6143
c-1.9346,1.585-3.5459,2.8008-4.7969,3.6182c-1.7979,1.208-5.8218,3.2314-12.5986,3.2314c-0.0073,0-0.0142,0-0.021,0
c-0.1357,0.0029-0.269,0.0039-0.4043,0.0039c-12.2642,0-23.4736-10.3262-24.5088-22.4814l53.0127,0.0322c0.0015,0,0.0024,0,0.0034,0
c2.2373,0,3.4697-1.1621,3.4712-3.2715c0.0034-5.2588-1.3574-10.3945-4.0464-15.2705
C155.0015,84.0953,151.2188,80.1363,146.4561,77.1739z M154.6451,100.4341l-49.1157-0.0293
c1.9834-11.6631,13.0181-21.2417,24.5034-21.0117c0.1387-0.0024,0.2754-0.0039,0.4136-0.0039
C143.4629,79.3892,152.4722,90.0162,154.6451,100.4341z"/>
<path style="fill:#FFFFFF;" d="M204.0386,136.6382c5.7319,0,11.1069-1.4502,15.9746-4.3115
c4.938-2.9014,8.75-6.7129,11.6533-11.6533c2.8608-4.8672,4.311-10.2578,4.311-16.0244c0-5.7324-1.4502-11.1064-4.311-15.9746
c-2.9019-4.9385-6.7134-8.75-11.6533-11.6533c-4.8687-2.8618-10.2437-4.3125-15.9746-4.3125
c-9.938,0-19.2021,4.7583-24.3516,12.3174v-9.438c0-0.5946-0.1465-1.0788-0.411-1.4511c-0.3815-0.5369-1.0157-0.834-1.8727-0.834
h-2.6738c-1.4521,0-2.2852,0.833-2.2852,2.2852v5.6964v46.4791v23.9676c0,1.2568,0.7808,2.0371,2.0371,2.0371h3.3667
c0.9209,0,1.6421-0.6992,1.6421-1.5908v-17.098v-10.984C185.0884,131.8892,194.2749,136.6382,204.0386,136.6382z M186.6358,122.5591
c-4.9346-4.9346-7.6831-11.4932-7.542-18.0254c-0.1367-6.3506,2.5439-12.751,7.3545-17.5605
c4.8521-4.8521,11.3037-7.5547,17.7383-7.417c4.3691,0,8.4863,1.1465,12.2314,3.4043c3.7344,2.2979,6.7456,5.4053,8.9492,9.2354
c2.1699,3.9072,3.2695,8.0967,3.2695,12.4697c0.1396,6.4619-2.5967,12.9844-7.5083,17.8955
c-4.7617,4.7617-11.0469,7.3857-17.2544,7.2803C197.6856,129.9712,191.396,127.3208,186.6358,122.5591z"/>
<path style="fill:#FFFFFF;" d="M241.8955,80.3975h7.5669v42.0259c0,6.8174,4.5674,12.1309,11.0825,12.9189
c0.6836,0.1055,1.8379,0.1572,3.5303,0.1572c2.0078,0,3.0273-0.3535,3.0273-2.2842v-2.377c0-1.7891-1.334-2.0371-2.7568-2.0371
c0,0-0.001,0-0.002,0l-1.7871-0.0488c-2.0117-0.0439-3.4883-0.7627-4.3896-2.1367c-0.9697-1.4805-1.4619-3.1738-1.4619-5.0352
V80.3975h10.0928c1.3076,0,2.2852-1.3628,2.2852-2.5815v-1.9312c0-1.3999-0.8359-2.2354-2.2354-2.2354h-10.1426V60.6861
c0-1.4619-0.7969-2.4829-1.9375-2.4829c-0.1865,0-0.4121,0-0.6392,0.0884l-2.6489,0.6865
c-1.2109,0.3682-2.0171,0.9263-2.0171,2.4507v12.2207h-7.5669c-1.4185,0-2.335,0.897-2.335,2.2852v1.8813
C239.5606,79.2393,240.6079,80.3975,241.8955,80.3975z"/>
<path style="fill:#FFFFFF;" d="M379.1182,106.2691c-4.0488-2.9219-8.8545-5.0293-14.291-6.2646
c-6.5049-1.3975-13.4473-5.2129-13.3203-10.3066c0-7.5225,6.6367-10.1914,12.3203-10.1914c5.3574,0,10.2207,3.002,13.001,8.0146
c0.6729,1.2861,1.4785,1.9375,2.3955,1.9375c0.3311,0,0.7061-0.1113,0.9922-0.2832l2.2021-1.1523
c0.5947-0.3408,0.9229-0.9414,0.9229-1.6924c0-0.5205-0.0908-0.9541-0.2617-1.292c-3.6367-8.2466-10.0967-12.4282-19.2021-12.4282
c-11.7305,0-19.6123,6.9263-19.6123,17.2349c0,4.3125,1.8438,7.9746,5.4756,10.8809c3.4482,2.7979,7.9121,4.8623,13.2705,6.1377
c4.5859,1.085,8.3193,2.5654,11.0977,4.4023c1.4159,0.9354,2.4412,2.0535,3.106,3.3672c0.6053,1.1962,0.9135,2.5535,0.9135,4.1005
c0.0742,2.3857-0.79,4.5176-2.5684,6.3389c-3.1445,3.2178-8.4053,4.6689-12.0205,4.6689c-0.0361,0-0.0723,0-0.1074,0
c-3.4268,0-6.4893-0.8438-9.1035-2.5068c-2.5918-1.6484-4.2363-3.8076-5.0293-6.6064c-0.3203-1.0996-0.751-2.1738-2.1553-2.1738
c-0.0742,0-0.2109,0.0146-0.4062,0.0449c-0.1133,0.0166-0.2559,0.0381-0.5088,0.0742l-1.8818,0.4463l-0.1045,0.0332
c-1.0244,0.4082-1.6113,1.1846-1.6113,2.1309c0,0.2285,0.0625,0.6592,0.2178,1.1094c1.9707,8.5801,10.2432,14.3447,20.5732,14.3447
c0.125,0.002,0.249,0.002,0.374,0.002c6.5947,0,12.6748-2.3193,16.7275-6.3945c3.1895-3.208,4.8311-7.2363,4.748-11.6357
c0-2.8187-0.6185-5.3109-1.8062-7.481C382.4437,109.2624,381.0062,107.631,379.1182,106.2691z"/>
<path style="fill:#FFFFFF;" d="M348.9043,45.7325c0-6.3157-3.2826-11.8699-8.2238-15.0756
c-2.811-1.8237-6.1537-2.8947-9.7469-2.8947c-9.9092,0-17.9707,8.0615-17.9707,17.9702c0,4.7659,1.8775,9.0925,4.9157,12.3123
c-3.6619,4.3709-6.6334,9.3336-8.7663,14.7186c-1.5873-0.2422-3.2123-0.3683-4.8662-0.3683
c-17.7158,0-32.1289,14.4131-32.1289,32.1289c0,14.6854,9.9077,27.0922,23.3869,30.9101
c-6.7762,17.3461-23.6572,29.6719-43.3742,29.6719c-16.8195,0-31.583-8.9662-39.7656-22.369
c-2.4778,0.5446-5.0429,0.8519-7.6721,0.9023c9.0226,16.99,26.8969,28.5917,47.4377,28.5917
c23.2646,0,43.1121-14.8788,50.5461-35.6179c0.5204,0.0251,1.0435,0.0398,1.5701,0.0398c17.7158,0,32.1289-14.4131,32.1289-32.1289
c0-13.557-8.4446-25.1712-20.3465-29.8811c1.9001-4.5678,4.5115-8.7646,7.6888-12.4641c0.9996,0.4404,2.0479,0.785,3.1324,1.0384
c1.3144,0.3071,2.6773,0.486,4.0839,0.486C340.8428,63.7032,348.9043,55.6416,348.9043,45.7325z M304.2461,129.5279
c-13.7871,0-25.0039-11.2168-25.0039-25.0039s11.2168-25.0039,25.0039-25.0039S329.25,90.7369,329.25,104.524
S318.0332,129.5279,304.2461,129.5279z M330.9336,34.8872c0.645,0,1.2737,0.0671,1.8881,0.1755
c5.0818,0.8974,8.9576,5.3347,8.9576,10.6697c0,5.9805-4.8652,10.8457-10.8457,10.8457s-10.8457-4.8652-10.8457-10.8457
c0-1.3967,0.2746-2.7282,0.7576-3.9555C322.4306,37.7496,326.35,34.8872,330.9336,34.8872z"/>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 115.9988 115.9988" style="enable-background:new 0 0 115.9988 115.9988;" xml:space="preserve">
<g>
<g>
<g>
<path style="fill:#180D38;" d="M29.1281,108.2941c9.5736-4.5548,17.1531-12.6456,21.0335-22.5787
c-12.0865-3.4232-20.9707-14.548-20.9707-27.7159c0-15.8849,12.9236-28.8085,28.8085-28.8085
c1.4832,0,2.9404,0.113,4.3639,0.3303c1.9125-4.8287,4.5771-9.2786,7.8607-13.1979c-2.7243-2.8871-4.4077-6.7665-4.4077-11.0399
c0-1.6191,0.2457-3.1808,0.6921-4.6562C63.7305,0.2186,60.8908,0,57.9995,0C25.9672,0,0,25.9672,0,57.9994
C0,79.5165,11.7263,98.2828,29.1281,108.2941z"/>
<path style="fill:#EF3939;" d="M81.9297,15.0082c3.6788,0,6.886-2.0536,8.5379-5.0742
c-5.3185-3.5997-11.2684-6.3339-17.646-8.0151c-0.3903,1.0504-0.6168,2.1798-0.6168,3.3644
C72.2049,10.6458,76.5673,15.0082,81.9297,15.0082z"/>
<path style="fill:#180D38;" d="M95.5663,13.828c-2.8537,4.5375-7.8918,7.5688-13.6366,7.5688
c-1.2614,0-2.4835-0.1604-3.6622-0.4359c-0.9722-0.2272-1.9121-0.5362-2.8083-0.931c-2.8492,3.3173-5.1907,7.0806-6.8945,11.1766
c10.6715,4.2233,18.2432,14.6371,18.2432,26.7928c0,15.8849-12.9235,28.8085-28.8085,28.8085
c-0.4718,0-0.9406-0.0131-1.4069-0.0357c-3.7532,10.4704-11.0354,19.2744-20.406,24.9696
c6.7355,2.7367,14.0948,4.257,21.8129,4.257c32.0322,0,57.9994-25.9672,57.9994-57.9995
C115.9988,40.3018,108.0628,24.4664,95.5663,13.828z"/>
<circle style="fill:#EF3939;" cx="57.9994" cy="57.9994" r="22.4198"/>
</g>
<path style="fill:#FFFFFF;" d="M78.2676,20.961c1.1786,0.2755,2.4008,0.4359,3.6622,0.4359
c5.7448,0,10.7829-3.0313,13.6366-7.5688c-1.6275-1.3855-3.3236-2.6925-5.0987-3.894c-1.6519,3.0206-4.8591,5.0742-8.5379,5.0742
c-5.3624,0-9.7249-4.3624-9.7249-9.7249c0-1.1846,0.2264-2.3141,0.6168-3.3644c-2.062-0.5436-4.1682-0.9763-6.3133-1.2917
c-0.4464,1.4753-0.6921,3.0371-0.6921,4.6562c0,4.2734,1.6834,8.1528,4.4077,11.0399c-3.2836,3.9193-5.9482,8.3692-7.8607,13.1979
c-1.4235-0.2172-2.8807-0.3303-4.3639-0.3303c-15.8849,0-28.8085,12.9235-28.8085,28.8085
c0,13.168,8.8842,24.2928,20.9707,27.7159c-3.8804,9.9332-11.4599,18.0239-21.0335,22.5787
c2.2621,1.3013,4.6175,2.456,7.0584,3.4478c9.3706-5.6952,16.6528-14.4992,20.406-24.9696
c0.4663,0.0226,0.9351,0.0357,1.4069,0.0357c15.8849,0,28.8085-12.9236,28.8085-28.8085c0-12.1557-7.5717-22.5695-18.2432-26.7928
c1.7038-4.0959,4.0453-7.8593,6.8945-11.1766C76.3555,20.4248,77.2953,20.7338,78.2676,20.961z M80.4193,57.9994
c0,12.3623-10.0576,22.4199-22.4198,22.4199c-12.3623,0-22.4199-10.0576-22.4199-22.4199
c0-12.3622,10.0576-22.4199,22.4199-22.4199C70.3617,35.5795,80.4193,45.6371,80.4193,57.9994z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 115.5026 115.5026" style="enable-background:new 0 0 115.5026 115.5026;" xml:space="preserve">
<path style="fill:#181139;" d="M115.5026,0h-13.957c0.0002,0.0315,0.0031,0.0623,0.0031,0.0938
c0,9.718-7.9059,17.6239-17.6239,17.6239c-1.3796,0-2.7163-0.1754-4.0055-0.4767c-1.0634-0.2485-2.0913-0.5864-3.0715-1.0182
c-3.1162,3.6283-5.6772,7.7443-7.5408,12.2242c11.6719,4.6192,19.9532,16.0091,19.9532,29.3043
c0,17.374-14.1349,31.5089-31.5089,31.5089c-0.5161,0-1.0288-0.0143-1.5388-0.039c-3.8856,10.8397-11.2302,20.0454-20.6959,26.2814
h79.986V0z"/>
<circle style="fill:#EF3939;" cx="57.7513" cy="57.7513" r="24.5214"/>
<path style="fill:#181139;" d="M49.1788,88.0652c-13.2195-3.744-22.9364-15.9116-22.9364-30.3139
c0-17.374,14.1349-31.5089,31.5089-31.5089c1.6223,0,3.2161,0.1237,4.7729,0.3612c2.0918-5.2813,5.0061-10.1484,8.5975-14.4351
c-2.9796-3.1577-4.8209-7.4008-4.8209-12.0747c0-0.0317,0.0046-0.0622,0.0048-0.0938H0v115.5026h18.8623
C32.7495,111.6378,43.9877,101.3537,49.1788,88.0652z"/>
<path style="fill:#EF3939;" d="M83.9248,10.7302c5.8651,0,10.6364-4.7714,10.6364-10.6364c0-0.0316-0.004-0.0623-0.0043-0.0938
H73.293c-0.0003,0.0316-0.0046,0.0621-0.0046,0.0938C73.2884,5.9589,78.0598,10.7302,83.9248,10.7302z"/>
<path style="fill:#FFFFFF;" d="M56.2125,89.2212c0.51,0.0247,1.0228,0.039,1.5388,0.039c17.374,0,31.5089-14.1349,31.5089-31.5089
c0-13.2952-8.2814-24.6851-19.9532-29.3043c1.8635-4.4799,4.4246-8.5959,7.5408-12.2242c0.9802,0.4318,2.0082,0.7698,3.0715,1.0182
c1.2892,0.3013,2.6259,0.4767,4.0055,0.4767c9.718,0,17.6239-7.9059,17.6239-17.6239c0-0.0315-0.0029-0.0623-0.0031-0.0938h-6.9887
c0.0003,0.0316,0.0043,0.0622,0.0043,0.0938c0,5.8651-4.7714,10.6364-10.6364,10.6364S73.2884,5.9589,73.2884,0.0938
c0-0.0317,0.0043-0.0622,0.0046-0.0938h-6.9874c-0.0002,0.0316-0.0048,0.0621-0.0048,0.0938c0,4.674,1.8413,8.9171,4.8209,12.0747
c-3.5914,4.2867-6.5057,9.1537-8.5975,14.4351c-1.5569-0.2375-3.1507-0.3612-4.7729-0.3612
c-17.374,0-31.5089,14.1349-31.5089,31.5089c0,14.4023,9.7169,26.5699,22.9364,30.3139
c-5.1912,13.2885-16.4293,23.5726-30.3165,27.4374h16.6543C44.9824,109.2666,52.327,100.0609,56.2125,89.2212z M33.2299,57.7513
c0-13.5211,11.0004-24.5214,24.5214-24.5214s24.5214,11.0004,24.5214,24.5214S71.2724,82.2727,57.7513,82.2727
S33.2299,71.2723,33.2299,57.7513z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -1,44 +0,0 @@
[package]
name = "leptos-counter-isomorphic"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
actix-files = { version = "0.6", optional = true }
actix-web = { version = "4", optional = true, features = ["openssl", "macros"] }
broadcaster = "1"
console_log = "0.2"
console_error_panic_hook = "0.1"
serde = { version = "1", features = ["derive"] }
futures = "0.3"
cfg-if = "1"
lazy_static = "1"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_actix = { path = "../../integrations/actix", optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
log = "0.4"
simple_logger = "2"
gloo = { git = "https://github.com/rustwasm/gloo" }
[features]
default = ["csr"]
csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [
"dep:actix-files",
"dep:actix-web",
"leptos/ssr",
"leptos_actix",
"leptos_meta/ssr",
"leptos_router/ssr",
]
[package.metadata.cargo-all-features]
denylist = ["actix-files", "actix-web", "leptos_actix"]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]

View File

@@ -1,21 +0,0 @@
# Leptos Counter Isomorphic Example
This example demonstrates how to use a function isomorphically, to run a server side function from the browser and receive a result.
## Server Side Rendering With Hydration
To run it as a server side app with hydration, first you should run
```bash
wasm-pack build --target=web --no-default-features --features=hydrate
```
to generate the WebAssembly to provide hydration features for the server.
Then run the server with `cargo run` to serve the server side rendered HTML and the WASM bundle for hydration.
```bash
cargo run --no-default-features --features=ssr
```
> Note that if your hydration code changes, you will have to rerun the wasm-pack command above
> This should be temporary, and vastly improve once cargo-leptos becomes ready for prime time!

View File

@@ -0,0 +1,4 @@
[tasks.build]
command = "cargo"
args = ["+nightly", "build-all-features"]
install_crate = "cargo-all-features"

View File

@@ -3,5 +3,3 @@
This example creates a simple counter in a client side rendered app with Rust and WASM!
To run it, just issue the `trunk serve --open` command in the example root. This will build the app, run it, and open a new browser to serve it.
> If you don't have `trunk` installed, [click here for install instructions.](https://trunkrs.dev/)

View File

@@ -2,6 +2,7 @@
<html>
<head>
<link data-trunk rel="rust" data-wasm-opt="z"/>
<link data-trunk rel="icon" type="image/ico" href="/public/favicon.ico"/>
</head>
<body></body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -2,14 +2,16 @@ use leptos::*;
/// A simple counter component.
///
/// You can document each of the properties passed to a component using the format below.
///
/// # Props
/// - **initial_value** [`i32`] - The value the counter should start at.
/// - **step** [`i32`] - The change that should be applied on each step.
/// You can use doc comments like this to document your component.
#[component]
pub fn SimpleCounter(cx: Scope, initial_value: i32, step: i32) -> web_sys::Element {
let (value, set_value) = create_signal(cx, 0);
pub fn SimpleCounter(
cx: Scope,
/// The starting value for the counter
initial_value: i32,
/// The change that should be applied each time the button is clicked.
step: i32
) -> impl IntoView {
let (value, set_value) = create_signal(cx, initial_value);
view! { cx,
<div>

View File

@@ -4,5 +4,10 @@ use leptos::*;
pub fn main() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to_body(|cx| view! { cx, <SimpleCounter initial_value=3 step=1/> })
mount_to_body(|cx| view! { cx,
<SimpleCounter
initial_value=0
step=1
/>
})
}

View File

@@ -11,11 +11,16 @@ fn inc() {
let document = leptos::document();
let div = document.query_selector("div").unwrap().unwrap();
let dec = div
let clear = div
.first_child()
.unwrap()
.dyn_into::<HtmlElement>()
.unwrap();
let dec = clear
.next_sibling()
.unwrap()
.dyn_into::<HtmlElement>()
.unwrap();
let text = dec
.next_sibling()
.unwrap()
@@ -30,12 +35,16 @@ fn inc() {
inc.click();
inc.click();
assert_eq!(text.text_content(), Some("2".to_string()));
assert_eq!(text.text_content(), Some("Value: 2!".to_string()));
dec.click();
dec.click();
dec.click();
dec.click();
assert_eq!(text.text_content(), Some("-2".to_string()));
assert_eq!(text.text_content(), Some("Value: -2!".to_string()));
clear.click();
assert_eq!(text.text_content(), Some("Value: 0!".to_string()));
}

View File

@@ -0,0 +1 @@
.leptos.kdl

View File

@@ -0,0 +1,88 @@
[package]
name = "counter_isomorphic"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
actix-files = { version = "0.6", optional = true }
actix-web = { version = "4", optional = true, features = ["openssl", "macros"] }
broadcaster = "1"
console_log = "0.2"
console_error_panic_hook = "0.1"
serde = { version = "1", features = ["derive"] }
futures = "0.3"
cfg-if = "1"
lazy_static = "1"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_actix = { path = "../../integrations/actix", optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
log = "0.4"
simple_logger = "4.0.0"
gloo-net = { git = "https://github.com/rustwasm/gloo" }
[features]
default = []
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [
"dep:actix-files",
"dep:actix-web",
"leptos/ssr",
"leptos_actix",
"leptos_meta/ssr",
"leptos_router/ssr",
]
stable = ["leptos/stable", "leptos_router/stable"]
[package.metadata.cargo-all-features]
denylist = ["actix-files", "actix-web", "leptos_actix", "stable"]
skip_feature_sets = [["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 = "counter_isomorphic"
# 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 = "src/styles/tailwind.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-address = "127.0.0.1:3000"
# The port to use for automatic reload monitoring
reload-port = 3001
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
end2end-cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha 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

View File

@@ -0,0 +1,4 @@
[tasks.build]
command = "cargo"
args = ["+nightly", "build-all-features"]
install_crate = "cargo-all-features"

View File

@@ -0,0 +1,40 @@
# Leptos Counter Isomorphic Example
This example demonstrates how to use a function isomorphically, to run a server side function from the browser and receive a result.
## Client Side Rendering
To run it as a Client Side App, you can issue `trunk serve --open` in the root. This will build the entire
app into one CSR bundle. Make sure you have trunk installed with `cargo install trunk`.
## Server Side Rendering with cargo-leptos
cargo-leptos is now the easiest and most featureful way to build server side rendered apps with hydration. It provides automatic recompilation of client and server code, wasm optimisation, CSS minification, and more! Check out more about it [here](https://github.com/akesson/cargo-leptos)
1. Install cargo-leptos
```bash
cargo install --locked cargo-leptos
```
2. Build the site in watch mode, recompiling on file changes
```bash
cargo leptos watch
```
3. When ready to deploy, run
```bash
cargo leptos build --release
```
## Server Side Rendering without cargo-leptos
To run it as a server side app with hydration, you'll need to have wasm-pack installed.
0. Edit the `[package.metadata.leptos]` section and set `site-root` to `"pkg"`. You'll also want to change the path of the `<StyleSheet / >` component in the root component to point towards the CSS file in the root. This tells leptos that the WASM/JS files generated by wasm-pack are available at `./pkg` and that the CSS files are no longer processed by cargo-leptos. Building to alternative folders is not supported at this time.
1. Install wasm-pack
```bash
cargo install wasm-pack
```
2. Build the Webassembly used to hydrate the HTML from the server
```bash
wasm-pack build --target=web --debug --no-default-features --features=hydrate
```
3. Run the server to serve the Webassembly, JS, and HTML
```bash
cargo run --no-default-features --features=ssr
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,5 +1,6 @@
use leptos::*;
use leptos_router::*;
use leptos_meta::*;
#[cfg(feature = "ssr")]
use std::sync::atomic::{AtomicI32, Ordering};
@@ -9,9 +10,9 @@ use broadcaster::BroadcastChannel;
#[cfg(feature = "ssr")]
pub fn register_server_functions() {
GetServerCount::register();
AdjustServerCount::register();
ClearServerCount::register();
_ = GetServerCount::register();
_ = AdjustServerCount::register();
_ = ClearServerCount::register();
}
#[cfg(feature = "ssr")]
@@ -43,41 +44,41 @@ pub async fn clear_server_count() -> Result<i32, ServerFnError> {
Ok(0)
}
#[component]
pub fn Counters(cx: Scope) -> Element {
pub fn Counters(cx: Scope) -> impl IntoView {
provide_meta_context(cx);
view! {
cx,
<div>
<Router>
<header>
<h1>"Server-Side Counters"</h1>
<p>"Each of these counters stores its data in the same variable on the server."</p>
<p>"The value is shared across connections. Try opening this is another browser tab to see what I mean."</p>
</header>
<nav>
<ul>
<li><A href="">"Simple"</A></li>
<li><A href="form">"Form-Based"</A></li>
<li><A href="multi">"Multi-User"</A></li>
</ul>
</nav>
<main>
<Routes>
<Route path="" element=|cx| view! {
cx,
<Counter/>
}/>
<Route path="form" element=|cx| view! {
cx,
<FormCounter/>
}/>
<Route path="multi" element=|cx| view! {
cx,
<MultiuserCounter/>
}/>
</Routes>
</main>
</Router>
</div>
<Router>
<header>
<h1>"Server-Side Counters"</h1>
<p>"Each of these counters stores its data in the same variable on the server."</p>
<p>"The value is shared across connections. Try opening this is another browser tab to see what I mean."</p>
</header>
<nav>
<ul>
<li><A href="">"Simple"</A></li>
<li><A href="form">"Form-Based"</A></li>
<li><A href="multi">"Multi-User"</A></li>
</ul>
</nav>
<Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/>
<main>
<Routes>
<Route path="" view=|cx| view! {
cx,
<Counter/>
}/>
<Route path="form" view=|cx| view! {
cx,
<FormCounter/>
}/>
<Route path="multi" view=|cx| view! {
cx,
<MultiuserCounter/>
}/>
</Routes>
</main>
</Router>
}
}
@@ -86,13 +87,13 @@ pub fn Counters(cx: Scope) -> Element {
// it's invalidated by one of the user's own actions
// This is the typical pattern for a CRUD app
#[component]
pub fn Counter(cx: Scope) -> Element {
pub fn Counter(cx: Scope) -> impl IntoView {
let dec = create_action(cx, |_| adjust_server_count(-1, "decing".into()));
let inc = create_action(cx, |_| adjust_server_count(1, "incing".into()));
let clear = create_action(cx, |_| clear_server_count());
let counter = create_resource(
cx,
move || (dec.version.get(), inc.version.get(), clear.version.get()),
move || (dec.version().get(), inc.version().get(), clear.version().get()),
|_| get_server_count(),
);
@@ -118,6 +119,7 @@ pub fn Counter(cx: Scope) -> Element {
<span>"Value: " {move || value().to_string()} "!"</span>
<button on:click=move |_| inc.dispatch(())>"+1"</button>
</div>
{move || error_msg().map(|msg| view! { cx, <p>"Error: " {msg.to_string()}</p>})}
</div>
}
}
@@ -126,20 +128,15 @@ pub fn Counter(cx: Scope) -> Element {
// It uses the same invalidation pattern as the plain counter,
// but uses HTML forms to submit the actions
#[component]
pub fn FormCounter(cx: Scope) -> Element {
pub fn FormCounter(cx: Scope) -> impl IntoView {
let adjust = create_server_action::<AdjustServerCount>(cx);
let clear = create_server_action::<ClearServerCount>(cx);
let counter = create_resource(
cx,
{
let adjust = adjust.version;
let clear = clear.version;
move || (adjust.get(), clear.get())
},
move || (adjust.version().get(), clear.version().get()),
|_| {
log::debug!("FormCounter running fetcher");
get_server_count()
},
);
@@ -153,8 +150,6 @@ pub fn FormCounter(cx: Scope) -> Element {
.unwrap_or(0)
};
let adjust2 = adjust.clone();
view! {
cx,
<div>
@@ -174,7 +169,7 @@ pub fn FormCounter(cx: Scope) -> Element {
<input type="submit" value="-1"/>
</ActionForm>
<span>"Value: " {move || value().to_string()} "!"</span>
<ActionForm action=adjust2>
<ActionForm action=adjust>
<input type="hidden" name="delta" value="1"/>
<input type="hidden" name="msg" value="form value up"/>
<input type="submit" value="+1"/>
@@ -189,7 +184,7 @@ pub fn FormCounter(cx: Scope) -> Element {
// Whenever another user updates the value, it will update here
// This is the primitive pattern for live chat, collaborative editing, etc.
#[component]
pub fn MultiuserCounter(cx: Scope) -> Element {
pub fn MultiuserCounter(cx: Scope) -> impl IntoView {
let dec = create_action(cx, |_| adjust_server_count(-1, "dec dec goose".into()));
let inc = create_action(cx, |_| adjust_server_count(1, "inc inc moose".into()));
let clear = create_action(cx, |_| clear_server_count());
@@ -198,7 +193,7 @@ pub fn MultiuserCounter(cx: Scope) -> Element {
let multiplayer_value = {
use futures::StreamExt;
let mut source = gloo::net::eventsource::futures::EventSource::new("/api/events")
let mut source = gloo_net::eventsource::futures::EventSource::new("/api/events")
.expect_throw("couldn't connect to SSE stream");
let s = create_signal_from_stream(
cx,
@@ -217,8 +212,8 @@ pub fn MultiuserCounter(cx: Scope) -> Element {
};
#[cfg(feature = "ssr")]
let multiplayer_value =
create_signal_from_stream(cx, futures::stream::once(Box::pin(async { 0.to_string() })));
let (multiplayer_value, _) =
create_signal(cx, None::<i32>);
view! {
cx,
@@ -228,7 +223,7 @@ pub fn MultiuserCounter(cx: Scope) -> Element {
<div>
<button on:click=move |_| clear.dispatch(())>"Clear"</button>
<button on:click=move |_| dec.dispatch(())>"-1"</button>
<span>"Multiplayer Value: " {move || multiplayer_value().unwrap_or_default().to_string()}</span>
<span>"Multiplayer Value: " {move || multiplayer_value.get().unwrap_or_default().to_string()}</span>
<button on:click=move |_| inc.dispatch(())>"+1"</button>
</div>
</div>

View File

@@ -14,7 +14,7 @@ cfg_if! {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
leptos::hydrate(body().unwrap(), |cx| {
mount_to_body(|cx| {
view! { cx, <Counters/> }
});
}

View File

@@ -9,7 +9,7 @@ cfg_if! {
use actix_files::{Files};
use actix_web::*;
use crate::counters::*;
use std::{net::SocketAddr, env};
use leptos_actix::{generate_route_list, LeptosRoutes};
#[get("/api/events")]
async fn counter_events() -> impl Responder {
@@ -30,18 +30,23 @@ cfg_if! {
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let addr = SocketAddr::from(([127,0,0,1],3000));
crate::counters::register_server_functions();
let conf = get_configuration(Some("Cargo.toml")).await.unwrap();
let addr = conf.leptos_options.site_address.clone();
let routes = generate_route_list(|cx| view! { cx, <Counters/> });
HttpServer::new(move || {
let render_options: RenderOptions = RenderOptions::builder().pkg_path("/pkg/leptos_counter_isomorphic").reload_port(3001).socket_address(addr.clone()).environment(&env::var("RUST_ENV")).build();
render_options.write_to_file();
let leptos_options = &conf.leptos_options;
let site_root = &leptos_options.site_root;
App::new()
.service(Files::new("/pkg", "./pkg"))
.service(counter_events)
.route("/api/{tail:.*}", leptos_actix::handle_server_fns())
.route("/{tail:.*}", leptos_actix::render_app_to_stream(render_options, |cx| view! { cx, <Counters/> }))
//.wrap(middleware::Compress::default())
.leptos_routes(leptos_options.to_owned(), routes.to_owned(), |cx| view! { cx, <Counters/> })
.service(Files::new("/", &site_root))
//.wrap(middleware::Compress::default())
})
.bind(&addr)?
.run()
@@ -51,7 +56,7 @@ cfg_if! {
// client-only stuff for Trunk
else {
use leptos_counter_isomorphic::counters::*;
use counter_isomorphic::counters::*;
pub fn main() {
_ = console_log::init_with_level(log::Level::Debug);

View File

@@ -1,10 +0,0 @@
# Leptos Counters Example on Rust Stable
This example showcases a basic Leptos app with many counters. It is a good example of how to setup a basic reactive app with signals and effects, and how to interact with browser events. Unlike the other counters example, it will compile on Rust stable, because it has the `stable` feature enabled.
## Client Side Rendering
To run it as a Client Side App, you can issue `trunk serve --open` in the root. This will build the entire
app into one CSR bundle.
> If you don't have `trunk` installed, [click here for install instructions.](https://trunkrs.dev/)

View File

@@ -0,0 +1,4 @@
[tasks.build]
command = "cargo"
args = ["+nightly", "build-all-features"]
install_crate = "cargo-all-features"

View File

@@ -1,10 +0,0 @@
# Leptos Counters Example
This example showcases a basic Leptos app with many counters. It is a good example of how to set up a basic reactive app with signals and effects, and how to interact with browser events.
## Client Side Rendering
To run it as a Client Side App, you can issue `trunk serve --open` in the root. This will build the entire
app into one CSR bundle.
> If you don't have `trunk` installed, [click here for install instructions.](https://trunkrs.dev/)

View File

@@ -11,7 +11,7 @@ struct CounterUpdater {
}
#[component]
pub fn Counters(cx: Scope) -> web_sys::Element {
pub fn Counters(cx: Scope) -> impl IntoView {
let (next_counter_id, set_next_counter_id) = create_signal(cx, 0);
let (counters, set_counters) = create_signal::<CounterHolder>(cx, vec![]);
provide_context(cx, CounterUpdater { set_counters });
@@ -39,7 +39,7 @@ pub fn Counters(cx: Scope) -> web_sys::Element {
};
view! { cx,
<div>
<>
<button on:click=add_counter>
"Add Counter"
</button>
@@ -63,16 +63,18 @@ pub fn Counters(cx: Scope) -> web_sys::Element {
" counters."
</p>
<ul>
<For each=counters key=|counter| counter.0>{
|cx, (id, (value, set_value)): &(usize, (ReadSignal<i32>, WriteSignal<i32>))| {
<For
each=counters
key=|counter| counter.0
view=move |(id, (value, set_value)): (usize, (ReadSignal<i32>, WriteSignal<i32>))| {
view! {
cx,
<Counter id=*id value=*value set_value=*set_value/>
<Counter id value set_value/>
}
}
}</For>
/>
</ul>
</div>
</>
}
}
@@ -82,7 +84,7 @@ fn Counter(
id: usize,
value: ReadSignal<i32>,
set_value: WriteSignal<i32>,
) -> web_sys::Element {
) -> impl IntoView {
let CounterUpdater { set_counters } = use_context(cx).unwrap_throw();
let input = move |ev| set_value(event_target_value(&ev).parse::<i32>().unwrap_or_default());

View File

@@ -1,7 +1,7 @@
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
use leptos::{wasm_bindgen::JsValue, *};
use leptos::*;
use web_sys::HtmlElement;
use counters::{Counters, CountersProps};
@@ -75,37 +75,39 @@ fn inc() {
dec_button.click();
}
// we can use RSX in test comparisons!
// note that if RSX template creation is bugged, this probably won't catch it
// (because the same bug will be reproduced in both sides of the assertion)
// so I use HTML tests for most internal testing like this
// but in user-land testing, RSX comparanda are cool
assert_eq!(
div.outer_html(),
view! { cx,
<div>
<button>"Add Counter"</button>
<button>"Add 1000 Counters"</button>
<button>"Clear Counters"</button>
<p>"Total: "<span>"3"</span>" from "<span>"2"</span>" counters."</p>
<ul>
<li>
<button>"-1"</button>
<input type="text"/>
<span>"1"</span>
<button>"+1"</button>
<button>"x"</button>
</li>
<li>
<button>"-1"</button>
<input type="text"/>
<span>"2"</span>
<button>"+1"</button>
<button>"x"</button>
</li>
</ul>
</div>
}
.outer_html()
);
run_scope(create_runtime(), move |cx| {
// we can use RSX in test comparisons!
// note that if RSX template creation is bugged, this probably won't catch it
// (because the same bug will be reproduced in both sides of the assertion)
// so I use HTML tests for most internal testing like this
// but in user-land testing, RSX comparanda are cool
assert_eq!(
div.outer_html(),
view! { cx,
<div>
<button>"Add Counter"</button>
<button>"Add 1000 Counters"</button>
<button>"Clear Counters"</button>
<p>"Total: "<span>"3"</span>" from "<span>"2"</span>" counters."</p>
<ul>
<li>
<button>"-1"</button>
<input type="text"/>
<span>"1"</span>
<button>"+1"</button>
<button>"x"</button>
</li>
<li>
<button>"-1"</button>
<input type="text"/>
<span>"2"</span>
<button>"+1"</button>
<button>"x"</button>
</li>
</ul>
</div>
}
.outer_html()
);
});
}

View File

@@ -0,0 +1,4 @@
[tasks.build]
command = "cargo"
args = ["+stable", "build-all-features"]
install_crate = "cargo-all-features"

View File

@@ -17,7 +17,7 @@ struct CounterUpdater {
}
#[component]
pub fn Counters(cx: Scope) -> web_sys::Element {
pub fn Counters(cx: Scope) -> impl IntoView {
let (next_counter_id, set_next_counter_id) = create_signal(cx, 0);
let (counters, set_counters) = create_signal::<CounterHolder>(cx, vec![]);
provide_context(cx, CounterUpdater { set_counters });
@@ -69,14 +69,16 @@ pub fn Counters(cx: Scope) -> web_sys::Element {
" counters."
</p>
<ul>
<For each={move || counters.get()} key={|counter| counter.0}>{
|cx, (id, (value, set_value)): &(usize, (ReadSignal<i32>, WriteSignal<i32>))| {
<For
each={move || counters.get()}
key={|counter| counter.0}
view=move |(id, (value, set_value))| {
view! {
cx,
<Counter id=*id value=*value set_value=*set_value/>
<Counter id value set_value/>
}
}
}</For>
/>
</ul>
</div>
}
@@ -88,14 +90,14 @@ fn Counter(
id: usize,
value: ReadSignal<i32>,
set_value: WriteSignal<i32>,
) -> web_sys::Element {
) -> impl IntoView {
let CounterUpdater { set_counters } = use_context(cx).unwrap_throw();
let input = move |ev| set_value.set(event_target_value(&ev).parse::<i32>().unwrap_or_default());
view! { cx,
<li>
<button on:click={move |_| set_value.update(move |value| *value -= 1)}>"-1"</button>
<button on:click=move |_| set_value.update(move |value| *value -= 1)>"-1"</button>
<input type="text"
prop:value={move || value.get().to_string()}
on:input=input

View File

@@ -11,7 +11,7 @@ serde = { version = "1", features = ["derive"] }
log = "0.4"
console_log = "0.2"
console_error_panic_hook = "0.1.7"
gloo-timers = { version = "0.2", features = ["futures"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.0"

View File

@@ -0,0 +1,4 @@
[tasks.build]
command = "cargo"
args = ["+nightly", "build-all-features"]
install_crate = "cargo-all-features"

View File

@@ -1,10 +0,0 @@
# Client Side Fetch
This example shows how to fetch data from the client in WebAssembly.
## Client Side Rendering
To run it as a Client Side App, you can issue `trunk serve --open` in the root. This will build the entire
app into one CSR bundle.
> If you don't have `trunk` installed, [click here for install instructions.](https://trunkrs.dev/)

View File

@@ -2,6 +2,7 @@
<html>
<head>
<link data-trunk rel="rust" data-wasm-opt="z"/>
<link data-trunk rel="icon" type="image/ico" href="/public/favicon.ico"/>
</head>
<style>
img {

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,6 +1,3 @@
use std::time::Duration;
use gloo_timers::future::TimeoutFuture;
use leptos::*;
use serde::{Deserialize, Serialize};
@@ -10,10 +7,6 @@ pub struct Cat {
}
async fn fetch_cats(count: u32) -> Result<Vec<String>, ()> {
// artificial delay
// the cat API is too fast to show the transition
TimeoutFuture::new(500).await;
if count > 0 {
let res = reqwasm::http::Request::get(&format!(
"https://api.thecatapi.com/v1/images/search?limit={}",
@@ -34,50 +27,41 @@ async fn fetch_cats(count: u32) -> Result<Vec<String>, ()> {
}
}
pub fn fetch_example(cx: Scope) -> web_sys::Element {
pub fn fetch_example(cx: Scope) -> impl IntoView {
let (cat_count, set_cat_count) = create_signal::<u32>(cx, 1);
let cats = create_resource(cx, cat_count, |count| fetch_cats(count));
let (pending, set_pending) = create_signal(cx, false);
view! { cx,
view! { cx,
<div>
<label>
"How many cats would you like?"
<input type="number"
value={move || cat_count.get().to_string()}
prop:value={move || cat_count.get().to_string()}
on:input=move |ev| {
let val = event_target_value(&ev).parse::<u32>().unwrap_or(0);
set_cat_count(val);
}
/>
</label>
{move || pending().then(|| view! { cx, <p>"Loading more cats..."</p> })}
<div>
// <Transition/> holds the previous value while new async data is being loaded
// Switch the <Transition/> to <Suspense/> to fall back to "Loading..." every time
<Transition
fallback={"Loading (Suspense Fallback)...".to_string()}
set_pending
>
{move || {
cats.read().map(|data| match data {
Err(_) => view! { cx, <pre>"Error"</pre> },
Ok(cats) => view! { cx,
<div>{
cats.iter()
.map(|src| {
view! { cx,
<img src={src}/>
}
})
.collect::<Vec<_>>()
}</div>
},
})
}
<Transition fallback=move || view! { cx, <div>"Loading (Suspense Fallback)..."</div>}>
{move || {
cats.read().map(|data| match data {
Err(_) => view! { cx, <pre>"Error"</pre> }.into_view(cx),
Ok(cats) => view! { cx,
<div>{
cats.iter()
.map(|src| {
view! { cx,
<img src={src}/>
}
})
.collect::<Vec<_>>()
}</div>
}.into_view(cx),
})
}
</Transition>
</div>
}
</Transition>
</div>
}
}

View File

@@ -1,8 +0,0 @@
# Leptos in a GTK App
This example creates a basic GTK app that uses Leptoss reactive primitives.
## Build and Run
Unlike the other examples, this has a variety of build prerequisites that are out of scope of this crate. More detail on that can be found [here](https://gtk-rs.org/gtk4-rs/stable/latest/book/installation.html). The example comes from [here](https://gtk-rs.org/gtk4-rs/stable/latest/book/hello_world.html) and should be
runnable with `cargo run` if you have the GTK prerequisites installed.

View File

@@ -6,7 +6,7 @@ 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() {
_ = create_scope(create_runtime(), |cx| {
_ = create_scope(|cx| {
// Create a new application
let app = Application::builder().application_id(APP_ID).build();

View File

@@ -1,51 +0,0 @@
[package]
name = "leptos-hackernews-axum"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
anyhow = "1.0.66"
console_log = "0.2.0"
console_error_panic_hook = "0.1.7"
futures = "0.3.25"
cfg-if = "1.0.0"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_axum = { path = "../../integrations/axum", optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
log = "0.4.17"
simple_logger = "4.0.0"
serde = { version = "1.0.148", features = ["derive"] }
serde_json = "1.0.89"
gloo-net = { version = "0.2.5", features = ["http"] }
reqwest = { version = "0.11.13", features = ["json"] }
axum = { version = "0.6.1", optional = true }
tower = { version = "0.4.13", optional = true }
tower-http = { version = "0.3.4", features = ["fs"], optional = true }
tokio = { version = "1.22.0", features = ["full"], optional = true }
http = { version = "0.2.8", optional = true }
[features]
default = ["csr"]
csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [
"dep:axum",
"dep:tower",
"dep:tower-http",
"dep:tokio",
"dep:http",
"leptos/ssr",
"leptos_axum",
"leptos_meta/ssr",
"leptos_router/ssr",
]
[package.metadata.cargo-all-features]
denylist = ["axum", "tower", "tower-http", "tokio", "http", "leptos_axum"]
skip_feature_sets = [["csr", "ssr"], ["csr", "hydrate"], ["ssr", "hydrate"]]

View File

@@ -1,29 +0,0 @@
# Leptos Hacker News Example with Axum
This example creates a basic clone of the Hacker News site. It showcases Leptos' ability to create both a client-side rendered app, and a server side rendered app with hydration, in a single repository. This repo differs from the main Hacker News example by using Axum as it's server.
## Client Side Rendering
To run it as a Client Side App, you can issue `trunk serve --open` in the root. This will build the entire
app into one CSR bundle.
> If you don't have `trunk` installed, [click here for install instructions.](https://trunkrs.dev/)
## Server Side Rendering With Hydration
To run it as a server side app with hydration, first you should run
```bash
wasm-pack build --target=web --no-default-features --features=hydrate
```
to generate the WebAssembly to hydrate the HTML that is generated on the server.
Then run the server with `cargo run` to serve the server side rendered HTML and the WASM bundle for hydration.
```bash
cargo run --no-default-features --features=ssr
```
> Note that if your hydration code changes, you will have to rerun the wasm-pack command above
> This should be temporary, and vastly improve once cargo-leptos becomes ready for prime time!

View File

@@ -1,72 +0,0 @@
use cfg_if::cfg_if;
use leptos::*;
// boilerplate to run in different modes
cfg_if! {
if #[cfg(feature = "ssr")] {
use axum::{
routing::{get},
Router,
error_handling::HandleError,
};
use http::StatusCode;
use std::net::SocketAddr;
use tower_http::services::ServeDir;
use std::env;
#[tokio::main]
async fn main() {
use leptos_hackernews_axum::*;
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
log::debug!("serving at {addr}");
simple_logger::init_with_level(log::Level::Debug).expect("couldn't initialize logging");
// These are Tower Services that will serve files from the static and pkg repos.
// HandleError is needed as Axum requires services to implement Infallible Errors
// because all Errors are converted into Responses
let static_service = HandleError::new( ServeDir::new("./static"), handle_file_error);
let pkg_service =HandleError::new( ServeDir::new("./pkg"), handle_file_error);
/// Convert the Errors from ServeDir to a type that implements IntoResponse
async fn handle_file_error(err: std::io::Error) -> (StatusCode, String) {
(
StatusCode::NOT_FOUND,
format!("File Not Found: {}", err),
)
}
let render_options: RenderOptions = RenderOptions::builder().pkg_path("/pkg/leptos_hackernews_axum").socket_address(addr).reload_port(3001).environment(&env::var("RUST_ENV")).build();
render_options.write_to_file();
// build our application with a route
let app = Router::new()
// `GET /` goes to `root`
.nest_service("/pkg", pkg_service)
.nest_service("/static", static_service)
.fallback(leptos_axum::render_app_to_stream(render_options, |cx| view! { cx, <App/> }));
// run our app with hyper
// `axum::Server` is a re-export of `hyper::Server`
log!("listening on {}", addr);
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
}
// client-only stuff for Trunk
else {
use leptos_hackernews_axum::*;
pub fn main() {
console_error_panic_hook::set_once();
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to_body(|cx| {
view! { cx, <App/> }
});
}
}
}

View File

@@ -1,103 +0,0 @@
use crate::api;
use leptos::*;
use leptos_router::*;
#[component]
pub fn Story(cx: Scope) -> Element {
let params = use_params_map(cx);
let story = create_resource(
cx,
move || params().get("id").cloned().unwrap_or_default(),
move |id| async move { api::fetch_api::<api::Story>(&api::story(&format!("item/{id}"))).await },
);
view! { cx,
<div>
{move || story.read().map(|story| match story {
None => view! { cx, <div class="item-view">"Error loading this story."</div> },
Some(story) => view! { cx,
<div class="item-view">
<div class="item-view-header">
<a href=story.url target="_blank">
<h1>{story.title}</h1>
</a>
<span class="host">
"("{story.domain}")"
</span>
{story.user.map(|user| view! { cx, <p class="meta">
{story.points}
" points | by "
<A href=format!("/users/{}", user)>{user.clone()}</A>
{format!(" {}", story.time_ago)}
</p>})}
</div>
<div class="item-view-comments">
<p class="item-view-comments-header">
{if story.comments_count.unwrap_or_default() > 0 {
format!("{} comments", story.comments_count.unwrap_or_default())
} else {
"No comments yet.".into()
}}
</p>
<ul class="comment-children">
<For each=move || story.comments.clone().unwrap_or_default() key=|comment| comment.id>
{move |cx, comment: &api::Comment| view! { cx, <Comment comment=comment.clone() /> }}
</For>
</ul>
</div>
</div>
}})}
</div>
}
}
#[component]
pub fn Comment(cx: Scope, comment: api::Comment) -> Element {
let (open, set_open) = create_signal(cx, true);
view! { cx,
<li class="comment">
<div class="by">
<A href=format!("/users/{}", comment.user.clone().unwrap_or_default())>{comment.user.clone()}</A>
{format!(" {}", comment.time_ago)}
</div>
<div class="text" inner_html=comment.content></div>
{(!comment.comments.is_empty()).then(|| {
view! { cx,
<div>
<div class="toggle" class:open=open>
<a on:click=move |_| set_open.update(|n| *n = !*n)>
{
let comments_len = comment.comments.len();
move || if open() {
"[-]".into()
} else {
format!("[+] {}{} collapsed", comments_len, pluralize(comments_len))
}
}
</a>
</div>
{move || open().then({
let comments = comment.comments.clone();
move || view! { cx,
<ul class="comment-children">
<For each=move || comments.clone() key=|comment| comment.id>
{|cx, comment: &api::Comment| view! { cx, <Comment comment=comment.clone() /> }}
</For>
</ul>
}
})}
</div>
}
})}
</li>
}
}
fn pluralize(n: usize) -> &'static str {
if n == 1 {
" reply"
} else {
" replies"
}
}

View File

@@ -1,39 +0,0 @@
use crate::api::{self, User};
use leptos::*;
use leptos_router::*;
#[component]
pub fn User(cx: Scope) -> Element {
let params = use_params_map(cx);
let user = create_resource(
cx,
move || params().get("id").cloned().unwrap_or_default(),
move |id| async move { api::fetch_api::<User>(&api::user(&id)).await },
);
view! { cx,
<div class="user-view">
{move || user.read().map(|user| match user {
None => view! { cx, <h1>"User not found."</h1> },
Some(user) => view! { cx,
<div>
<h1>"User: " {&user.id}</h1>
<ul class="meta">
<li>
<span class="label">"Created: "</span> {user.created}
</li>
<li>
<span class="label">"Karma: "</span> {user.karma}
</li>
{user.about.as_ref().map(|about| view! { cx, <li inner_html=about class="about"></li> })}
</ul>
<p class="links">
<a href=format!("https://news.ycombinator.com/submitted?id={}", user.id)>"submissions"</a>
" | "
<a href=format!("https://news.ycombinator.com/threads?id={}", user.id)>"comments"</a>
</p>
</div>
}
})}
</div>
}
}

View File

@@ -1,5 +1,5 @@
[package]
name = "leptos-hackernews"
name = "hackernews"
version = "0.1.0"
edition = "2021"
@@ -14,21 +14,22 @@ console_log = "0.2"
console_error_panic_hook = "0.1"
futures = "0.3"
cfg-if = "1"
leptos = { version = "0.0.20", default-features = false, features = ["serde"] }
leptos_meta = { version = "0.0", default-features = false }
leptos_actix = { version = "0.0.2", default-features = false, optional = true }
leptos_router = { version = "0.0", default-features = false }
leptos = { path = "../../leptos", default-features = false, features = ["serde"] }
leptos_meta = { path = "../../meta", default-features = false }
leptos_actix = { path = "../../integrations/actix", default-features = false, optional = true }
leptos_router = { path = "../../router", default-features = false }
log = "0.4"
simple_logger = "2"
simple_logger = "4.0.0"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
gloo-net = { version = "0.2", features = ["http"] }
reqwest = { version = "0.11", features = ["json"] }
# openssl = { version = "0.10", features = ["v110"] }
wasm-bindgen = "0.2"
web-sys = { version = "0.3", features = ["AbortController", "AbortSignal"] }
tracing = "0.1"
[features]
default = ["csr"]
csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [
@@ -43,3 +44,47 @@ ssr = [
[package.metadata.cargo-all-features]
denylist = ["actix-files", "actix-web", "leptos_actix"]
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 = "hackernews"
# 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-address = "127.0.0.1:3000"
# The port to use for automatic reload monitoring
reload-port = 3001
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
end2end-cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha 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

View File

@@ -0,0 +1,4 @@
[tasks.build]
command = "cargo"
args = ["+nightly", "build-all-features"]
install_crate = "cargo-all-features"

View File

@@ -1,29 +1,40 @@
# Leptos Hacker News Example
This example creates a basic clone of the Hacker News site. It showcases Leptoss ability to create both a client-side rendered app, and a server side rendered app with hydration, in a single repository. It uses Actix as its backend.
This example creates a basic clone of the Hacker News site. It showcases Leptos' ability to create both a client-side rendered app, and a server side rendered app with hydration, in a single repository
## Client Side Rendering
To run it as a Client Side App, you can issue `trunk serve --open` in the root. This will build the entire
app into one CSR bundle. Make sure you have trunk installed with `cargo install trunk`.
To run it as a Client Side App, you can issue `trunk serve --open` in the root. This will build the entire
app into one CSR bundle.
> If you don't have `trunk` installed, [click here for install instructions.](https://trunkrs.dev/)
## Server Side Rendering With Hydration
To run it as a server side app with hydration, first you should run
## Server Side Rendering with cargo-leptos
cargo-leptos is now the easiest and most featureful way to build server side rendered apps with hydration. It provides automatic recompilation of client and server code, wasm optimisation, CSS minification, and more! Check out more about it [here](https://github.com/akesson/cargo-leptos)
1. Install cargo-leptos
```bash
wasm-pack build --target=web --no-default-features --features=hydrate
cargo install --locked cargo-leptos
```
2. Build the site in watch mode, recompiling on file changes
```bash
cargo leptos watch
```
3. When ready to deploy, run
```bash
cargo leptos build --release
```
to generate the WebAssembly to hydrate the HTML that is generated on the server.
Then run the server with `cargo run` to serve the server side rendered HTML and the WASM bundle for hydration.
## Server Side Rendering without cargo-leptos
To run it as a server side app with hydration, you'll need to have wasm-pack installed.
0. Edit the `[package.metadata.leptos]` section and set `site-root` to `"pkg"`. You'll also want to change the path of the `<StyleSheet / >` component in the root component to point towards the CSS file in the root. This tells leptos that the WASM/JS files generated by wasm-pack are available at `./pkg` and that the CSS files are no longer processed by cargo-leptos. Building to alternative folders is not supported at this time.
1. Install wasm-pack
```bash
cargo install wasm-pack
```
2. Build the Webassembly used to hydrate the HTML from the server
```bash
wasm-pack build --target=web --debug --no-default-features --features=hydrate
```
3. Run the server to serve the Webassembly, JS, and HTML
```bash
cargo run --no-default-features --features=ssr
```
> Note that if your hydration code changes, you will have to rerun the wasm-pack command above
> This should be temporary, and vastly improve once cargo-leptos becomes ready for prime time!

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,4 +1,4 @@
use leptos::{on_cleanup, Scope, Serializable};
use leptos::{Scope, Serializable};
use serde::{Deserialize, Serialize};
pub fn story(path: &str) -> String {
@@ -29,7 +29,7 @@ where
// abort in-flight requests if the Scope is disposed
// i.e., if we've navigated away from this page
on_cleanup(cx, move || {
leptos::on_cleanup(cx, move || {
if let Some(abort_controller) = abort_controller {
abort_controller.abort()
}
@@ -38,7 +38,7 @@ where
}
#[cfg(feature = "ssr")]
pub async fn fetch_api<T>(cx: Scope, path: &str) -> Option<T>
pub async fn fetch_api<T>(_cx: Scope, path: &str) -> Option<T>
where
T: Serializable,
{

View File

@@ -1,5 +1,5 @@
use cfg_if::cfg_if;
use leptos::*;
use leptos::{component, view, IntoView, Scope};
use leptos_meta::*;
use leptos_router::*;
mod api;
@@ -10,25 +10,25 @@ use routes::story::*;
use routes::users::*;
#[component]
pub fn App(cx: Scope) -> Element {
provide_context(cx, MetaContext::default());
pub fn App(cx: Scope) -> impl IntoView {
provide_meta_context(cx);
view! {
cx,
<div>
<Stylesheet href="/style.css"/>
<>
<Stylesheet id="leptos" href="/pkg/hackernews.css"/>
<Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/>
<Meta name="description" content="Leptos implementation of a HackerNews demo."/>
<Router>
<Nav />
<main>
<Routes>
<Route path="users/:id" element=|cx| view! { cx, <User/> }/>
<Route path="stories/:id" element=|cx| view! { cx, <Story/> }/>
<Route path="*stories" element=|cx| view! { cx, <Stories/> }/>
<Route path="users/:id" view=|cx| view! { cx, <User/> }/>
<Route path="stories/:id" view=|cx| view! { cx, <Story/> }/>
<Route path=":stories?" view=|cx| view! { cx, <Stories/> }/>
</Routes>
</main>
</Router>
</div>
</>
}
}
@@ -41,7 +41,7 @@ cfg_if! {
pub fn hydrate() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
leptos::hydrate(body().unwrap(), move |cx| {
leptos::mount_to_body(move |cx| {
view! { cx, <App/> }
});
}

View File

@@ -7,26 +7,35 @@ cfg_if! {
if #[cfg(feature = "ssr")] {
use actix_files::{Files};
use actix_web::*;
use leptos_hackernews::*;
use std::{net::SocketAddr, env};
use hackernews::{App,AppProps};
use leptos_actix::{LeptosRoutes, generate_route_list};
#[get("/style.css")]
async fn css() -> impl Responder {
actix_files::NamedFile::open_async("./style.css").await
}
#[get("/favicon.ico")]
async fn favicon() -> impl Responder {
actix_files::NamedFile::open_async("./target/site//favicon.ico").await
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let addr = SocketAddr::from(([127,0,0,1],3000));
let conf = get_configuration(Some("Cargo.toml")).await.unwrap();
let addr = conf.leptos_options.site_address.clone();
// Generate the list of routes in your Leptos App
let routes = generate_route_list(|cx| view! { cx, <App/> });
HttpServer::new(move || {
let render_options: RenderOptions = RenderOptions::builder().pkg_path("/pkg/leptos_hackernews").reload_port(3001).socket_address(addr.clone()).environment(&env::var("RUST_ENV")).build();
render_options.write_to_file();
let leptos_options = &conf.leptos_options;
let site_root = &leptos_options.site_root;
App::new()
.service(Files::new("/pkg", "./pkg"))
.service(css)
.service(favicon)
.route("/api/{tail:.*}", leptos_actix::handle_server_fns())
.route("/{tail:.*}", leptos_actix::render_app_to_stream(render_options, |cx| view! { cx, <App/> }))
.leptos_routes(leptos_options.to_owned(), routes.to_owned(), |cx| view! { cx, <App/> })
.service(Files::new("/", &site_root))
//.wrap(middleware::Compress::default())
})
.bind(&addr)?

View File

@@ -1,12 +1,12 @@
use leptos::*;
use leptos::{component, Scope, IntoView, view};
use leptos_router::*;
#[component]
pub fn Nav(cx: Scope) -> Element {
pub fn Nav(cx: Scope) -> impl IntoView {
view! { cx,
<header class="header">
<nav class="inner">
<A href="/" class="home".to_string()>
<A href="/">
<strong>"HN"</strong>
</A>
<A href="/new">

View File

@@ -14,7 +14,7 @@ fn category(from: &str) -> &'static str {
}
#[component]
pub fn Stories(cx: Scope) -> Element {
pub fn Stories(cx: Scope) -> impl IntoView {
let query = use_query_map(cx);
let params = use_params_map(cx);
let page = move || {
@@ -54,14 +54,14 @@ pub fn Stories(cx: Scope) -> Element {
>
"< prev"
</a>
}
}.into_any()
} else {
view! {
cx,
<span class="page-link disabled" aria-hidden="true">
"< prev"
</span>
}
}.into_any()
}}
</span>
<span>"page " {page}</span>
@@ -79,24 +79,26 @@ pub fn Stories(cx: Scope) -> Element {
<main class="news-list">
<div>
<Transition
fallback=view! { cx, <p>"Loading..."</p> }
set_pending
fallback=move || view! { cx, <p>"Loading..."</p> }
set_pending=set_pending.into()
>
{move || match stories.read() {
None => None,
Some(None) => Some(view! { cx, <p>"Error loading stories."</p> }),
Some(None) => Some(view! { cx, <p>"Error loading stories."</p> }.into_any()),
Some(Some(stories)) => {
Some(view! { cx,
<ul>
<For each=move || stories.clone() key=|story| story.id>{
move |cx: Scope, story: &api::Story| {
<For
each=move || stories.clone()
key=|story| story.id
view=move |story: api::Story| {
view! { cx,
<Story story=story.clone() />
<Story story/>
}
}
}</For>
/>
</ul>
})
}.into_any())
}
}}
</Transition>
@@ -107,7 +109,7 @@ pub fn Stories(cx: Scope) -> Element {
}
#[component]
fn Story(cx: Scope, story: api::Story) -> Element {
fn Story(cx: Scope, story: api::Story) -> impl IntoView {
view! { cx,
<li class="news-item">
<span class="score">{story.points}</span>
@@ -120,10 +122,10 @@ fn Story(cx: Scope, story: api::Story) -> Element {
</a>
<span class="host">"("{story.domain}")"</span>
</span>
}
}.into_view(cx)
} else {
let title = story.title.clone();
view! { cx, <A href=format!("/stories/{}", story.id)>{title.clone()}</A> }
view! { cx, <A href=format!("/stories/{}", story.id)>{title.clone()}</A> }.into_view(cx)
}}
</span>
<br />
@@ -132,7 +134,7 @@ fn Story(cx: Scope, story: api::Story) -> Element {
view! { cx,
<span>
{"by "}
{story.user.map(|user| view ! { cx, <A href=format!("/users/{}", user)>{user.clone()}</A>})}
{story.user.map(|user| view ! { cx, <A href=format!("/users/{user}")>{user.clone()}</A>})}
{format!(" {} | ", story.time_ago)}
<A href=format!("/stories/{}", story.id)>
{if story.comments_count.unwrap_or_default() > 0 {
@@ -142,17 +144,15 @@ fn Story(cx: Scope, story: api::Story) -> Element {
}}
</A>
</span>
}
}.into_view(cx)
} else {
let title = story.title.clone();
view! { cx, <A href=format!("/item/{}", story.id)>{title.clone()}</A> }
view! { cx, <A href=format!("/item/{}", story.id)>{title.clone()}</A> }.into_view(cx)
}}
</span>
{(story.story_type != "link").then(|| view! { cx,
<span>
//{" "}
<span class="label">{story.story_type}</span>
</span>
" "
<span class="label">{story.story_type}</span>
})}
</li>
}

View File

@@ -4,7 +4,7 @@ use leptos_meta::*;
use leptos_router::*;
#[component]
pub fn Story(cx: Scope) -> Element {
pub fn Story(cx: Scope) -> impl IntoView {
let params = use_params_map(cx);
let story = create_resource(
cx,
@@ -17,51 +17,56 @@ pub fn Story(cx: Scope) -> Element {
}
},
);
let meta_description = move || story.read().and_then(|story| story.map(|story| story.title.clone())).unwrap_or_else(|| "Loading story...".to_string());
let meta_description = move || story.read().and_then(|story| story.map(|story| story.title)).unwrap_or_else(|| "Loading story...".to_string());
view! { cx,
<div>
<>
<Meta name="description" content=meta_description/>
{move || story.read().map(|story| match story {
None => view! { cx, <div class="item-view">"Error loading this story."</div> },
Some(story) => view! { cx,
<div class="item-view">
<div class="item-view-header">
<a href=story.url target="_blank">
<h1>{story.title}</h1>
</a>
<span class="host">
"("{story.domain}")"
</span>
{story.user.map(|user| view! { cx, <p class="meta">
{story.points}
" points | by "
<A href=format!("/users/{}", user)>{user.clone()}</A>
{format!(" {}", story.time_ago)}
</p>})}
<Suspense fallback=|| view! { cx, "Loading..." }>
{move || story.read().map(|story| match story {
None => view! { cx, <div class="item-view">"Error loading this story."</div> },
Some(story) => view! { cx,
<div class="item-view">
<div class="item-view-header">
<a href=story.url target="_blank">
<h1>{story.title}</h1>
</a>
<span class="host">
"("{story.domain}")"
</span>
{story.user.map(|user| view! { cx, <p class="meta">
{story.points}
" points | by "
<A href=format!("/users/{user}")>{user.clone()}</A>
{format!(" {}", story.time_ago)}
</p>})}
</div>
<div class="item-view-comments">
<p class="item-view-comments-header">
{if story.comments_count.unwrap_or_default() > 0 {
format!("{} comments", story.comments_count.unwrap_or_default())
} else {
"No comments yet.".into()
}}
</p>
<ul class="comment-children">
<For
each=move || story.comments.clone().unwrap_or_default()
key=|comment| comment.id
view=move |comment| view! { cx, <Comment comment /> }
/>
</ul>
</div>
</div>
<div class="item-view-comments">
<p class="item-view-comments-header">
{if story.comments_count.unwrap_or_default() > 0 {
format!("{} comments", story.comments_count.unwrap_or_default())
} else {
"No comments yet.".into()
}}
</p>
<ul class="comment-children">
<For each=move || story.comments.clone().unwrap_or_default() key=|comment| comment.id>
{move |cx, comment: &api::Comment| view! { cx, <Comment comment=comment.clone() /> }}
</For>
</ul>
</div>
</div>
}})}
</div>
}})
}
</Suspense>
</>
}
}
#[component]
pub fn Comment(cx: Scope, comment: api::Comment) -> Element {
pub fn Comment(cx: Scope, comment: api::Comment) -> impl IntoView {
let (open, set_open) = create_signal(cx, true);
view! { cx,
@@ -90,9 +95,11 @@ pub fn Comment(cx: Scope, comment: api::Comment) -> Element {
let comments = comment.comments.clone();
move || view! { cx,
<ul class="comment-children">
<For each=move || comments.clone() key=|comment| comment.id>
{|cx, comment: &api::Comment| view! { cx, <Comment comment=comment.clone() /> }}
</For>
<For
each=move || comments.clone()
key=|comment| comment.id
view=move |comment: api::Comment| view! { cx, <Comment comment /> }
/>
</ul>
}
})}

View File

@@ -3,7 +3,7 @@ use leptos::*;
use leptos_router::*;
#[component]
pub fn User(cx: Scope) -> Element {
pub fn User(cx: Scope) -> impl IntoView {
let params = use_params_map(cx);
let user = create_resource(
cx,
@@ -18,28 +18,30 @@ pub fn User(cx: Scope) -> Element {
);
view! { cx,
<div class="user-view">
{move || user.read().map(|user| match user {
None => view! { cx, <h1>"User not found."</h1> },
Some(user) => view! { cx,
<div>
<h1>"User: " {&user.id}</h1>
<ul class="meta">
<li>
<span class="label">"Created: "</span> {user.created}
</li>
<li>
<span class="label">"Karma: "</span> {user.karma}
</li>
{user.about.as_ref().map(|about| view! { cx, <li inner_html=about class="about"></li> })}
</ul>
<p class="links">
<a href=format!("https://news.ycombinator.com/submitted?id={}", user.id)>"submissions"</a>
" | "
<a href=format!("https://news.ycombinator.com/threads?id={}", user.id)>"comments"</a>
</p>
</div>
}
})}
<Suspense fallback=|| view! { cx, "Loading..." }>
{move || user.read().map(|user| match user {
None => view! { cx, <h1>"User not found."</h1> }.into_any(),
Some(user) => view! { cx,
<div>
<h1>"User: " {&user.id}</h1>
<ul class="meta">
<li>
<span class="label">"Created: "</span> {user.created}
</li>
<li>
<span class="label">"Karma: "</span> {user.karma}
</li>
{user.about.as_ref().map(|about| view! { cx, <li inner_html=about class="about"></li> })}
</ul>
<p class="links">
<a href=format!("https://news.ycombinator.com/submitted?id={}", user.id)>"submissions"</a>
" | "
<a href=format!("https://news.ycombinator.com/threads?id={}", user.id)>"comments"</a>
</p>
</div>
}.into_any()
})}
</Suspense>
</div>
}
}

View File

@@ -0,0 +1,98 @@
[package]
name = "hackernews_axum"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
anyhow = "1.0.66"
console_log = "0.2.0"
console_error_panic_hook = "0.1.7"
futures = "0.3.25"
cfg-if = "1.0.0"
leptos = { path = "../../leptos", default-features = false, features = [
"serde",
] }
leptos_axum = { path = "../../integrations/axum", optional = true }
leptos_meta = { path = "../../meta", default-features = false }
leptos_router = { path = "../../router", default-features = false }
log = "0.4.17"
simple_logger = "4.0.0"
serde = { version = "1.0.148", features = ["derive"] }
serde_json = "1.0.89"
gloo-net = { version = "0.2.5", features = ["http"] }
reqwest = { version = "0.11.13", features = ["json"] }
axum = { version = "0.6.1", optional = true }
tower = { version = "0.4.13", optional = true }
tower-http = { version = "0.3.4", features = ["fs"], optional = true }
tokio = { version = "1.22.0", features = ["full"], optional = true }
http = { version = "0.2.8", optional = true }
web-sys = { version = "0.3", features = ["AbortController", "AbortSignal"] }
wasm-bindgen = "0.2"
tracing = "0.1"
[features]
default = ["csr"]
csr = ["leptos/csr", "leptos_meta/csr", "leptos_router/csr"]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
ssr = [
"dep:axum",
"dep:tower",
"dep:tower-http",
"dep:tokio",
"dep:http",
"leptos/ssr",
"leptos_axum",
"leptos_meta/ssr",
"leptos_router/ssr",
]
[package.metadata.cargo-all-features]
denylist = ["axum", "tower", "tower-http", "tokio", "http", "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 = "hackernews_axum"
# 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-address = "127.0.0.1:3000"
# The port to use for automatic reload monitoring
reload-port = 3001
# [Optional] Command to use when running end2end tests. It will run in the end2end dir.
end2end-cmd = "npx playwright test"
# The browserlist query used for optimizing the CSS.
browserquery = "defaults"
# Set by cargo-leptos watch when building with tha 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

View File

@@ -0,0 +1,4 @@
[tasks.build]
command = "cargo"
args = ["+nightly", "build-all-features"]
install_crate = "cargo-all-features"

View File

@@ -0,0 +1,40 @@
# Leptos Hacker News Example with Axum
This example creates a basic clone of the Hacker News site. It showcases Leptos' ability to create both a client-side rendered app, and a server side rendered app with hydration, in a single repository. This repo differs from the main Hacker News example by using Axum as it's server.
## Client Side Rendering
To run it as a Client Side App, you can issue `trunk serve --open` in the root. This will build the entire
app into one CSR bundle. Make sure you have trunk installed with `cargo install trunk`.
## Server Side Rendering with cargo-leptos
cargo-leptos is now the easiest and most featureful way to build server side rendered apps with hydration. It provides automatic recompilation of client and server code, wasm optimisation, CSS minification, and more! Check out more about it [here](https://github.com/akesson/cargo-leptos)
1. Install cargo-leptos
```bash
cargo install --locked cargo-leptos
```
2. Build the site in watch mode, recompiling on file changes
```bash
cargo leptos watch
```
3. When ready to deploy, run
```bash
cargo leptos build --release
```
## Server Side Rendering without cargo-leptos
To run it as a server side app with hydration, you'll need to have wasm-pack installed.
0. Edit the `[package.metadata.leptos]` section and set `site-root` to `"pkg"`. You'll also want to change the path of the `<StyleSheet / >` component in the root component to point towards the CSS file in the root. This tells leptos that the WASM/JS files generated by wasm-pack are available at `./pkg` and that the CSS files are no longer processed by cargo-leptos. Building to alternative folders is not supported at this time.
1. Install wasm-pack
```bash
cargo install wasm-pack
```
2. Build the Webassembly used to hydrate the HTML from the server
```bash
wasm-pack build --target=web --debug --no-default-features --features=hydrate
```
3. Run the server to serve the Webassembly, JS, and HTML
```bash
cargo run --no-default-features --features=ssr
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,4 +1,4 @@
use leptos::Serializable;
use leptos::{on_cleanup, Scope, Serializable};
use serde::{Deserialize, Serialize};
pub fn story(path: &str) -> String {
@@ -10,11 +10,15 @@ pub fn user(path: &str) -> String {
}
#[cfg(not(feature = "ssr"))]
pub async fn fetch_api<T>(path: &str) -> Option<T>
pub async fn fetch_api<T>(cx: Scope, path: &str) -> Option<T>
where
T: Serializable,
{
let abort_controller = web_sys::AbortController::new().ok();
let abort_signal = abort_controller.as_ref().map(|a| a.signal());
let json = gloo_net::http::Request::get(path)
.abort_signal(abort_signal.as_ref())
.send()
.await
.map_err(|e| log::error!("{e}"))
@@ -22,11 +26,19 @@ where
.text()
.await
.ok()?;
// abort in-flight requests if the Scope is disposed
// i.e., if we've navigated away from this page
on_cleanup(cx, move || {
if let Some(abort_controller) = abort_controller {
abort_controller.abort()
}
});
T::from_json(&json).ok()
}
#[cfg(feature = "ssr")]
pub async fn fetch_api<T>(path: &str) -> Option<T>
pub async fn fetch_api<T>(cx: Scope, path: &str) -> Option<T>
where
T: Serializable,
{

View File

@@ -0,0 +1,41 @@
use cfg_if::cfg_if;
cfg_if! {
if #[cfg(feature = "ssr")] {
use axum::{
body::{boxed, Body, BoxBody},
extract::Extension,
http::{Request, Response, StatusCode, Uri},
};
use tower::ServiceExt;
use tower_http::services::ServeDir;
use std::sync::Arc;
use leptos::LeptosOptions;
pub async fn file_handler(uri: Uri, Extension(options): Extension<Arc<LeptosOptions>>) -> Result<Response<BoxBody>, (StatusCode, String)> {
let options = &*options;
let root = options.site_root.clone();
let res = get_static_file(uri.clone(), &root).await?;
match res.status() {
StatusCode::OK => Ok(res),
_ => Err((res.status(), "File Not Found".to_string()))
}
}
async fn get_static_file(uri: Uri, root: &str) -> Result<Response<BoxBody>, (StatusCode, String)> {
let req = Request::builder().uri(uri.clone()).body(Body::empty()).unwrap();
let root_path = format!("{root}");
// `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot`
// This path is relative to the cargo root
match ServeDir::new(&root_path).oneshot(req).await {
Ok(res) => Ok(res.map(boxed)),
Err(err) => Err((
StatusCode::INTERNAL_SERVER_ERROR,
format!("Something went wrong: {}", err),
)),
}
}
}
}

View File

@@ -0,0 +1,66 @@
use cfg_if::cfg_if;
cfg_if! {
if #[cfg(feature = "ssr")] {
use axum::{
body::{boxed, Body, BoxBody},
http::{Request, Response, StatusCode, Uri},
};
use tower::ServiceExt;
use tower_http::services::ServeDir;
pub async fn file_handler(uri: Uri) -> Result<Response<BoxBody>, (StatusCode, String)> {
let res = get_static_file(uri.clone(), "/pkg").await?;
println!("FIRST URI{:?}", uri);
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<BoxBody>, (StatusCode, String)> {
let res = get_static_file(uri.clone(), "/static").await?;
println!("FIRST URI{:?}", uri);
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<BoxBody>, (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
println!("Base: {:#?}", base);
if base == "/static" {
match ServeDir::new("./static").oneshot(req).await {
Ok(res) => Ok(res.map(boxed)),
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.map(boxed)),
Err(err) => Err((
StatusCode::INTERNAL_SERVER_ERROR,
format!("Something went wrong: {}", err),
)),
}
} else{
Err((StatusCode::NOT_FOUND, "Not Found".to_string()))
}
}
}
}

View File

@@ -1,8 +1,10 @@
use cfg_if::cfg_if;
use leptos::*;
use leptos::{component, view, IntoView, Scope};
use leptos_meta::*;
use leptos_router::*;
mod api;
pub mod file;
pub mod handlers;
mod routes;
use routes::nav::*;
use routes::stories::*;
@@ -10,24 +12,25 @@ use routes::story::*;
use routes::users::*;
#[component]
pub fn App(cx: Scope) -> Element {
provide_context(cx, MetaContext::default());
pub fn App(cx: Scope) -> impl IntoView {
provide_meta_context(cx);
view! {
cx,
<div>
<Stylesheet href="/static/style.css"/>
<>
<Link rel="shortcut icon" type_="image/ico" href="/favicon.ico"/>
<Stylesheet id="leptos" href="/pkg/hackernews_axum.css"/>
<Meta name="description" content="Leptos implementation of a HackerNews demo."/>
<Router>
<Nav />
<main>
<Routes>
<Route path="users/:id" element=|cx| view! { cx, <User/> }/>
<Route path="stories/:id" element=|cx| view! { cx, <Story/> }/>
<Route path="*stories" element=|cx| view! { cx, <Stories/> }/>
<Route path="users/:id" view=|cx| view! { cx, <User/> }/>
<Route path="stories/:id" view=|cx| view! { cx, <Story/> }/>
<Route path=":stories?" view=|cx| view! { cx, <Stories/> }/>
</Routes>
</main>
</Router>
</div>
</>
}
}
@@ -40,7 +43,7 @@ cfg_if! {
pub fn hydrate() {
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
leptos::hydrate(body().unwrap(), move |cx| {
leptos::mount_to_body(move |cx| {
view! { cx, <App/> }
});
}

View File

@@ -0,0 +1,57 @@
use cfg_if::cfg_if;
use leptos::*;
// boilerplate to run in different modes
cfg_if! {
if #[cfg(feature = "ssr")] {
use axum::{
Router,
routing::get,
extract::Extension,
};
use leptos_axum::{generate_route_list, LeptosRoutes};
use std::sync::Arc;
use hackernews_axum::file::file_handler;
#[tokio::main]
async fn main() {
use hackernews_axum::*;
let conf = get_configuration(Some("Cargo.toml")).await.unwrap();
let leptos_options = conf.leptos_options;
let addr = leptos_options.site_address.clone();
let routes = generate_route_list(|cx| view! { cx, <App/> }).await;
simple_logger::init_with_level(log::Level::Debug).expect("couldn't initialize logging");
// build our application with a route
let app = Router::new()
.route("/favicon.ico", get(file_handler))
.leptos_routes(leptos_options.clone(), routes, |cx| view! { cx, <App/> } )
.fallback(file_handler)
.layer(Extension(Arc::new(leptos_options)));
// run our app with hyper
// `axum::Server` is a re-export of `hyper::Server`
log!("listening on {}", addr);
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
}
// client-only stuff for Trunk
else {
use hackernews_axum::*;
pub fn main() {
console_error_panic_hook::set_once();
_ = console_log::init_with_level(log::Level::Debug);
console_error_panic_hook::set_once();
mount_to_body(|cx| {
view! { cx, <App/> }
});
}
}
}

View File

@@ -1,8 +1,8 @@
use leptos::*;
use leptos::{component, Scope, IntoView, view};
use leptos_router::*;
#[component]
pub fn Nav(cx: Scope) -> Element {
pub fn Nav(cx: Scope) -> impl IntoView {
view! { cx,
<header class="header">
<nav class="inner">

View File

@@ -14,7 +14,7 @@ fn category(from: &str) -> &'static str {
}
#[component]
pub fn Stories(cx: Scope) -> Element {
pub fn Stories(cx: Scope) -> impl IntoView {
let query = use_query_map(cx);
let params = use_params_map(cx);
let page = move || {
@@ -32,11 +32,13 @@ pub fn Stories(cx: Scope) -> Element {
move || (page(), story_type()),
move |(page, story_type)| async move {
let path = format!("{}?page={}", category(&story_type), page);
api::fetch_api::<Vec<api::Story>>(&api::story(&path)).await
api::fetch_api::<Vec<api::Story>>(cx, &api::story(&path)).await
},
);
let (pending, set_pending) = create_signal(cx, false);
let hide_more_link = move || stories.read().unwrap_or(None).unwrap_or_default().len() < 28;
let hide_more_link =
move || pending() || stories.read().unwrap_or(None).unwrap_or_default().len() < 28;
view! {
cx,
@@ -52,14 +54,14 @@ pub fn Stories(cx: Scope) -> Element {
>
"< prev"
</a>
}
}.into_any()
} else {
view! {
cx,
<span class="page-link disabled" aria-hidden="true">
"< prev"
</span>
}
}.into_any()
}}
</span>
<span>"page " {page}</span>
@@ -76,25 +78,30 @@ pub fn Stories(cx: Scope) -> Element {
</div>
<main class="news-list">
<div>
<Suspense fallback=view! { cx, <p>"Loading..."</p> }>
<Transition
fallback=move || view! { cx, <p>"Loading..."</p> }
set_pending=set_pending.into()
>
{move || match stories.read() {
None => None,
Some(None) => Some(view! { cx, <p>"Error loading stories."</p> }),
Some(None) => Some(view! { cx, <p>"Error loading stories."</p> }.into_any()),
Some(Some(stories)) => {
Some(view! { cx,
<ul>
<For each=move || stories.clone() key=|story| story.id>{
move |cx: Scope, story: &api::Story| {
<For
each=move || stories.clone()
key=|story| story.id
view=move |story: api::Story| {
view! { cx,
<Story story=story.clone() />
<Story story/>
}
}
}</For>
/>
</ul>
})
}.into_any())
}
}}
</Suspense>
</Transition>
</div>
</main>
</div>
@@ -102,7 +109,7 @@ pub fn Stories(cx: Scope) -> Element {
}
#[component]
fn Story(cx: Scope, story: api::Story) -> Element {
fn Story(cx: Scope, story: api::Story) -> impl IntoView {
view! { cx,
<li class="news-item">
<span class="score">{story.points}</span>
@@ -115,10 +122,10 @@ fn Story(cx: Scope, story: api::Story) -> Element {
</a>
<span class="host">"("{story.domain}")"</span>
</span>
}
}.into_view(cx)
} else {
let title = story.title.clone();
view! { cx, <A href=format!("/stories/{}", story.id)>{title.clone()}</A> }
view! { cx, <A href=format!("/stories/{}", story.id)>{title.clone()}</A> }.into_view(cx)
}}
</span>
<br />
@@ -127,7 +134,7 @@ fn Story(cx: Scope, story: api::Story) -> Element {
view! { cx,
<span>
{"by "}
{story.user.map(|user| view ! { cx, <A href=format!("/users/{}", user)>{user.clone()}</A>})}
{story.user.map(|user| view ! { cx, <A href=format!("/users/{user}")>{user.clone()}</A>})}
{format!(" {} | ", story.time_ago)}
<A href=format!("/stories/{}", story.id)>
{if story.comments_count.unwrap_or_default() > 0 {
@@ -137,17 +144,15 @@ fn Story(cx: Scope, story: api::Story) -> Element {
}}
</A>
</span>
}
}.into_view(cx)
} else {
let title = story.title.clone();
view! { cx, <A href=format!("/item/{}", story.id)>{title.clone()}</A> }
view! { cx, <A href=format!("/item/{}", story.id)>{title.clone()}</A> }.into_view(cx)
}}
</span>
{(story.story_type != "link").then(|| view! { cx,
<span>
//{" "}
<span class="label">{story.story_type}</span>
</span>
" "
<span class="label">{story.story_type}</span>
})}
</li>
}

View File

@@ -0,0 +1,119 @@
use crate::api;
use leptos::*;
use leptos_meta::*;
use leptos_router::*;
#[component]
pub fn Story(cx: Scope) -> impl IntoView {
let params = use_params_map(cx);
let story = create_resource(
cx,
move || params().get("id").cloned().unwrap_or_default(),
move |id| async move {
if id.is_empty() {
None
} else {
api::fetch_api::<api::Story>(cx, &api::story(&format!("item/{id}"))).await
}
},
);
let meta_description = move || story.read().and_then(|story| story.map(|story| story.title)).unwrap_or_else(|| "Loading story...".to_string());
view! { cx,
<>
<Meta name="description" content=meta_description/>
<Suspense fallback=|| view! { cx, "Loading..." }>
{move || story.read().map(|story| match story {
None => view! { cx, <div class="item-view">"Error loading this story."</div> },
Some(story) => view! { cx,
<div class="item-view">
<div class="item-view-header">
<a href=story.url target="_blank">
<h1>{story.title}</h1>
</a>
<span class="host">
"("{story.domain}")"
</span>
{story.user.map(|user| view! { cx, <p class="meta">
{story.points}
" points | by "
<A href=format!("/users/{user}")>{user.clone()}</A>
{format!(" {}", story.time_ago)}
</p>})}
</div>
<div class="item-view-comments">
<p class="item-view-comments-header">
{if story.comments_count.unwrap_or_default() > 0 {
format!("{} comments", story.comments_count.unwrap_or_default())
} else {
"No comments yet.".into()
}}
</p>
<ul class="comment-children">
<For
each=move || story.comments.clone().unwrap_or_default()
key=|comment| comment.id
view=move |comment| view! { cx, <Comment comment /> }
/>
</ul>
</div>
</div>
}})
}
</Suspense>
</>
}
}
#[component]
pub fn Comment(cx: Scope, comment: api::Comment) -> impl IntoView {
let (open, set_open) = create_signal(cx, true);
view! { cx,
<li class="comment">
<div class="by">
<A href=format!("/users/{}", comment.user.clone().unwrap_or_default())>{comment.user.clone()}</A>
{format!(" {}", comment.time_ago)}
</div>
<div class="text" inner_html=comment.content></div>
{(!comment.comments.is_empty()).then(|| {
view! { cx,
<div>
<div class="toggle" class:open=open>
<a on:click=move |_| set_open.update(|n| *n = !*n)>
{
let comments_len = comment.comments.len();
move || if open() {
"[-]".into()
} else {
format!("[+] {}{} collapsed", comments_len, pluralize(comments_len))
}
}
</a>
</div>
{move || open().then({
let comments = comment.comments.clone();
move || view! { cx,
<ul class="comment-children">
<For
each=move || comments.clone()
key=|comment| comment.id
view=move |comment: api::Comment| view! { cx, <Comment comment /> }
/>
</ul>
}
})}
</div>
}
})}
</li>
}
}
fn pluralize(n: usize) -> &'static str {
if n == 1 {
" reply"
} else {
" replies"
}
}

View File

@@ -0,0 +1,47 @@
use crate::api::{self, User};
use leptos::*;
use leptos_router::*;
#[component]
pub fn User(cx: Scope) -> impl IntoView {
let params = use_params_map(cx);
let user = create_resource(
cx,
move || params().get("id").cloned().unwrap_or_default(),
move |id| async move {
if id.is_empty() {
None
} else {
api::fetch_api::<User>(cx, &api::user(&id)).await
}
},
);
view! { cx,
<div class="user-view">
<Suspense fallback=|| view! { cx, "Loading..." }>
{move || user.read().map(|user| match user {
None => view! { cx, <h1>"User not found."</h1> }.into_any(),
Some(user) => view! { cx,
<div>
<h1>"User: " {&user.id}</h1>
<ul class="meta">
<li>
<span class="label">"Created: "</span> {user.created}
</li>
<li>
<span class="label">"Karma: "</span> {user.karma}
</li>
{user.about.as_ref().map(|about| view! { cx, <li inner_html=about class="about"></li> })}
</ul>
<p class="links">
<a href=format!("https://news.ycombinator.com/submitted?id={}", user.id)>"submissions"</a>
" | "
<a href=format!("https://news.ycombinator.com/threads?id={}", user.id)>"comments"</a>
</p>
</div>
}.into_any()
})}
</Suspense>
</div>
}
}

View File

@@ -1,17 +0,0 @@
# Parent Child Example
This example highlights four different ways that child components can communicate with their parent:
1. <ButtonA/>: passing a WriteSignal as one of the child component props,
for the child component to write into and the parent to read
2. <ButtonB/>: passing a closure as one of the child component props, for
the child component to call
3. <ButtonC/>: adding a simple event listener on the child component itself
4. <ButtonD/>: providing a context that is used in the component (rather than prop drilling)
## Client Side Rendering
To run it as a Client Side App, you can issue `trunk serve --open` in the root. This will build the entire
app into one CSR bundle
> If you don't have `trunk` installed, [click here for install instructions.](https://trunkrs.dev/)

View File

@@ -0,0 +1,4 @@
[tasks.build]
command = "cargo"
args = ["+nightly", "build-all-features"]
install_crate = "cargo-all-features"

View File

@@ -2,6 +2,7 @@
<html>
<head>
<link data-trunk rel="rust" data-wasm-opt="z"/>
<link data-trunk rel="icon" type="image/ico" href="/public/favicon.ico"/>
<style>
.red {
color: red;

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -7,23 +7,21 @@ use web_sys::MouseEvent;
// for the child component to write into and the parent to read
// 2) <ButtonB/>: passing a closure as one of the child component props, for
// the child component to call
// 3) <ButtonC/>: adding a simple event listener on the child component itself
// 4) <ButtonD/>: providing a context that is used in the component (rather than prop drilling)
// 4) <ButtonC/>: providing a context that is used in the component (rather than prop drilling)
#[derive(Copy, Clone)]
struct SmallcapsContext(WriteSignal<bool>);
#[component]
pub fn App(cx: Scope) -> Element {
pub fn App(cx: Scope) -> impl IntoView {
// just some signals to toggle three classes on our <p>
let (red, set_red) = create_signal(cx, false);
let (right, set_right) = create_signal(cx, false);
let (italics, set_italics) = create_signal(cx, false);
let (smallcaps, set_smallcaps) = create_signal(cx, false);
// the newtype pattern isn't *necessary* here but is a good practice
// it avoids confusion with other possible future `WriteSignal<bool>` contexts
// and makes it easier to refer to it in ButtonD
// and makes it easier to refer to it in ButtonC
provide_context(cx, SmallcapsContext(set_smallcaps));
view! {
@@ -33,7 +31,6 @@ pub fn App(cx: Scope) -> Element {
// class: attributes take F: Fn() => bool, and these signals all implement Fn()
class:red=red
class:right=right
class:italics=italics
class:smallcaps=smallcaps
>
"Lorem ipsum sit dolor amet."
@@ -45,18 +42,19 @@ pub fn App(cx: Scope) -> Element {
// Button B: pass a closure
<ButtonB on_click=move |_| set_right.update(|value| *value = !*value)/>
// Button C: components that return an Element, like elements, can take on: event handler attributes
<ButtonC on:click=move |_| set_italics.update(|value| *value = !*value)/>
// Button D gets its setter from context rather than props
<ButtonD/>
<ButtonC/>
</main>
}
}
// Button A receives a signal setter and updates the signal itself
/// Button A receives a signal setter and updates the signal itself
#[component]
pub fn ButtonA(cx: Scope, setter: WriteSignal<bool>) -> Element {
pub fn ButtonA(
cx: Scope,
/// Signal that will be toggled when the button is clicked.
setter: WriteSignal<bool>
) -> impl IntoView {
view! {
cx,
<button
@@ -67,9 +65,13 @@ pub fn ButtonA(cx: Scope, setter: WriteSignal<bool>) -> Element {
}
}
// Button B receives a closure
/// Button B receives a closure
#[component]
pub fn ButtonB<F>(cx: Scope, on_click: F) -> Element
pub fn ButtonB<F>(
cx: Scope,
/// Callback that will be invoked when the button is clicked.
on_click: F
) -> impl IntoView
where
F: Fn(MouseEvent) + 'static,
{
@@ -95,22 +97,10 @@ where
// if Rust ever had named function arguments we could drop this requirement
}
// Button C will have its event listener added by the parent
// This is just a way of encapsulating whatever markup you need for the button
/// Button D is very similar to Button A, but instead of passing the setter as a prop
/// we get it from the context
#[component]
pub fn ButtonC(cx: Scope) -> Element {
view! {
cx,
<button>
"Toggle Italics"
</button>
}
}
// Button D is very similar to Button A, but instead of passing the setter as a prop
// we get it from the context
#[component]
pub fn ButtonD(cx: Scope) -> Element {
pub fn ButtonC(cx: Scope) -> impl IntoView {
let setter = use_context::<SmallcapsContext>(cx).unwrap().0;
view! {

View File

@@ -11,7 +11,7 @@ leptos_router = { path = "../../router", features = ["csr"] }
serde = { version = "1", features = ["derive"] }
futures = "0.3"
console_error_panic_hook = "0.1.7"
leptos_meta = { path = "../../meta", default-features = false }
leptos_meta = { path = "../../meta", features = ["csr"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.0"

Some files were not shown because too many files have changed in this diff Show More