mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-28 11:21:55 -05:00
Compare commits
1 Commits
v0.6.12
...
actix_midd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55ef106c50 |
2
.github/workflows/ci-changed-examples.yml
vendored
2
.github/workflows/ci-changed-examples.yml
vendored
@@ -29,4 +29,4 @@ jobs:
|
||||
with:
|
||||
directory: ${{ matrix.directory }}
|
||||
cargo_make_task: "ci"
|
||||
toolchain: stable
|
||||
toolchain: nightly
|
||||
|
||||
2
.github/workflows/ci-examples.yml
vendored
2
.github/workflows/ci-examples.yml
vendored
@@ -24,4 +24,4 @@ jobs:
|
||||
with:
|
||||
directory: ${{ matrix.directory }}
|
||||
cargo_make_task: "ci"
|
||||
toolchain: stable
|
||||
toolchain: nightly
|
||||
|
||||
28
.github/workflows/ci-semver.yml
vendored
28
.github/workflows/ci-semver.yml
vendored
@@ -1,28 +0,0 @@
|
||||
name: CI semver
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
get-leptos-changed:
|
||||
uses: ./.github/workflows/get-leptos-changed.yml
|
||||
|
||||
test:
|
||||
needs: [get-leptos-changed]
|
||||
if: needs.get-leptos-changed.outputs.leptos_changed == 'true'
|
||||
name: Run semver check (nightly-2024-04-14)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Semver Checks
|
||||
uses: obi1kenobi/cargo-semver-checks-action@v2
|
||||
with:
|
||||
rust-toolchain: nightly-2024-04-14
|
||||
26
.github/workflows/ci-stable-examples.yml
vendored
Normal file
26
.github/workflows/ci-stable-examples.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: CI Stable Examples
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
get-leptos-changed:
|
||||
uses: ./.github/workflows/get-leptos-changed.yml
|
||||
|
||||
test:
|
||||
name: CI
|
||||
needs: [get-leptos-changed]
|
||||
if: needs.get-leptos-changed.outputs.leptos_changed == 'true'
|
||||
strategy:
|
||||
matrix:
|
||||
directory: [examples/counters_stable, examples/counter_without_macros]
|
||||
uses: ./.github/workflows/run-cargo-make-task.yml
|
||||
with:
|
||||
directory: ${{ matrix.directory }}
|
||||
cargo_make_task: "ci"
|
||||
toolchain: stable
|
||||
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -40,4 +40,4 @@ jobs:
|
||||
with:
|
||||
directory: ${{ matrix.directory }}
|
||||
cargo_make_task: "ci"
|
||||
toolchain: nightly-2024-04-14
|
||||
toolchain: nightly
|
||||
|
||||
@@ -31,9 +31,10 @@ jobs:
|
||||
dir_names: true
|
||||
dir_names_max_depth: "2"
|
||||
files: |
|
||||
examples/**
|
||||
!examples/cargo-make/**
|
||||
!examples/gtk/**
|
||||
examples
|
||||
!examples/cargo-make
|
||||
!examples/gtk
|
||||
!examples/hackernews_js_fetch
|
||||
!examples/Makefile.toml
|
||||
!examples/*.md
|
||||
json: true
|
||||
|
||||
6
.github/workflows/get-example-changed.yml
vendored
6
.github/workflows/get-example-changed.yml
vendored
@@ -21,12 +21,12 @@ jobs:
|
||||
|
||||
- name: Get example files that changed
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v43
|
||||
uses: tj-actions/changed-files@v41
|
||||
with:
|
||||
files: |
|
||||
examples/**
|
||||
!examples/cargo-make/**
|
||||
!examples/gtk/**
|
||||
!examples/cargo-make
|
||||
!examples/gtk
|
||||
!examples/Makefile.toml
|
||||
!examples/*.md
|
||||
|
||||
|
||||
4
.github/workflows/get-examples-matrix.yml
vendored
4
.github/workflows/get-examples-matrix.yml
vendored
@@ -17,8 +17,8 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install jq
|
||||
run: sudo apt-get install jq
|
||||
- name: Install JQ Tool
|
||||
uses: mbround18/install-jq@v1
|
||||
|
||||
- name: Set Matrix
|
||||
id: set-matrix
|
||||
|
||||
4
.github/workflows/get-leptos-changed.yml
vendored
4
.github/workflows/get-leptos-changed.yml
vendored
@@ -16,12 +16,10 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get source files that changed
|
||||
id: changed-source
|
||||
uses: tj-actions/changed-files@v43
|
||||
uses: tj-actions/changed-files@v41
|
||||
with:
|
||||
files: |
|
||||
integrations/**
|
||||
|
||||
29
.github/workflows/run-cargo-make-task.yml
vendored
29
.github/workflows/run-cargo-make-task.yml
vendored
@@ -27,9 +27,11 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Rust
|
||||
uses: dtolnay/rust-toolchain@master
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ inputs.toolchain }}
|
||||
override: true
|
||||
components: rustfmt
|
||||
|
||||
- name: Add wasm32-unknown-unknown
|
||||
run: rustup target add wasm32-unknown-unknown
|
||||
@@ -42,20 +44,8 @@ jobs:
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Install binstall
|
||||
uses: cargo-bins/cargo-binstall@main
|
||||
|
||||
- name: Install wasm-bindgen
|
||||
run: cargo binstall wasm-bindgen-cli --no-confirm
|
||||
|
||||
- name: Install wasm-pack
|
||||
run: cargo binstall wasm-pack --no-confirm
|
||||
|
||||
- name: Install cargo-leptos
|
||||
run: cargo binstall cargo-leptos --no-confirm
|
||||
|
||||
- name: Install Trunk
|
||||
uses: jetli/trunk-action@v0.5.0
|
||||
uses: jetli/trunk-action@v0.4.0
|
||||
with:
|
||||
version: "latest"
|
||||
|
||||
@@ -65,9 +55,9 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
node-version: 18
|
||||
|
||||
- uses: pnpm/action-setup@v3
|
||||
- uses: pnpm/action-setup@v2
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
@@ -79,7 +69,7 @@ jobs:
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
||||
@@ -117,11 +107,6 @@ jobs:
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Install Deno
|
||||
uses: denoland/setup-deno@v1
|
||||
with:
|
||||
deno-version: v1.x
|
||||
|
||||
# Run Cargo Make Task
|
||||
- name: ${{ inputs.cargo_make_task }}
|
||||
run: |
|
||||
|
||||
@@ -72,19 +72,12 @@ check-examples`.
|
||||
|
||||
## Before Submitting a PR
|
||||
|
||||
We have a fairly extensive CI setup that runs both lints (like `rustfmt` and `clippy`)
|
||||
We have a fairly extensive CI setup that runs both lints (like `rustfmt` and `clippy`)
|
||||
and tests on PRs. You can run most of these locally if you have `cargo-make` installed.
|
||||
|
||||
Note that some of the `rustfmt` settings used require usage of the nightly compiler.
|
||||
Formatting the code using the stable toolchain may result in a wrong code format and
|
||||
subsequently CI errors.
|
||||
Run `cargo +nightly fmt` if you want to keep the stable toolchain active.
|
||||
You may want to let your IDE automatically use the `+nightly` parameter when a
|
||||
"format on save" action is used.
|
||||
|
||||
If you added an example, make sure to add it to the list in `examples/Makefile.toml`.
|
||||
|
||||
From the root directory of the repo, run
|
||||
From the root directory of the repo, run
|
||||
- `cargo +nightly fmt`
|
||||
- `cargo +nightly make check`
|
||||
- `cargo +nightly make test`
|
||||
|
||||
31
Cargo.toml
31
Cargo.toml
@@ -1,9 +1,6 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
# utilities
|
||||
"oco",
|
||||
|
||||
# core
|
||||
"leptos",
|
||||
"leptos_dom",
|
||||
@@ -28,24 +25,22 @@ members = [
|
||||
exclude = ["benchmarks", "examples"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.6.11"
|
||||
rust-version = "1.75"
|
||||
version = "0.6.0-beta"
|
||||
|
||||
[workspace.dependencies]
|
||||
oco_ref = { path = "./oco", version = "0.1.0" }
|
||||
leptos = { path = "./leptos", version = "0.6.11" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.6.11" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.6.11" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.6.11" }
|
||||
leptos_reactive = { path = "./leptos_reactive", version = "0.6.11" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.6.11" }
|
||||
server_fn = { path = "./server_fn", version = "0.6.11" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.6.11" }
|
||||
leptos = { path = "./leptos", version = "0.6.0-beta" }
|
||||
leptos_dom = { path = "./leptos_dom", version = "0.6.0-beta" }
|
||||
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.6.0-beta" }
|
||||
leptos_macro = { path = "./leptos_macro", version = "0.6.0-beta" }
|
||||
leptos_reactive = { path = "./leptos_reactive", version = "0.6.0-beta" }
|
||||
leptos_server = { path = "./leptos_server", version = "0.6.0-beta" }
|
||||
server_fn = { path = "./server_fn", version = "0.6.0-beta" }
|
||||
server_fn_macro = { path = "./server_fn_macro", version = "0.6.0-beta" }
|
||||
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.6" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.6.11" }
|
||||
leptos_router = { path = "./router", version = "0.6.11" }
|
||||
leptos_meta = { path = "./meta", version = "0.6.11" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.6.11" }
|
||||
leptos_config = { path = "./leptos_config", version = "0.6.0-beta" }
|
||||
leptos_router = { path = "./router", version = "0.6.0-beta" }
|
||||
leptos_meta = { path = "./meta", version = "0.6.0-beta" }
|
||||
leptos_integration_utils = { path = "./integrations/utils", version = "0.6.0-beta" }
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
|
||||
59
README.md
59
README.md
@@ -40,25 +40,6 @@ pub fn SimpleCounter(initial_value: i32) -> impl IntoView {
|
||||
}
|
||||
}
|
||||
|
||||
// we also support a builder syntax rather than the JSX-like `view` macro
|
||||
#[component]
|
||||
pub fn SimpleCounterWithBuilder(initial_value: i32) -> impl IntoView {
|
||||
use leptos::html::*;
|
||||
|
||||
let (value, set_value) = create_signal(initial_value);
|
||||
let clear = move |_| set_value(0);
|
||||
let decrement = move |_| set_value.update(|value| *value -= 1);
|
||||
let increment = move |_| set_value.update(|value| *value += 1);
|
||||
|
||||
// the `view` macro above expands to this builder syntax
|
||||
div().child((
|
||||
button().on(ev::click, clear).child("Clear"),
|
||||
button().on(ev::click, decrement).child("-1"),
|
||||
span().child(("Value: ", value, "!")),
|
||||
button().on(ev::click, increment).child("+1")
|
||||
))
|
||||
}
|
||||
|
||||
// Easy to use with Trunk (trunkrs.dev) or with a simple wasm-bindgen setup
|
||||
pub fn main() {
|
||||
mount_to_body(|| view! {
|
||||
@@ -150,7 +131,7 @@ There are several people in the community using Leptos right now for internal ap
|
||||
|
||||
### Can I use this for native GUI?
|
||||
|
||||
Sure! Obviously the `view` macro is for generating DOM nodes but you can use the reactive system to drive any native GUI toolkit that uses the same kind of object-oriented, event-callback-based framework as the DOM pretty easily. The principles are the same:
|
||||
Sure! Obviously the `view` macro is for generating DOM nodes but you can use the reactive system to drive native any GUI toolkit that uses the same kind of object-oriented, event-callback-based framework as the DOM pretty easily. The principles are the same:
|
||||
|
||||
- Use signals, derived signals, and memos to create your reactive system
|
||||
- Create GUI widgets
|
||||
@@ -159,27 +140,35 @@ Sure! Obviously the `view` macro is for generating DOM nodes but you can use the
|
||||
|
||||
I've put together a [very simple GTK example](https://github.com/leptos-rs/leptos/blob/main/examples/gtk/src/main.rs) so you can see what I mean.
|
||||
|
||||
The new rendering approach being developed for 0.7 supports “universal rendering,” i.e., it can use any rendering library that supports a small set of 6-8 functions. (This is intended as a layer over typical retained-mode, OOP-style GUI toolkits like the DOM, GTK, etc.) That future rendering work will allow creating native UI in a way that is much more similar to the declarative approach used by the web framework.
|
||||
### How is this different from Yew/Dioxus?
|
||||
|
||||
### How is this different from Yew?
|
||||
|
||||
Yew is the most-used library for Rust web UI development, but there are several differences between Yew and Leptos, in philosophy, approach, and performance.
|
||||
On the surface level, these libraries may seem similar. Yew is, of course, the most mature Rust library for web UI development and has a huge ecosystem. Dioxus is similar in many ways, being heavily inspired by React. Here are some conceptual differences between Leptos and these frameworks:
|
||||
|
||||
- **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.
|
||||
- **Server integration:** Yew was created in an era in which browser-rendered single-page apps (SPAs) were the dominant paradigm. While Leptos supports client-side rendering, it also focuses on integrating with the server side of your application via server functions and multiple modes of serving HTML, including out-of-order streaming.
|
||||
- **Performance:** This has huge performance implications: Leptos is simply much faster at both creating and updating the UI than Yew is. (Dioxus has made huge advances in performance with its recent 0.3 release, and is now roughly on par with Leptos.)
|
||||
- **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. You can call functions, create timeouts, etc. within the body of your component functions because they won’t be re-run. You don’t need to think about manual dependency tracking for effects; fine-grained reactivity tracks dependencies automatically.
|
||||
|
||||
- ### How is this different from Dioxus?
|
||||
### How is this different from Sycamore?
|
||||
|
||||
Like Leptos, Dioxus is a framework for building UIs using web technologies. However, there are significant differences in approach and features.
|
||||
Conceptually, these two frameworks are very similar: because both are built on fine-grained reactivity, most apps will end up looking very similar between the two, and Sycamore or Leptos apps will both look a lot like SolidJS apps, in the same way that Yew or Dioxus can look a lot like React.
|
||||
|
||||
- **VDOM vs. fine-grained:** While Dioxus has a performant virtual DOM (VDOM), it still uses coarse-grained/component-scoped reactivity: changing a stateful value reruns the component function and diffs the old UI against the new one. Leptos components use a different mental model, creating (and returning) actual DOM nodes and setting up a reactive system to update those DOM nodes.
|
||||
- **Web vs. desktop priorities:** Dioxus uses Leptos server functions in its fullstack mode, but does not have the same `<Suspense>`-based support for things like streaming HTML rendering, or share the same focus on holistic web performance. Leptos tends to prioritize holistic web performance (streaming HTML rendering, smaller WASM binary sizes, etc.), whereas Dioxus has an unparalleled experience when building desktop apps, because your application logic runs as a native Rust binary.
|
||||
There are some practical differences that make a significant difference:
|
||||
|
||||
- ### How is this different from Sycamore?
|
||||
- **Templating:** Leptos uses a JSX-like template format (built on [syn-rsx](https://github.com/stoically/syn-rsx)) for its `view` macro. Sycamore offers the choice of its own templating DSL or a builder syntax.
|
||||
- **Server integration:** Leptos provides primitives that encourage HTML streaming and allow for easy async integration and RPC calls, even without WASM enabled, making it easy to opt into integrations between your frontend and backend code without pushing you toward any particular metaframework patterns.
|
||||
- **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(0);` _(If you prefer or if it's more convenient for your API, you can use [`create_rw_signal`](https://docs.rs/leptos/latest/leptos/fn.create_rw_signal.html) 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:
|
||||
|
||||
Sycamore and Leptos are both heavily influenced by SolidJS. At this point, Leptos has a larger community and ecosystem and is more actively developed. Other differences:
|
||||
```rust
|
||||
let (count, set_count) = create_signal(0); // a signal
|
||||
let double_count = move || count() * 2; // a derived signal
|
||||
let memoized_count = create_memo(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) { ... }
|
||||
```
|
||||
|
||||
- **Templating DSLs:** Sycamore uses a custom templating language for its views, while Leptos uses a JSX-like template format.
|
||||
- **`'static` signals:** One of Leptos’s main innovations was the creation of `Copy + 'static` signals, which have excellent ergonomics. Sycamore is in the process of adopting the same pattern, but this is not yet released.
|
||||
- **Perseus vs. server functions:** The Perseus metaframework provides an opinionated way to build Sycamore apps that include server functionality. Leptos instead provides primitives like server functions in the core of the framework.
|
||||
- **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.
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "benchmarks"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
l0410 = { package = "leptos", version = "0.4.10", features = [
|
||||
|
||||
@@ -3,5 +3,5 @@ alias = "check-all"
|
||||
|
||||
[tasks.check-all]
|
||||
command = "cargo"
|
||||
args = ["check-all-features"]
|
||||
args = ["+nightly", "check-all-features"]
|
||||
install_crate = "cargo-all-features"
|
||||
|
||||
@@ -8,11 +8,4 @@ args = ["fmt", "--", "--check", "--config-path", "${LEPTOS_PROJECT_DIRECTORY}"]
|
||||
[tasks.clippy-each-feature]
|
||||
dependencies = ["install-clippy"]
|
||||
command = "cargo"
|
||||
args = [
|
||||
"clippy",
|
||||
"--all-features",
|
||||
"--no-deps",
|
||||
"--",
|
||||
"-D",
|
||||
"clippy::print_stdout",
|
||||
]
|
||||
args = ["hack", "clippy", "--all", "--each-feature", "--no-dev-deps"]
|
||||
|
||||
@@ -3,5 +3,5 @@ alias = "test-all"
|
||||
|
||||
[tasks.test-all]
|
||||
command = "cargo"
|
||||
args = ["test-all-features"]
|
||||
args = ["+nightly", "test-all-features"]
|
||||
install_crate = "cargo-all-features"
|
||||
|
||||
1
docs/book_ru/.gitignore
vendored
1
docs/book_ru/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
book
|
||||
@@ -1,2 +0,0 @@
|
||||
Перевод в процессе, книга скоро будет доступна
|
||||
> Translation underway, book will be available soon
|
||||
@@ -1,10 +0,0 @@
|
||||
[output.html]
|
||||
additional-css = ["./mdbook-admonish.css"]
|
||||
[output.html.playground]
|
||||
runnable = false
|
||||
|
||||
[preprocessor]
|
||||
|
||||
[preprocessor.admonish]
|
||||
command = "mdbook-admonish"
|
||||
assets_version = "3.0.1" # не редактировать: управляется `mdbook-admonish install`
|
||||
@@ -1,345 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
:root {
|
||||
--md-admonition-icon--admonish-note: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z'/></svg>");
|
||||
--md-admonition-icon--admonish-abstract: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z'/></svg>");
|
||||
--md-admonition-icon--admonish-info: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z'/></svg>");
|
||||
--md-admonition-icon--admonish-tip: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.58.58 0 0 1-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27z'/></svg>");
|
||||
--md-admonition-icon--admonish-success: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m9 20.42-6.21-6.21 2.83-2.83L9 14.77l9.88-9.89 2.83 2.83L9 20.42z'/></svg>");
|
||||
--md-admonition-icon--admonish-question: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m15.07 11.25-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 0 0-2-2 2 2 0 0 0-2 2H8a4 4 0 0 1 4-4 4 4 0 0 1 4 4 3.2 3.2 0 0 1-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10c0-5.53-4.5-10-10-10z'/></svg>");
|
||||
--md-admonition-icon--admonish-warning: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 14h-2V9h2m0 9h-2v-2h2M1 21h22L12 2 1 21z'/></svg>");
|
||||
--md-admonition-icon--admonish-failure: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6.91 17.09 4 12 9.09 6.91 4 4 6.91 9.09 12 4 17.09 6.91 20 12 14.91 17.09 20 20 17.09 14.91 12 20 6.91z'/></svg>");
|
||||
--md-admonition-icon--admonish-danger: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 15H6l7-14v8h5l-7 14v-8z'/></svg>");
|
||||
--md-admonition-icon--admonish-bug: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 0 0-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z'/></svg>");
|
||||
--md-admonition-icon--admonish-example: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 0 1 .75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z'/></svg>");
|
||||
--md-admonition-icon--admonish-quote: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z'/></svg>");
|
||||
--md-details-icon: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42Z'/></svg>");
|
||||
}
|
||||
|
||||
:is(.admonition) {
|
||||
display: flow-root;
|
||||
margin: 1.5625em 0;
|
||||
padding: 0 1.2rem;
|
||||
color: var(--fg);
|
||||
page-break-inside: avoid;
|
||||
background-color: var(--bg);
|
||||
border: 0 solid black;
|
||||
border-inline-start-width: 0.4rem;
|
||||
border-radius: 0.2rem;
|
||||
box-shadow: 0 0.2rem 1rem rgba(0, 0, 0, 0.05), 0 0 0.1rem rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
@media print {
|
||||
:is(.admonition) {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
:is(.admonition) > * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:is(.admonition) :is(.admonition) {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
:is(.admonition) > .tabbed-set:only-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
html :is(.admonition) > :last-child {
|
||||
margin-bottom: 1.2rem;
|
||||
}
|
||||
|
||||
a.admonition-anchor-link {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: -1.2rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
a.admonition-anchor-link:link, a.admonition-anchor-link:visited {
|
||||
color: var(--fg);
|
||||
}
|
||||
a.admonition-anchor-link:link:hover, a.admonition-anchor-link:visited:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
a.admonition-anchor-link::before {
|
||||
content: "§";
|
||||
}
|
||||
|
||||
:is(.admonition-title, summary.admonition-title) {
|
||||
position: relative;
|
||||
min-height: 4rem;
|
||||
margin-block: 0;
|
||||
margin-inline: -1.6rem -1.2rem;
|
||||
padding-block: 0.8rem;
|
||||
padding-inline: 4.4rem 1.2rem;
|
||||
font-weight: 700;
|
||||
background-color: rgba(68, 138, 255, 0.1);
|
||||
print-color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
display: flex;
|
||||
}
|
||||
:is(.admonition-title, summary.admonition-title) p {
|
||||
margin: 0;
|
||||
}
|
||||
html :is(.admonition-title, summary.admonition-title):last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
:is(.admonition-title, summary.admonition-title)::before {
|
||||
position: absolute;
|
||||
top: 0.625em;
|
||||
inset-inline-start: 1.6rem;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
background-color: #448aff;
|
||||
print-color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"></svg>');
|
||||
-webkit-mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"></svg>');
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-size: contain;
|
||||
content: "";
|
||||
}
|
||||
:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
details.admonition > summary.admonition-title::after {
|
||||
position: absolute;
|
||||
top: 0.625em;
|
||||
inset-inline-end: 1.6rem;
|
||||
height: 2rem;
|
||||
width: 2rem;
|
||||
background-color: currentcolor;
|
||||
mask-image: var(--md-details-icon);
|
||||
-webkit-mask-image: var(--md-details-icon);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-size: contain;
|
||||
content: "";
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.25s;
|
||||
}
|
||||
details[open].admonition > summary.admonition-title::after {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-note) {
|
||||
border-color: #448aff;
|
||||
}
|
||||
|
||||
:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(68, 138, 255, 0.1);
|
||||
}
|
||||
:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #448aff;
|
||||
mask-image: var(--md-admonition-icon--admonish-note);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-note);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) {
|
||||
border-color: #00b0ff;
|
||||
}
|
||||
|
||||
:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(0, 176, 255, 0.1);
|
||||
}
|
||||
:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #00b0ff;
|
||||
mask-image: var(--md-admonition-icon--admonish-abstract);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-abstract);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-info, .admonish-todo) {
|
||||
border-color: #00b8d4;
|
||||
}
|
||||
|
||||
:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(0, 184, 212, 0.1);
|
||||
}
|
||||
:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #00b8d4;
|
||||
mask-image: var(--md-admonition-icon--admonish-info);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-info);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) {
|
||||
border-color: #00bfa5;
|
||||
}
|
||||
|
||||
:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(0, 191, 165, 0.1);
|
||||
}
|
||||
:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #00bfa5;
|
||||
mask-image: var(--md-admonition-icon--admonish-tip);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-tip);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) {
|
||||
border-color: #00c853;
|
||||
}
|
||||
|
||||
:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(0, 200, 83, 0.1);
|
||||
}
|
||||
:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #00c853;
|
||||
mask-image: var(--md-admonition-icon--admonish-success);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-success);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) {
|
||||
border-color: #64dd17;
|
||||
}
|
||||
|
||||
:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(100, 221, 23, 0.1);
|
||||
}
|
||||
:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #64dd17;
|
||||
mask-image: var(--md-admonition-icon--admonish-question);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-question);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) {
|
||||
border-color: #ff9100;
|
||||
}
|
||||
|
||||
:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(255, 145, 0, 0.1);
|
||||
}
|
||||
:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #ff9100;
|
||||
mask-image: var(--md-admonition-icon--admonish-warning);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-warning);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) {
|
||||
border-color: #ff5252;
|
||||
}
|
||||
|
||||
:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(255, 82, 82, 0.1);
|
||||
}
|
||||
:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #ff5252;
|
||||
mask-image: var(--md-admonition-icon--admonish-failure);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-failure);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-danger, .admonish-error) {
|
||||
border-color: #ff1744;
|
||||
}
|
||||
|
||||
:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(255, 23, 68, 0.1);
|
||||
}
|
||||
:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #ff1744;
|
||||
mask-image: var(--md-admonition-icon--admonish-danger);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-danger);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-bug) {
|
||||
border-color: #f50057;
|
||||
}
|
||||
|
||||
:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(245, 0, 87, 0.1);
|
||||
}
|
||||
:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #f50057;
|
||||
mask-image: var(--md-admonition-icon--admonish-bug);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-bug);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-example) {
|
||||
border-color: #7c4dff;
|
||||
}
|
||||
|
||||
:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(124, 77, 255, 0.1);
|
||||
}
|
||||
:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #7c4dff;
|
||||
mask-image: var(--md-admonition-icon--admonish-example);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-example);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
:is(.admonition):is(.admonish-quote, .admonish-cite) {
|
||||
border-color: #9e9e9e;
|
||||
}
|
||||
|
||||
:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) {
|
||||
background-color: rgba(158, 158, 158, 0.1);
|
||||
}
|
||||
:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before {
|
||||
background-color: #9e9e9e;
|
||||
mask-image: var(--md-admonition-icon--admonish-quote);
|
||||
-webkit-mask-image: var(--md-admonition-icon--admonish-quote);
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.navy :is(.admonition) {
|
||||
background-color: var(--sidebar-bg);
|
||||
}
|
||||
|
||||
.ayu :is(.admonition),
|
||||
.coal :is(.admonition) {
|
||||
background-color: var(--theme-hover);
|
||||
}
|
||||
|
||||
.rust :is(.admonition) {
|
||||
background-color: var(--sidebar-bg);
|
||||
color: var(--sidebar-fg);
|
||||
}
|
||||
.rust .admonition-anchor-link:link, .rust .admonition-anchor-link:visited {
|
||||
color: var(--sidebar-fg);
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/">
|
||||
<link rel="canonical" href="https://book.leptos.dev/">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/15_global_state.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/15_global_state.html">
|
||||
@@ -1,56 +0,0 @@
|
||||
# Summary
|
||||
|
||||
- [Introduction](./01_introduction.md)
|
||||
- [Getting Started](./getting_started/README.md)
|
||||
- [Leptos DX](./getting_started/leptos_dx.md)
|
||||
- [The Leptos Community and leptos-* Crates](./getting_started/community_crates.md)
|
||||
- [Part 1: Building User Interfaces](./view/README.md)
|
||||
- [A Basic Component](./view/01_basic_component.md)
|
||||
- [Dynamic Attributes](./view/02_dynamic_attributes.md)
|
||||
- [Components and Props](./view/03_components.md)
|
||||
- [Iteration](./view/04_iteration.md)
|
||||
- [Iterating over More Complex Data](./view/04b_iteration.md)
|
||||
- [Forms and Inputs](./view/05_forms.md)
|
||||
- [Control Flow](./view/06_control_flow.md)
|
||||
- [Error Handling](./view/07_errors.md)
|
||||
- [Parent-Child Communication](./view/08_parent_child.md)
|
||||
- [Passing Children to Components](./view/09_component_children.md)
|
||||
- [No Macros: The View Builder Syntax](./view/builder.md)
|
||||
- [Reactivity](./reactivity/README.md)
|
||||
- [Working with Signals](./reactivity/working_with_signals.md)
|
||||
- [Responding to Changes with `create_effect`](./reactivity/14_create_effect.md)
|
||||
- [Interlude: Reactivity and Functions](./reactivity/interlude_functions.md)
|
||||
- [Testing](./testing.md)
|
||||
- [Async](./async/README.md)
|
||||
- [Loading Data with Resources](./async/10_resources.md)
|
||||
- [Suspense](./async/11_suspense.md)
|
||||
- [Transition](./async/12_transition.md)
|
||||
- [Actions](./async/13_actions.md)
|
||||
- [Interlude: Projecting Children](./interlude_projecting_children.md)
|
||||
- [Global State Management](./15_global_state.md)
|
||||
- [Router](./router/README.md)
|
||||
- [Defining `<Routes/>`](./router/16_routes.md)
|
||||
- [Nested Routing](./router/17_nested_routing.md)
|
||||
- [Params and Queries](./router/18_params_and_queries.md)
|
||||
- [`<A/>`](./router/19_a.md)
|
||||
- [`<Form/>`](./router/20_form.md)
|
||||
- [Interlude: Styling](./interlude_styling.md)
|
||||
- [Metadata](./metadata.md)
|
||||
- [Client-Side Rendering: Wrapping Up](./csr_wrapping_up.md)
|
||||
- [Part 2: Server Side Rendering](./ssr/README.md)
|
||||
- [`cargo-leptos`](./ssr/21_cargo_leptos.md)
|
||||
- [The Life of a Page Load](./ssr/22_life_cycle.md)
|
||||
- [Async Rendering and SSR “Modes”](./ssr/23_ssr_modes.md)
|
||||
- [Hydration Bugs](./ssr/24_hydration_bugs.md)
|
||||
- [Working with the Server](./server/README.md)
|
||||
- [Server Functions](./server/25_server_functions.md)
|
||||
- [Extractors](./server/26_extractors.md)
|
||||
- [Responses and Redirects](./server/27_response.md)
|
||||
- [Progressive Enhancement and Graceful Degradation](./progressive_enhancement/README.md)
|
||||
- [`<ActionForm/>`s](./progressive_enhancement/action_form.md)
|
||||
- [Deployment](./deployment/README.md)
|
||||
- [Optimizing WASM Binary Size](./deployment/binary_size.md)
|
||||
- [Guide: Islands](./islands.md)
|
||||
|
||||
- [Appendix: How Does the Reactive System Work?](./appendix_reactive_graph.md)
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/appendix_reactive_graph.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/appendix_reactive_graph.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/async/10_resources.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/async/10_resources.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/async/11_suspense.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/async/11_suspense.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/async/12_transition.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/async/12_transition.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/async/13_action.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/async/13_action.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/async/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/async/index.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/csr_wrapping_up.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/csr_wrapping_up.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/deployment/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/deployment/index.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/deployment/binary_size.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/deployment/binary_size.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/getting_started/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/getting_started/index.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/getting_started/community_crates.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/getting_started/community_crates.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/getting_started/leptos_dx.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/getting_started/leptos_dx.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/interlude_projecting_children.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/interlude_projecting_children.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/interlude_styling.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/interlude_styling.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/islands.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/islands.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/metadata.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/metadata.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/progressive_enhancement/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/progressive_enhancement/index.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/progressive_enhancement/action_form.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/progressive_enhancement/action_form.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/reactivity/14_create_effect.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/reactivity/14_create_effect.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/reactivity/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/reactivity/index.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/reactivity/interlude_functions.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/reactivity/interlude_functions.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/reactivity/working_with_signals.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/reactivity/working_with_signals.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/16_routes.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/16_routes.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/17_nested_routing.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/17_nested_routing.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/18_params_and_queries.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/18_params_and_queries.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/19_a.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/19_a.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/20_form.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/20_form.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/router/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/router/index.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/server/25_server_functions.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/server/25_server_functions.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/server/26_extractors.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/server/26_extractors.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/server/27_response.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/server/27_response.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/server/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/server/index.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/ssr/21_cargo_leptos.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/ssr/21_cargo_leptos.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/ssr/22_life_cycle.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/ssr/22_life_cycle.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/ssr/23_ssr_modes.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/ssr/23_ssr_modes.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/ssr/24_hydration_bugs.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/ssr/24_hydration_bugs.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/ssr/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/ssr/index.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/testing.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/testing.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/01_basic_component.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/01_basic_component.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/02_dynamic_attributes.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/02_dynamic_attributes.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/03_components.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/03_components.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/04_iteration.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/04_iteration.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/04b_iteration.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/04b_iteration.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/05_forms.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/05_forms.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/06_control_flow.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/06_control_flow.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/07_errors.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/07_errors.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/08_parent_child.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/08_parent_child.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/09_component_children.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/09_component_children.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/index.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/index.html">
|
||||
@@ -1,2 +0,0 @@
|
||||
<meta http-equiv="refresh" content="0; URL=https://book.leptos.dev/view/builder.html">
|
||||
<link rel="canonical" href="https://book.leptos.dev/view/builder.html">
|
||||
@@ -5,41 +5,34 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
||||
CARGO_MAKE_CARGO_BUILD_TEST_FLAGS = ""
|
||||
CARGO_MAKE_WORKSPACE_EMULATION = true
|
||||
CARGO_MAKE_CRATE_WORKSPACE_MEMBERS = [
|
||||
"action-form-error-handling",
|
||||
"animated_show",
|
||||
"counter",
|
||||
"counter_isomorphic",
|
||||
"counters",
|
||||
"counters_stable",
|
||||
"counter_url_query",
|
||||
"counter_without_macros",
|
||||
"directives",
|
||||
"error_boundary",
|
||||
"errors_axum",
|
||||
"fetch",
|
||||
"hackernews",
|
||||
"hackernews_axum",
|
||||
"hackernews_islands_axum",
|
||||
"hackernews_js_fetch",
|
||||
"js-framework-benchmark",
|
||||
"login_with_token_csr_only",
|
||||
"parent_child",
|
||||
"portal",
|
||||
"router",
|
||||
"server_fns_axum",
|
||||
"session_auth_axum",
|
||||
"slots",
|
||||
"spread",
|
||||
"sso_auth_axum",
|
||||
"ssr_modes",
|
||||
"ssr_modes_axum",
|
||||
"suspense_tests",
|
||||
"tailwind_actix",
|
||||
"tailwind_axum",
|
||||
"tailwind_csr",
|
||||
"tailwind_axum",
|
||||
"timer",
|
||||
"todo_app_sqlite",
|
||||
"todo_app_sqlite_axum",
|
||||
"todo_app_sqlite_csr",
|
||||
"todomvc",
|
||||
]
|
||||
|
||||
@@ -47,16 +40,114 @@ CARGO_MAKE_CRATE_WORKSPACE_MEMBERS = [
|
||||
workspace = false
|
||||
description = "Generate the list of workspace members"
|
||||
script = '''
|
||||
examples=$(ls |
|
||||
grep -v .md |
|
||||
grep -v Makefile.toml |
|
||||
grep -v cargo-make |
|
||||
grep -v gtk |
|
||||
examples=$(ls |
|
||||
grep -v .md |
|
||||
grep -v Makefile.toml |
|
||||
grep -v cargo-make |
|
||||
grep -v gtk |
|
||||
jq -R -s -c 'split("\n")[:-1]')
|
||||
echo "CARGO_MAKE_CRATE_WORKSPACE_MEMBERS = $examples"
|
||||
'''
|
||||
|
||||
[tasks.test-report]
|
||||
workspace = false
|
||||
description = "show the cargo-make configuration for web examples [web|all|help]"
|
||||
script = { file = "./cargo-make/scripts/web-report.sh" }
|
||||
description = "report web testing technology used by examples - OPTION: [all]"
|
||||
script = '''
|
||||
set -emu
|
||||
|
||||
BOLD="\e[1m"
|
||||
GREEN="\e[0;32m"
|
||||
ITALIC="\e[3m"
|
||||
YELLOW="\e[0;33m"
|
||||
RESET="\e[0m"
|
||||
|
||||
echo
|
||||
echo "${YELLOW}Web Test Technology${RESET}"
|
||||
echo
|
||||
|
||||
makefile_paths=$(find . -name Makefile.toml -not -path '*/target/*' -not -path '*/node_modules/*' |
|
||||
sed 's%./%%' |
|
||||
sed 's%/Makefile.toml%%' |
|
||||
grep -v Makefile.toml |
|
||||
sort -u)
|
||||
|
||||
start_path=$(pwd)
|
||||
|
||||
for path in $makefile_paths; do
|
||||
cd $path
|
||||
|
||||
crate_symbols=
|
||||
|
||||
pw_count=$(find . -name playwright.config.ts | wc -l)
|
||||
|
||||
while read -r line; do
|
||||
case $line in
|
||||
*"cucumber"*)
|
||||
crate_symbols=$crate_symbols"C"
|
||||
;;
|
||||
*"fantoccini"*)
|
||||
crate_symbols=$crate_symbols"D"
|
||||
;;
|
||||
esac
|
||||
done <"./Cargo.toml"
|
||||
|
||||
while read -r line; do
|
||||
case $line in
|
||||
*"cargo-make/wasm-test.toml"*)
|
||||
crate_symbols=$crate_symbols"W"
|
||||
;;
|
||||
*"cargo-make/playwright-test.toml"*)
|
||||
crate_symbols=$crate_symbols"P"
|
||||
crate_symbols=$crate_symbols"N"
|
||||
;;
|
||||
*"cargo-make/playwright-trunk-test.toml"*)
|
||||
crate_symbols=$crate_symbols"P"
|
||||
crate_symbols=$crate_symbols"T"
|
||||
;;
|
||||
*"cargo-make/trunk_server.toml"*)
|
||||
crate_symbols=$crate_symbols"T"
|
||||
;;
|
||||
*"cargo-make/cargo-leptos-webdriver-test.toml"*)
|
||||
crate_symbols=$crate_symbols"L"
|
||||
;;
|
||||
*"cargo-make/cargo-leptos-test.toml"*)
|
||||
crate_symbols=$crate_symbols"L"
|
||||
if [ $pw_count -gt 0 ]; then
|
||||
crate_symbols=$crate_symbols"P"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done <"./Makefile.toml"
|
||||
|
||||
# Sort list of tools
|
||||
sorted_crate_symbols=$(echo ${crate_symbols} | grep -o . | sort | tr -d "\n")
|
||||
|
||||
formatted_crate_symbols=" ➤ ${BOLD}${YELLOW}${sorted_crate_symbols}${RESET}"
|
||||
crate_line=$path
|
||||
if [ ! -z ${1+x} ]; then
|
||||
# Show all examples
|
||||
if [ ! -z $crate_symbols ]; then
|
||||
crate_line=$crate_line$formatted_crate_symbols
|
||||
fi
|
||||
echo $crate_line
|
||||
elif [ ! -z $crate_symbols ]; then
|
||||
# Filter out examples that do not run tests in `ci`
|
||||
crate_line=$crate_line$formatted_crate_symbols
|
||||
echo $crate_line
|
||||
fi
|
||||
|
||||
cd ${start_path}
|
||||
done
|
||||
|
||||
c="${BOLD}${YELLOW}C${RESET} = Cucumber"
|
||||
d="${BOLD}${YELLOW}D${RESET} = WebDriver"
|
||||
l="${BOLD}${YELLOW}L${RESET} = Cargo Leptos"
|
||||
n="${BOLD}${YELLOW}N${RESET} = Node"
|
||||
p="${BOLD}${YELLOW}P${RESET} = Playwright"
|
||||
t="${BOLD}${YELLOW}T${RESET} = Trunk"
|
||||
w="${BOLD}${YELLOW}W${RESET} = WASM"
|
||||
|
||||
echo
|
||||
echo "${ITALIC}Keys:${RESET} $c, $d, $l, $n, $p, $t, $w"
|
||||
echo
|
||||
'''
|
||||
|
||||
@@ -8,7 +8,7 @@ To the extent that new features have been released or breaking changes have been
|
||||
|
||||
## Getting Started
|
||||
|
||||
The simplest way to get started with any example is to use the “quick start” command found in the README for each example. Most of the examples use either [`trunk`](https://trunkrs.dev/) (a simple build system and dev server for client-side-rendered apps) or [`cargo-leptos`](https://github.com/leptos-rs/cargo-leptos) (a build system for server-rendered and client-hydrated apps).
|
||||
The simplest way to get started with any example is to use the “quick start” command found in the README for each example. Most of the examples use either [`trunk`](https://trunkrs.dev/) (a simple build system and dev server for client-side-rendered apps) or [`cargo-leptos`](https://github.com/leptos-rs/cargo-leptos) (a build system for server-rendered and client-hydrated apps).
|
||||
|
||||
## Using Cargo Make
|
||||
|
||||
@@ -16,18 +16,16 @@ You can also run any of the examples using [`cargo-make`](https://github.com/sag
|
||||
|
||||
Follow these steps to get any example up and running.
|
||||
|
||||
1. `cd` to the example you want to run
|
||||
2. Make sure `cargo-make` is installed (for example by running `cargo install cargo-make`)
|
||||
3. Make sure `rustup target add wasm32-unknown-unknown` was executed for the currently selected toolchain.
|
||||
4. Run `cargo make ci` to setup and test the example
|
||||
5. Run `cargo make start` to run the example
|
||||
6. Open the client URL in the console output (<http://127.0.0.1:8080> or <http://127.0.0.1:3000> by default)
|
||||
7. Run `cargo make stop` to end any processes started by `cargo make start`.
|
||||
1. `cd` to the example root directory
|
||||
2. Run `cargo make ci` to setup and test the example
|
||||
3. Run `cargo make start` to run the example
|
||||
4. Open the client URL in the console output (<http://127.0.0.1:8080> or <http://127.0.0.1:3000> by default)
|
||||
5. Run `cargo make stop` to end any processes started by `cargo make start`.
|
||||
|
||||
Here are a few additional notes:
|
||||
|
||||
- Extendable custom task files are located in the [cargo-make](./cargo-make/) directory
|
||||
- Running a task will automatically install `cargo` dependencies
|
||||
- Running a task will automatically install `cargo` dependencies
|
||||
- Each `Makefile.toml` file must extend the [cargo-make/main.toml](./cargo-make/main.toml) file
|
||||
- [cargo-make](./cargo-make/) files that end in `*-test.toml` configure web testing strategies
|
||||
- Run `cargo make test-report` to learn which examples have web tests
|
||||
|
||||
@@ -7,7 +7,7 @@ edition = "2021"
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
|
||||
@@ -15,13 +15,13 @@ clear = true
|
||||
dependencies = ["check-debug", "check-release"]
|
||||
|
||||
[tasks.check-debug]
|
||||
toolchain = "stable"
|
||||
toolchain = "nightly"
|
||||
command = "cargo"
|
||||
args = ["check-all-features"]
|
||||
install_crate = "cargo-all-features"
|
||||
|
||||
[tasks.check-release]
|
||||
toolchain = "stable"
|
||||
toolchain = "nightly"
|
||||
command = "cargo"
|
||||
args = ["check-all-features", "--release"]
|
||||
install_crate = "cargo-all-features"
|
||||
|
||||
@@ -4,13 +4,11 @@ dependencies = [
|
||||
"clean-trunk",
|
||||
"clean-node_modules",
|
||||
"clean-playwright",
|
||||
"clean-pkg",
|
||||
]
|
||||
|
||||
[tasks.clean-cargo]
|
||||
script = '''
|
||||
find . -type d -name target | xargs rm -rf
|
||||
'''
|
||||
command = "rm"
|
||||
args = ["-rf", "target"]
|
||||
|
||||
[tasks.clean-trunk]
|
||||
script = '''
|
||||
@@ -29,8 +27,3 @@ fi
|
||||
script = '''
|
||||
find . -name playwright-report -name playwright -name test-results | xargs rm -rf
|
||||
'''
|
||||
|
||||
[tasks.clean-pkg]
|
||||
script = '''
|
||||
find . -type d -name pkg | xargs rm -rf
|
||||
'''
|
||||
|
||||
@@ -3,36 +3,32 @@
|
||||
[tasks.stop-client]
|
||||
condition = { env_set = ["CLIENT_PROCESS_NAME"] }
|
||||
script = '''
|
||||
if pidof -q ${CLIENT_PROCESS_NAME}; then
|
||||
echo " Stopping ${CLIENT_PROCESS_NAME}"
|
||||
if [ ! -z $(pidof ${CLIENT_PROCESS_NAME}) ]; then
|
||||
pkill -ef ${CLIENT_PROCESS_NAME}
|
||||
else
|
||||
echo " ${CLIENT_PROCESS_NAME} is already stopped"
|
||||
fi
|
||||
'''
|
||||
|
||||
[tasks.client-status]
|
||||
condition = { env_set = ["CLIENT_PROCESS_NAME"] }
|
||||
script = '''
|
||||
if pidof -q ${CLIENT_PROCESS_NAME}; then
|
||||
echo " ${CLIENT_PROCESS_NAME} is up"
|
||||
else
|
||||
if [ -z $(pidof ${CLIENT_PROCESS_NAME}) ]; then
|
||||
echo " ${CLIENT_PROCESS_NAME} is not running"
|
||||
else
|
||||
echo " ${CLIENT_PROCESS_NAME} is up"
|
||||
fi
|
||||
'''
|
||||
|
||||
[tasks.maybe-start-client]
|
||||
condition = { env_set = ["CLIENT_PROCESS_NAME"] }
|
||||
script = '''
|
||||
if pidof -q ${CLIENT_PROCESS_NAME}; then
|
||||
echo " ${CLIENT_PROCESS_NAME} is already started"
|
||||
else
|
||||
if [ -z $(pidof ${CLIENT_PROCESS_NAME}) ]; then
|
||||
echo " Starting ${CLIENT_PROCESS_NAME}"
|
||||
if [ -n "${SPAWN_CLIENT_PROCESS}" ];then
|
||||
echo "Spawning process..."
|
||||
if [ -z ${SPAWN_CLIENT_PROCESS} ];then
|
||||
cargo make start-client ${@} &
|
||||
else
|
||||
cargo make start-client ${@}
|
||||
fi
|
||||
else
|
||||
echo " ${CLIENT_PROCESS_NAME} is already started"
|
||||
fi
|
||||
'''
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[tasks.build]
|
||||
toolchain = "stable"
|
||||
toolchain = "nightly"
|
||||
command = "cargo"
|
||||
args = ["build-all-features"]
|
||||
install_crate = "cargo-all-features"
|
||||
|
||||
[tasks.check]
|
||||
toolchain = "stable"
|
||||
toolchain = "nightly"
|
||||
command = "cargo"
|
||||
args = ["check-all-features"]
|
||||
install_crate = "cargo-all-features"
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
[tasks.build]
|
||||
clear = true
|
||||
command = "deno"
|
||||
args = ["task", "build"]
|
||||
|
||||
[tasks.start-client]
|
||||
command = "deno"
|
||||
args = ["task", "start"]
|
||||
|
||||
[tasks.check]
|
||||
clear = true
|
||||
dependencies = ["check-debug", "check-release"]
|
||||
|
||||
[tasks.check-debug]
|
||||
toolchain = "stable"
|
||||
command = "cargo"
|
||||
args = ["check-all-features"]
|
||||
install_crate = "cargo-all-features"
|
||||
|
||||
[tasks.check-release]
|
||||
toolchain = "stable"
|
||||
command = "cargo"
|
||||
args = ["check-all-features", "--release"]
|
||||
install_crate = "cargo-all-features"
|
||||
@@ -1,5 +1,5 @@
|
||||
[tasks.pre-clippy]
|
||||
env = { CARGO_MAKE_CLIPPY_ARGS = "--no-deps --all-targets --all-features -- -D warnings" }
|
||||
env = { CARGO_MAKE_CLIPPY_ARGS = "--all-targets --all-features -- -D warnings" }
|
||||
|
||||
[tasks.check-style]
|
||||
dependencies = ["check-format-flow", "clippy-flow"]
|
||||
|
||||
@@ -6,17 +6,9 @@ extend = [
|
||||
[tasks.integration-test]
|
||||
description = "Run integration test with automated start and stop of processes"
|
||||
env = { SPAWN_CLIENT_PROCESS = "1" }
|
||||
run_task = { name = ["start", "wait-test-stop"], parallel = true }
|
||||
dependencies = ["start", "wait-one", "test-playwright", "stop"]
|
||||
|
||||
[tasks.wait-test-stop]
|
||||
private = true
|
||||
dependencies = ["wait-server", "test-playwright", "stop"]
|
||||
|
||||
[tasks.wait-server]
|
||||
[tasks.wait-one]
|
||||
script = '''
|
||||
for run in {1..12}; do
|
||||
echo "Waiting to ensure server is started..."
|
||||
sleep 10
|
||||
done
|
||||
echo "Times up, running tests"
|
||||
sleep 1
|
||||
'''
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -emu
|
||||
|
||||
BOLD="\e[1m"
|
||||
ITALIC="\e[3m"
|
||||
YELLOW="\e[1;33m"
|
||||
BLUE="\e[1;36m"
|
||||
RESET="\e[0m"
|
||||
|
||||
function web { #task: only include examples with web cargo-make configuration
|
||||
print_header
|
||||
print_crate_tags "$@"
|
||||
print_footer
|
||||
}
|
||||
|
||||
function all { #task: includes all examples
|
||||
print_header
|
||||
print_crate_tags "all"
|
||||
print_footer
|
||||
}
|
||||
|
||||
function print_header {
|
||||
echo -e "${YELLOW}Cargo Make Web Report${RESET}"
|
||||
echo
|
||||
echo -e "${ITALIC}Show how crates are configured to run and test web examples with cargo-make${RESET}"
|
||||
echo
|
||||
}
|
||||
|
||||
function print_crate_tags {
|
||||
local makefile_paths
|
||||
makefile_paths=$(find_makefile_lines)
|
||||
|
||||
local start_path
|
||||
start_path=$(pwd)
|
||||
|
||||
for path in $makefile_paths; do
|
||||
cd "$path"
|
||||
|
||||
local crate_tags=
|
||||
|
||||
# Add cargo tags
|
||||
while read -r line; do
|
||||
case $line in
|
||||
*"cucumber"*)
|
||||
crate_tags=$crate_tags"C"
|
||||
;;
|
||||
*"fantoccini"*)
|
||||
crate_tags=$crate_tags"F"
|
||||
;;
|
||||
*"package.metadata.leptos"*)
|
||||
crate_tags=$crate_tags"M"
|
||||
;;
|
||||
esac
|
||||
done <"./Cargo.toml"
|
||||
|
||||
#Add makefile tags
|
||||
|
||||
local pw_count
|
||||
pw_count=$(find . -name playwright.config.ts | wc -l)
|
||||
|
||||
while read -r line; do
|
||||
case $line in
|
||||
*"cargo-make/wasm-test.toml"*)
|
||||
crate_tags=$crate_tags"W"
|
||||
;;
|
||||
*"cargo-make/playwright-test.toml"*)
|
||||
crate_tags=$crate_tags"P"
|
||||
crate_tags=$crate_tags"N"
|
||||
;;
|
||||
*"cargo-make/playwright-trunk-test.toml"*)
|
||||
crate_tags=$crate_tags"P"
|
||||
crate_tags=$crate_tags"T"
|
||||
;;
|
||||
*"cargo-make/trunk_server.toml"*)
|
||||
crate_tags=$crate_tags"T"
|
||||
;;
|
||||
*"cargo-make/cargo-leptos-webdriver-test.toml"*)
|
||||
crate_tags=$crate_tags"L"
|
||||
;;
|
||||
*"cargo-make/cargo-leptos-test.toml"*)
|
||||
crate_tags=$crate_tags"L"
|
||||
if [ "$pw_count" -gt 0 ]; then
|
||||
crate_tags=$crate_tags"P"
|
||||
fi
|
||||
;;
|
||||
*"cargo-make/cargo-leptos.toml"*)
|
||||
crate_tags=$crate_tags"L"
|
||||
;;
|
||||
*"cargo-make/deno-build.toml"*)
|
||||
crate_tags=$crate_tags"D"
|
||||
;;
|
||||
esac
|
||||
done <"./Makefile.toml"
|
||||
|
||||
# Sort tags
|
||||
local keys
|
||||
keys=$(echo "$crate_tags" | grep -o . | sort | tr -d "\n")
|
||||
|
||||
# Find leptos projects that are not configured to build with cargo-leptos
|
||||
keys=${keys//"LM"/"L"}
|
||||
|
||||
# Find leptos projects that are not configured to build with deno
|
||||
keys=${keys//"DM"/"D"}
|
||||
|
||||
# Maybe print line
|
||||
local crate_line=$path
|
||||
|
||||
if [ -n "$crate_tags" ]; then
|
||||
local color=$YELLOW
|
||||
case $keys in
|
||||
*"M"*)
|
||||
color=$BLUE
|
||||
;;
|
||||
esac
|
||||
|
||||
crate_line="$crate_line ➤ ${color}$keys${RESET}"
|
||||
echo -e "$crate_line"
|
||||
elif [ "$#" -gt 0 ]; then
|
||||
crate_line="${BOLD}$crate_line${RESET}"
|
||||
echo -e "$crate_line"
|
||||
fi
|
||||
|
||||
cd "$start_path"
|
||||
done
|
||||
}
|
||||
|
||||
function find_makefile_lines {
|
||||
find . -name Makefile.toml -not -path '*/target/*' -not -path '*/node_modules/*' |
|
||||
sed 's%./%%' |
|
||||
sed 's%/Makefile.toml%%' |
|
||||
grep -v Makefile.toml |
|
||||
sort -u
|
||||
}
|
||||
|
||||
function print_footer {
|
||||
c="${BOLD}${YELLOW}C${RESET} = Cucumber Test Runner"
|
||||
d="${BOLD}${YELLOW}D${RESET} = Deno"
|
||||
f="${BOLD}${YELLOW}F${RESET} = Fantoccini WebDriver"
|
||||
l="${BOLD}${YELLOW}L${RESET} = Cargo Leptos"
|
||||
m="${BOLD}${BLUE}M${RESET} = Cargo Leptos Metadata Only (${ITALIC}ci is not configured to build with cargo-leptos or deno${RESET})"
|
||||
n="${BOLD}${YELLOW}N${RESET} = Node"
|
||||
p="${BOLD}${YELLOW}P${RESET} = Playwright Test"
|
||||
t="${BOLD}${YELLOW}T${RESET} = Trunk"
|
||||
w="${BOLD}${YELLOW}W${RESET} = WASM Test"
|
||||
|
||||
echo
|
||||
echo -e "${ITALIC}Report Keys:${RESET}\n $c\n $d\n $f\n $l\n $m\n $n\n $p\n $t\n $w"
|
||||
echo
|
||||
}
|
||||
|
||||
###################
|
||||
# HELP
|
||||
###################
|
||||
|
||||
function list_help_for {
|
||||
local task=$1
|
||||
grep -E "^function.+ #$task" "$0" |
|
||||
sed 's/function/ /' |
|
||||
sed -e "s| { #$task: |~|g" |
|
||||
column -s"~" -t |
|
||||
sort
|
||||
}
|
||||
|
||||
function help { #help: show task descriptions
|
||||
echo -e "${BOLD}Usage:${RESET} ./$(basename "$0") <task> [options]"
|
||||
echo
|
||||
echo "Show the cargo-make configuration for web examples"
|
||||
echo
|
||||
echo -e "${BOLD}Tasks:${RESET}"
|
||||
list_help_for task
|
||||
echo
|
||||
}
|
||||
|
||||
TIMEFORMAT="./web-report.sh completed in %3lR"
|
||||
time "${@:-all}" # Show the report by default
|
||||
@@ -3,21 +3,18 @@
|
||||
[tasks.stop-server]
|
||||
condition = { env_set = ["SERVER_PROCESS_NAME"] }
|
||||
script = '''
|
||||
if pidof -q ${SERVER_PROCESS_NAME}; then
|
||||
echo " Stopping ${SERVER_PROCESS_NAME}"
|
||||
if [ ! -z $(pidof ${SERVER_PROCESS_NAME}) ]; then
|
||||
pkill -ef ${SERVER_PROCESS_NAME}
|
||||
else
|
||||
echo " ${SERVER_PROCESS_NAME} is already stopped"
|
||||
fi
|
||||
'''
|
||||
|
||||
[tasks.server-status]
|
||||
condition = { env_set = ["SERVER_PROCESS_NAME"] }
|
||||
script = '''
|
||||
if pidof -q ${SERVER_PROCESS_NAME}; then
|
||||
echo " ${SERVER_PROCESS_NAME} is up"
|
||||
else
|
||||
if [ -z $(pidof ${SERVER_PROCESS_NAME}) ]; then
|
||||
echo " ${SERVER_PROCESS_NAME} is not running"
|
||||
else
|
||||
echo " ${SERVER_PROCESS_NAME} is up"
|
||||
fi
|
||||
'''
|
||||
|
||||
@@ -27,11 +24,11 @@ script = '''
|
||||
YELLOW="\e[0;33m"
|
||||
RESET="\e[0m"
|
||||
|
||||
if pidof -q ${SERVER_PROCESS_NAME}; then
|
||||
echo " ${SERVER_PROCESS_NAME} is already started"
|
||||
else
|
||||
if [ -z $(pidof ${SERVER_PROCESS_NAME}) ]; then
|
||||
echo " Starting ${SERVER_PROCESS_NAME}"
|
||||
echo " ${YELLOW}>> Run cargo make stop to end process${RESET}"
|
||||
cargo make start-server ${@} &
|
||||
else
|
||||
echo " ${SERVER_PROCESS_NAME} is already started"
|
||||
fi
|
||||
'''
|
||||
|
||||
@@ -6,33 +6,25 @@ script = '''
|
||||
RESET="\e[0m"
|
||||
|
||||
if command -v chromedriver; then
|
||||
if pidof -q chromedriver; then
|
||||
echo " chromedriver is already started"
|
||||
else
|
||||
echo "Starting chomedriver"
|
||||
if [ -z $(pidof chromedriver) ]; then
|
||||
chromedriver --port=4444 &
|
||||
fi
|
||||
else
|
||||
echo "${RED}${BOLD}ERROR${RESET} - chromedriver not found"
|
||||
echo "${RED}${BOLD}ERROR${RESET} - chromedriver is required by this task"
|
||||
exit 1
|
||||
fi
|
||||
'''
|
||||
|
||||
[tasks.stop-webdriver]
|
||||
script = '''
|
||||
if pidof -q chromedriver; then
|
||||
echo " Stopping chromedriver"
|
||||
pkill -ef "chromedriver"
|
||||
else
|
||||
echo " chromedriver is already stopped"
|
||||
fi
|
||||
pkill -f "chromedriver"
|
||||
'''
|
||||
|
||||
[tasks.webdriver-status]
|
||||
script = '''
|
||||
if pidof -q chromedriver; then
|
||||
echo chromedriver is up
|
||||
else
|
||||
if [ -z $(pidof chromedriver) ]; then
|
||||
echo chromedriver is not running
|
||||
else
|
||||
echo chromedriver is up
|
||||
fi
|
||||
'''
|
||||
|
||||
@@ -8,7 +8,7 @@ codegen-units = 1
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "stable" # test change
|
||||
channel = "nightly"
|
||||
|
||||
@@ -14,7 +14,7 @@ pub fn SimpleCounter(
|
||||
|
||||
view! {
|
||||
<div>
|
||||
<button on:click=move |_| set_value.set(0)>"Clear"</button>
|
||||
<button on:click=move |_| set_value(0)>"Clear"</button>
|
||||
<button on:click=move |_| set_value.update(|value| *value -= step)>"-1"</button>
|
||||
<span>"Value: " {value} "!"</span>
|
||||
<button on:click=move |_| set_value.update(|value| *value += step)>"+1"</button>
|
||||
|
||||
@@ -25,12 +25,13 @@ leptos_router = { path = "../../router" }
|
||||
log = "0.4"
|
||||
once_cell = "1.18"
|
||||
gloo-net = { git = "https://github.com/rustwasm/gloo" }
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen = "0.2.87"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
simple_logger = "4.3"
|
||||
tracing = { version = "0.1", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["nightly"]
|
||||
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
|
||||
ssr = [
|
||||
"dep:actix-files",
|
||||
@@ -41,9 +42,10 @@ ssr = [
|
||||
"leptos_meta/ssr",
|
||||
"leptos_router/ssr",
|
||||
]
|
||||
nightly = ["leptos/nightly", "leptos_router/nightly"]
|
||||
|
||||
[package.metadata.cargo-all-features]
|
||||
denylist = ["actix-files", "actix-web", "leptos_actix"]
|
||||
denylist = ["actix-files", "actix-web", "leptos_actix", "nightly"]
|
||||
skip_feature_sets = [["ssr", "hydrate"]]
|
||||
|
||||
[package.metadata.leptos]
|
||||
@@ -67,7 +69,7 @@ reload-port = 3001
|
||||
end2end-cmd = "npx playwright test"
|
||||
# The browserlist query used for optimizing the CSS.
|
||||
browserquery = "defaults"
|
||||
# Set by cargo-leptos watch when building with that tool. Controls whether autoreload JS will be included in the head
|
||||
# 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"
|
||||
|
||||
@@ -118,9 +118,9 @@ pub fn Counters() -> impl IntoView {
|
||||
// This is the typical pattern for a CRUD app
|
||||
#[component]
|
||||
pub fn Counter() -> impl IntoView {
|
||||
let dec = create_action(|_: &()| adjust_server_count(-1, "decing".into()));
|
||||
let inc = create_action(|_: &()| adjust_server_count(1, "incing".into()));
|
||||
let clear = create_action(|_: &()| clear_server_count());
|
||||
let dec = create_action(|_| adjust_server_count(-1, "decing".into()));
|
||||
let inc = create_action(|_| adjust_server_count(1, "incing".into()));
|
||||
let clear = create_action(|_| clear_server_count());
|
||||
let counter = create_resource(
|
||||
move || {
|
||||
(
|
||||
@@ -132,6 +132,15 @@ pub fn Counter() -> impl IntoView {
|
||||
|_| get_server_count(),
|
||||
);
|
||||
|
||||
let value =
|
||||
move || counter.get().map(|count| count.unwrap_or(0)).unwrap_or(0);
|
||||
let error_msg = move || {
|
||||
counter.get().and_then(|res| match res {
|
||||
Ok(_) => None,
|
||||
Err(e) => Some(e),
|
||||
})
|
||||
};
|
||||
|
||||
view! {
|
||||
<div>
|
||||
<h2>"Simple Counter"</h2>
|
||||
@@ -141,24 +150,15 @@ pub fn Counter() -> impl IntoView {
|
||||
<div>
|
||||
<button on:click=move |_| clear.dispatch(())>"Clear"</button>
|
||||
<button on:click=move |_| dec.dispatch(())>"-1"</button>
|
||||
<span>
|
||||
"Value: "
|
||||
<Suspense>
|
||||
{move || counter.and_then(|count| *count)} "!"
|
||||
</Suspense>
|
||||
</span>
|
||||
<span>"Value: " {value} "!"</span>
|
||||
<button on:click=move |_| inc.dispatch(())>"+1"</button>
|
||||
</div>
|
||||
<Suspense>
|
||||
{move || {
|
||||
counter.get().and_then(|res| match res {
|
||||
Ok(_) => None,
|
||||
Err(e) => Some(e),
|
||||
}).map(|msg| {
|
||||
view! { <p>"Error: " {msg.to_string()}</p> }
|
||||
})
|
||||
}}
|
||||
</Suspense>
|
||||
{move || {
|
||||
error_msg()
|
||||
.map(|msg| {
|
||||
view! { <p>"Error: " {msg.to_string()}</p> }
|
||||
})
|
||||
}}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -204,7 +204,7 @@ pub fn FormCounter() -> impl IntoView {
|
||||
<input type="hidden" name="msg" value="form value down"/>
|
||||
<input type="submit" value="-1"/>
|
||||
</ActionForm>
|
||||
<span>"Value: " <Suspense>{move || value().to_string()} "!"</Suspense></span>
|
||||
<span>"Value: " {move || value().to_string()} "!"</span>
|
||||
<ActionForm action=adjust>
|
||||
<input type="hidden" name="delta" value="1"/>
|
||||
<input type="hidden" name="msg" value="form value up"/>
|
||||
@@ -222,10 +222,9 @@ pub fn FormCounter() -> impl IntoView {
|
||||
#[component]
|
||||
pub fn MultiuserCounter() -> impl IntoView {
|
||||
let dec =
|
||||
create_action(|_: &()| adjust_server_count(-1, "dec dec goose".into()));
|
||||
let inc =
|
||||
create_action(|_: &()| adjust_server_count(1, "inc inc moose".into()));
|
||||
let clear = create_action(|_: &()| clear_server_count());
|
||||
create_action(|_| adjust_server_count(-1, "dec dec goose".into()));
|
||||
let inc = create_action(|_| adjust_server_count(1, "inc inc moose".into()));
|
||||
let clear = create_action(|_| clear_server_count());
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
let multiplayer_value = {
|
||||
|
||||
@@ -8,7 +8,7 @@ codegen-units = 1
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
|
||||
leptos_router = { path = "../../router", features = ["csr"] }
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "stable" # test change
|
||||
channel = "nightly"
|
||||
|
||||
@@ -7,17 +7,17 @@ use leptos_router::*;
|
||||
#[component]
|
||||
pub fn SimpleQueryCounter() -> impl IntoView {
|
||||
let (count, set_count) = create_query_signal::<i32>("count");
|
||||
let clear = move |_| set_count.set(None);
|
||||
let decrement = move |_| set_count.set(Some(count.get().unwrap_or(0) - 1));
|
||||
let increment = move |_| set_count.set(Some(count.get().unwrap_or(0) + 1));
|
||||
let clear = move |_| set_count(None);
|
||||
let decrement = move |_| set_count(Some(count().unwrap_or(0) - 1));
|
||||
let increment = move |_| set_count(Some(count().unwrap_or(0) + 1));
|
||||
|
||||
let (msg, set_msg) = create_query_signal::<String>("message");
|
||||
let update_msg = move |ev| {
|
||||
let new_msg = event_target_value(&ev);
|
||||
if new_msg.is_empty() {
|
||||
set_msg.set(None);
|
||||
set_msg(None);
|
||||
} else {
|
||||
set_msg.set(Some(new_msg));
|
||||
set_msg(Some(new_msg));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -25,13 +25,13 @@ pub fn SimpleQueryCounter() -> impl IntoView {
|
||||
<div>
|
||||
<button on:click=clear>"Clear"</button>
|
||||
<button on:click=decrement>"-1"</button>
|
||||
<span>"Value: " {move || count.get().unwrap_or(0)} "!"</span>
|
||||
<span>"Value: " {move || count().unwrap_or(0)} "!"</span>
|
||||
<button on:click=increment>"+1"</button>
|
||||
|
||||
<br />
|
||||
|
||||
<input
|
||||
prop:value=move || msg.get().unwrap_or_default()
|
||||
prop:value=move || msg().unwrap_or_default()
|
||||
on:input=update_msg
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
name = "counter_without_macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.75"
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
@@ -15,7 +14,7 @@ log = "0.4"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen = "0.2.84"
|
||||
wasm-bindgen-test = "0.3.34"
|
||||
pretty_assertions = "1.3.0"
|
||||
rstest = "0.17.0"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use leptos::{html::*, *};
|
||||
use leptos::{ev, html::*, *};
|
||||
|
||||
/// A simple counter view.
|
||||
// A component is really just a function call: it runs once to create the DOM and reactive system
|
||||
|
||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos", features = ["csr"] }
|
||||
leptos = { path = "../../leptos", features = ["csr", "nightly"] }
|
||||
log = "0.4"
|
||||
console_log = "1"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
[toolchain]
|
||||
channel = "stable" # test change
|
||||
channel = "nightly"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use leptos::*;
|
||||
use leptos::{For, *};
|
||||
|
||||
const MANY_COUNTERS: usize = 1000;
|
||||
|
||||
@@ -16,14 +16,14 @@ pub fn Counters() -> impl IntoView {
|
||||
provide_context(CounterUpdater { set_counters });
|
||||
|
||||
let add_counter = move |_| {
|
||||
let id = next_counter_id.get();
|
||||
let id = next_counter_id();
|
||||
let sig = create_signal(0);
|
||||
set_counters.update(move |counters| counters.push((id, sig)));
|
||||
set_next_counter_id.update(|id| *id += 1);
|
||||
};
|
||||
|
||||
let add_many_counters = move |_| {
|
||||
let next_id = next_counter_id.get();
|
||||
let next_id = next_counter_id();
|
||||
let new_counters = (next_id..next_id + MANY_COUNTERS).map(|id| {
|
||||
let signal = create_signal(0);
|
||||
(id, signal)
|
||||
@@ -53,17 +53,17 @@ pub fn Counters() -> impl IntoView {
|
||||
<span>{move ||
|
||||
counters.get()
|
||||
.iter()
|
||||
.map(|(_, (count, _))| count.get())
|
||||
.map(|(_, (count, _))| count())
|
||||
.sum::<i32>()
|
||||
.to_string()
|
||||
}</span>
|
||||
" from "
|
||||
<span>{move || counters.get().len().to_string()}</span>
|
||||
<span>{move || counters().len().to_string()}</span>
|
||||
" counters."
|
||||
</p>
|
||||
<ul>
|
||||
<For
|
||||
each=move || counters.get()
|
||||
each=counters
|
||||
key=|counter| counter.0
|
||||
children=move |(id, (value, set_value)): (usize, (ReadSignal<i32>, WriteSignal<i32>))| {
|
||||
view! {
|
||||
@@ -85,8 +85,7 @@ fn Counter(
|
||||
let CounterUpdater { set_counters } = use_context().unwrap();
|
||||
|
||||
let input = move |ev| {
|
||||
set_value
|
||||
.set(event_target_value(&ev).parse::<i32>().unwrap_or_default())
|
||||
set_value(event_target_value(&ev).parse::<i32>().unwrap_or_default())
|
||||
};
|
||||
|
||||
// this will run when the scope is disposed, i.e., when this row is deleted
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user