mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-01-23 00:59:22 -05:00
Merge branch 'main' into use_web_notification
This commit is contained in:
commit
18021ad942
82 changed files with 1607 additions and 368 deletions
|
@ -1,3 +1,3 @@
|
||||||
[unstable]
|
[build]
|
||||||
rustflags = ["--cfg=web_sys_unstable_apis"]
|
rustflags = ["--cfg=web_sys_unstable_apis"]
|
||||||
rustdocflags = ["--cfg=web_sys_unstable_apis"]
|
rustdocflags = ["--cfg=web_sys_unstable_apis"]
|
||||||
|
|
89
.github/workflows/cd.yml
vendored
Normal file
89
.github/workflows/cd.yml
vendored
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
# Pattern matched against refs/tags
|
||||||
|
tags:
|
||||||
|
- '*' # Push events to every tag not containing /
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
name: CD
|
||||||
|
|
||||||
|
permissions: write-all
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
name: Publish
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: nightly
|
||||||
|
profile: minimal
|
||||||
|
override: true
|
||||||
|
components: rustfmt, clippy, rust-src
|
||||||
|
- name: Cache
|
||||||
|
uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
|
- name: Check function count badge
|
||||||
|
run: python3 docs/generate_count_badge.py --check
|
||||||
|
- name: Check version in docs
|
||||||
|
run: python3 docs/add_version_to_docs.py --check
|
||||||
|
|
||||||
|
- name: Check formatting
|
||||||
|
run: cargo fmt --check
|
||||||
|
- name: Clippy
|
||||||
|
run: cargo clippy --features docs,math --tests -- -D warnings
|
||||||
|
|
||||||
|
- name: Run tests (general)
|
||||||
|
run: cargo test --features math,docs,ssr
|
||||||
|
- name: Run tests (axum) use_cookie
|
||||||
|
run: cargo test --features math,docs,ssr,axum --doc use_cookie
|
||||||
|
- name: Run tests (axum) use_locale
|
||||||
|
run: cargo test --features math,docs,ssr,axum --doc use_locale
|
||||||
|
- name: Run tests (actix) use_cookie
|
||||||
|
run: cargo test --features math,docs,ssr,actix --doc use_cookie
|
||||||
|
- name: Run tests (actix) use_locale
|
||||||
|
run: cargo test --features math,docs,ssr,actix --doc use_locale
|
||||||
|
|
||||||
|
#### mdbook
|
||||||
|
- name: Install mdbook I
|
||||||
|
uses: taiki-e/install-action@v2
|
||||||
|
with:
|
||||||
|
tool: cargo-binstall,mdbook
|
||||||
|
- name: Install mdbook II
|
||||||
|
run: |
|
||||||
|
cargo binstall -y mdbook-cmdrun
|
||||||
|
cargo binstall -y trunk@0.17.5
|
||||||
|
rustup target add wasm32-unknown-unknown
|
||||||
|
- name: Setup Pages
|
||||||
|
id: pages
|
||||||
|
uses: actions/configure-pages@v3
|
||||||
|
- name: Build mdbook # TODO : run mdbook tests
|
||||||
|
run: |
|
||||||
|
cd docs/book
|
||||||
|
mdbook build
|
||||||
|
python3 post_build.py
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-pages-artifact@v1
|
||||||
|
with:
|
||||||
|
path: ./docs/book/book
|
||||||
|
- name: Deploy book to github pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v2
|
||||||
|
##### mdbook end
|
||||||
|
|
||||||
|
- name: Publish crate leptos-use
|
||||||
|
uses: katyo/publish-crates@v2
|
||||||
|
with:
|
||||||
|
registry-token: ${{ secrets.CRATES_TOKEN }}
|
||||||
|
|
||||||
|
- uses: CSchoel/release-notes-from-changelog@v1
|
||||||
|
- name: Create Release using GitHub CLI
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: >
|
||||||
|
gh release create
|
||||||
|
-d
|
||||||
|
-F RELEASE.md
|
||||||
|
-t "Version $RELEASE_VERSION"
|
||||||
|
${GITHUB_REF#refs/*/}
|
110
.github/workflows/ci.yml
vendored
110
.github/workflows/ci.yml
vendored
|
@ -1,82 +1,48 @@
|
||||||
|
name: Continuous Integration
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
pull_request:
|
||||||
# Pattern matched against refs/tags
|
branches:
|
||||||
tags:
|
- main
|
||||||
- '*' # Push events to every tag not containing /
|
paths:
|
||||||
workflow_dispatch:
|
- "**"
|
||||||
|
- "!/*.md"
|
||||||
|
- "!/**.md"
|
||||||
|
|
||||||
name: CI
|
concurrency:
|
||||||
|
group: "${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}"
|
||||||
permissions: write-all
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
integrity:
|
||||||
name: Publish
|
name: Integrity Checks on Rust ${{ matrix.toolchain }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 15
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
toolchain:
|
||||||
|
- stable
|
||||||
|
- nightly
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- name: Checkout
|
||||||
- uses: actions-rs/toolchain@v1
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Rust
|
||||||
|
uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
toolchain: nightly
|
toolchain: ${{ matrix.toolchain }}
|
||||||
profile: minimal
|
targets: wasm32-unknown-unknown
|
||||||
override: true
|
components: clippy, rustfmt
|
||||||
components: rustfmt, clippy, rust-src
|
|
||||||
- name: Cache
|
- name: Setup Rust Cache
|
||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
- name: Check function count badge
|
|
||||||
run: python3 docs/generate_count_badge.py --check
|
- name: Build
|
||||||
- name: Check version in docs
|
run: cargo build
|
||||||
run: python3 docs/add_version_to_docs.py --check
|
|
||||||
- name: Check formatting
|
- name: Format
|
||||||
run: cargo fmt --check
|
run: cargo fmt --check
|
||||||
|
|
||||||
- name: Clippy
|
- name: Clippy
|
||||||
run: cargo clippy --features docs,math --tests -- -D warnings
|
run: cargo clippy -- -D warnings
|
||||||
- name: Run tests (general)
|
|
||||||
run: cargo test --features math,docs,ssr
|
|
||||||
- name: Run tests (axum)
|
|
||||||
run: cargo test --features math,docs,ssr,axum --doc use_cookie::use_cookie
|
|
||||||
- name: Run tests (actix)
|
|
||||||
run: cargo test --features math,docs,ssr,actix --doc use_cookie::use_cookie
|
|
||||||
|
|
||||||
#### mdbook
|
|
||||||
- name: Install mdbook I
|
|
||||||
uses: taiki-e/install-action@v2
|
|
||||||
with:
|
|
||||||
tool: cargo-binstall,mdbook
|
|
||||||
- name: Install mdbook II
|
|
||||||
run: |
|
|
||||||
cargo binstall -y mdbook-cmdrun
|
|
||||||
cargo binstall -y trunk@0.17.5
|
|
||||||
rustup target add wasm32-unknown-unknown
|
|
||||||
- name: Setup Pages
|
|
||||||
id: pages
|
|
||||||
uses: actions/configure-pages@v3
|
|
||||||
- name: Build mdbook # TODO : run mdbook tests
|
|
||||||
run: |
|
|
||||||
cd docs/book
|
|
||||||
mdbook build
|
|
||||||
python3 post_build.py
|
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-pages-artifact@v1
|
|
||||||
with:
|
|
||||||
path: ./docs/book/book
|
|
||||||
- name: Deploy book to github pages
|
|
||||||
id: deployment
|
|
||||||
uses: actions/deploy-pages@v2
|
|
||||||
##### mdbook end
|
|
||||||
|
|
||||||
- name: Publish crate leptos-use
|
|
||||||
uses: katyo/publish-crates@v2
|
|
||||||
with:
|
|
||||||
registry-token: ${{ secrets.CRATES_TOKEN }}
|
|
||||||
|
|
||||||
- uses: CSchoel/release-notes-from-changelog@v1
|
|
||||||
- name: Create Release using GitHub CLI
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: >
|
|
||||||
gh release create
|
|
||||||
-d
|
|
||||||
-F RELEASE.md
|
|
||||||
-t "Version $RELEASE_VERSION"
|
|
||||||
${GITHUB_REF#refs/*/}
|
|
||||||
|
|
27
.github/workflows/tests.yml
vendored
27
.github/workflows/tests.yml
vendored
|
@ -1,5 +1,11 @@
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- "**"
|
||||||
|
- "!/*.md"
|
||||||
|
- "!/**.md"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
name: Tests
|
name: Tests
|
||||||
|
@ -20,13 +26,18 @@ jobs:
|
||||||
components: rustfmt, clippy, rust-src
|
components: rustfmt, clippy, rust-src
|
||||||
- name: Cache
|
- name: Cache
|
||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
- name: Check formatting
|
|
||||||
run: cargo fmt --check
|
|
||||||
- name: Clippy
|
|
||||||
run: cargo clippy --features docs,math --tests -- -D warnings
|
|
||||||
- name: Run tests (general)
|
- name: Run tests (general)
|
||||||
run: cargo test --features math,docs,ssr
|
run: cargo test --features math,docs,ssr
|
||||||
- name: Run tests (axum)
|
|
||||||
run: cargo test --features math,docs,ssr,axum --doc use_cookie::use_cookie
|
- name: Run tests (axum) use_cookie
|
||||||
- name: Run tests (actix)
|
run: cargo test --features math,docs,ssr,axum --doc use_cookie
|
||||||
run: cargo test --features math,docs,ssr,actix --doc use_cookie::use_cookie
|
|
||||||
|
- name: Run tests (axum) use_locale
|
||||||
|
run: cargo test --features math,docs,ssr,axum --doc use_locale
|
||||||
|
|
||||||
|
- name: Run tests (actix) use_cookie
|
||||||
|
run: cargo test --features math,docs,ssr,actix --doc use_cookie
|
||||||
|
|
||||||
|
- name: Run tests (actix) use_locale
|
||||||
|
run: cargo test --features math,docs,ssr,actix --doc use_locale
|
||||||
|
|
3
.idea/leptos-use.iml
generated
3
.idea/leptos-use.iml
generated
|
@ -77,6 +77,9 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/examples/use_or/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/examples/use_or/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/examples/use_event_source/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/examples/use_event_source/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/examples/sync_signal/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/examples/sync_signal/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/examples/use_user_media/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/examples/use_locale/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/examples/use_locales/src" isTestSource="false" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/examples/use_event_listener/target" />
|
<excludeFolder url="file://$MODULE_DIR$/examples/use_event_listener/target" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/docs/book/book" />
|
<excludeFolder url="file://$MODULE_DIR$/docs/book/book" />
|
||||||
|
|
37
CHANGELOG.md
37
CHANGELOG.md
|
@ -3,7 +3,27 @@
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [0.11.3] - 2024-07-31
|
||||||
|
|
||||||
|
### Fix 🍕
|
||||||
|
|
||||||
|
- Made `use_timeout_fn` SSR-safe
|
||||||
|
|
||||||
|
## [0.11.2] - 2024-07-30
|
||||||
|
|
||||||
|
### Change 🔥
|
||||||
|
|
||||||
|
- `use_locale` has now a supported locale list.
|
||||||
|
|
||||||
|
## (yanked) [0.11.1] - 2024-07-28
|
||||||
|
|
||||||
|
### New Functions 🚀
|
||||||
|
|
||||||
|
- `use_locale` (thanks to @BrandonDyer64)
|
||||||
|
- `use_locales` (thanks to @BrandonDyer64)
|
||||||
|
- `header` – Standard implementations for reading a header on the server.
|
||||||
|
|
||||||
|
## [0.11.0] - 2024-07-27
|
||||||
|
|
||||||
### New Functions 🚀
|
### New Functions 🚀
|
||||||
|
|
||||||
|
@ -31,7 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
the DOM controlled by a value from storage. This leads to hydration errors which can be fixed by setting this new
|
the DOM controlled by a value from storage. This leads to hydration errors which can be fixed by setting this new
|
||||||
option to `true`.
|
option to `true`.
|
||||||
- `cookie::SameSite` is now re-exported
|
- `cookie::SameSite` is now re-exported
|
||||||
- Changing the signal returned by `use_cookie` now tries and changes the headers during SSR.
|
- Changing the signal returned by `use_cookie` now tries and changes the headers during SSR.
|
||||||
- New book chapter about codecs
|
- New book chapter about codecs
|
||||||
- The macro `use_derive_signal!` is now exported (thanks to @mscofield0).
|
- The macro `use_derive_signal!` is now exported (thanks to @mscofield0).
|
||||||
|
|
||||||
|
@ -44,8 +64,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- `JsonCodec` has been renamed to `JsonSerdeCodec`.
|
- `JsonCodec` has been renamed to `JsonSerdeCodec`.
|
||||||
- The feature to enable this codec is now called `json_serde` instead of just `serde`.
|
- The feature to enable this codec is now called `json_serde` instead of just `serde`.
|
||||||
- `ProstCodec` now encodes as binary data. If you want to keep using it with string data you can wrap it like
|
- `ProstCodec` now encodes as binary data. If you want to keep using it with string data you can wrap it like
|
||||||
this: `Base64<ProstCodec>`. You have to enable both features `prost` and `base64` for this.
|
this: `Base64<ProstCodec>`.
|
||||||
- All of these structs, traits and features now live in their own crate called `codee`
|
- All of these structs, traits and features now live in their own crate called `codee`
|
||||||
|
- A bunch of new codecs are available. Have a look at the docs for crate `codee`.
|
||||||
- `use_websocket`:
|
- `use_websocket`:
|
||||||
- `UseWebsocketOptions` has been renamed to `UseWebSocketOptions` (uppercase S) to be consistent with the return
|
- `UseWebsocketOptions` has been renamed to `UseWebSocketOptions` (uppercase S) to be consistent with the return
|
||||||
type.
|
type.
|
||||||
|
@ -64,12 +85,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
to `on_message_raw` and `on_message_raw_bytes`.
|
to `on_message_raw` and `on_message_raw_bytes`.
|
||||||
- The new `UseWebSocketOptions::on_message` takes a `&T`.
|
- The new `UseWebSocketOptions::on_message` takes a `&T`.
|
||||||
- `UseWebSocketOptions::on_error` now takes a `UseWebSocketError` instead of a `web_sys::Event`.
|
- `UseWebSocketOptions::on_error` now takes a `UseWebSocketError` instead of a `web_sys::Event`.
|
||||||
- `use_storage` now always saves the default value to storage if the key doesn't exist yet.
|
- `use_storage` now always saves the default value to storage if the key doesn't exist yet.
|
||||||
|
- Renamed `BreakpointsSematic` to `BreakpointsSemantic` and `breakpoints_sematic` to `breakpoints_semantic`
|
||||||
|
(note the `n`) (thanks to @mondeja).
|
||||||
|
|
||||||
### Fixes 🍕
|
### Fixes 🍕
|
||||||
|
|
||||||
- Fixed auto-reconnect in `use_websocket`
|
- Fixed auto-reconnect in `use_websocket`
|
||||||
- Fixed typo in compiler error messages in `use_cookie` (thanks to @SleeplessOne1917).
|
- Fixed typo in compiler error messages in `use_cookie` (thanks to @SleeplessOne1917).
|
||||||
|
- Fixed potential signal out of scope issue with `use_raf_fn`
|
||||||
|
|
||||||
|
### Other Changes 🔥
|
||||||
|
|
||||||
|
- Better links in docs that work both in the book and in rustdoc (thanks to @mondeja).
|
||||||
|
- Better CI/CD (thanks to @EstebanBorai).
|
||||||
|
|
||||||
## [0.10.10] - 2024-05-10
|
## [0.10.10] - 2024-05-10
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
[package]
|
[package]
|
||||||
name = "leptos-use"
|
name = "leptos-use"
|
||||||
version = "0.10.10"
|
version = "0.11.3"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Marc-Stefan Cassola"]
|
authors = ["Marc-Stefan Cassola"]
|
||||||
categories = ["gui", "web-programming"]
|
categories = ["gui", "web-programming"]
|
||||||
description = "Collection of essential Leptos utilities inspired by SolidJS USE / VueUse"
|
description = "Collection of essential Leptos utilities inspired by React-Use / VueUse / SolidJS-USE"
|
||||||
exclude = ["examples/", "tests/"]
|
exclude = ["examples/", "tests/"]
|
||||||
keywords = ["leptos", "utilities"]
|
keywords = ["leptos", "utilities"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
|
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
|
||||||
<a href="https://leptos-use.rs/server_side_rendering.html"><img src="https://img.shields.io/badge/-SSR-%236a214b" alt="SSR"></a>
|
<a href="https://leptos-use.rs/server_side_rendering.html"><img src="https://img.shields.io/badge/-SSR-%236a214b" alt="SSR"></a>
|
||||||
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
|
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
|
||||||
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-77%20functions-%23EF3939" alt="77 Functions" /></a>
|
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-82%20functions-%23EF3939" alt="82 Functions" /></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
[![Docs](https://docs.rs/leptos-use/badge.svg)](https://docs.rs/leptos-use/)
|
[![Docs](https://docs.rs/leptos-use/badge.svg)](https://docs.rs/leptos-use/)
|
||||||
[![MIT/Apache 2.0](https://img.shields.io/badge/license-MIT%2FApache-blue.svg)](https://github.com/synphonyte/leptos-use#license)
|
[![MIT/Apache 2.0](https://img.shields.io/badge/license-MIT%2FApache-blue.svg)](https://github.com/synphonyte/leptos-use#license)
|
||||||
[![Build Status](https://github.com/synphonyte/leptos-use/actions/workflows/ci.yml/badge.svg)](https://github.com/synphonyte/leptos-use/actions/workflows/ci.yml)
|
[![Build Status](https://github.com/synphonyte/leptos-use/actions/workflows/cd.yml/badge.svg)](https://github.com/synphonyte/leptos-use/actions/workflows/cd.yml)
|
||||||
[![Discord](https://img.shields.io/discord/1031524867910148188?color=%237289DA&label=discord)](https://discord.com/channels/1031524867910148188/1121154537709895783)
|
[![Discord](https://img.shields.io/discord/1031524867910148188?color=%237289DA&label=discord)](https://discord.com/channels/1031524867910148188/1121154537709895783)
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
@ -92,4 +92,4 @@ This will create the function file in the src directory, scaffold an example dir
|
||||||
| <= 0.3 | 0.3 |
|
| <= 0.3 | 0.3 |
|
||||||
| 0.4, 0.5, 0.6 | 0.4 |
|
| 0.4, 0.5, 0.6 | 0.4 |
|
||||||
| 0.7, 0.8, 0.9 | 0.5 |
|
| 0.7, 0.8, 0.9 | 0.5 |
|
||||||
| 0.10 | 0.6 |
|
| 0.10, 0.11 | 0.6 |
|
||||||
|
|
|
@ -13,7 +13,8 @@ def main():
|
||||||
if os.path.isdir(category_dir):
|
if os.path.isdir(category_dir):
|
||||||
for file in os.listdir(category_dir):
|
for file in os.listdir(category_dir):
|
||||||
if file.endswith(".md") and (len(sys.argv) == 1 or (sys.argv[1] in file)):
|
if file.endswith(".md") and (len(sys.argv) == 1 or (sys.argv[1] in file)):
|
||||||
build_and_copy_demo(category, file)
|
if build_and_copy_demo(category, file):
|
||||||
|
rewrite_links(category, file)
|
||||||
|
|
||||||
|
|
||||||
def build_and_copy_demo(category, md_name):
|
def build_and_copy_demo(category, md_name):
|
||||||
|
@ -24,7 +25,8 @@ def build_and_copy_demo(category, md_name):
|
||||||
code = p.wait()
|
code = p.wait()
|
||||||
|
|
||||||
if code != 0:
|
if code != 0:
|
||||||
sys.exit(code, f"failed to build example '{name}'")
|
sys.stderr.write(f"failed to build example '{name}'\n")
|
||||||
|
sys.exit(code)
|
||||||
|
|
||||||
example_output_path = os.path.join(example_dir, "dist")
|
example_output_path = os.path.join(example_dir, "dist")
|
||||||
target_path = os.path.join("book", category, name, "demo")
|
target_path = os.path.join("book", category, name, "demo")
|
||||||
|
@ -49,7 +51,7 @@ def build_and_copy_demo(category, md_name):
|
||||||
|
|
||||||
with open(book_html_path, "w") as f:
|
with open(book_html_path, "w") as f:
|
||||||
f.write(
|
f.write(
|
||||||
f"""{head_split[0]}
|
f"""{head_split[0]}
|
||||||
<head>
|
<head>
|
||||||
{demo_head}
|
{demo_head}
|
||||||
{target_head}
|
{target_head}
|
||||||
|
@ -60,6 +62,32 @@ def build_and_copy_demo(category, md_name):
|
||||||
</body>
|
</body>
|
||||||
{body_split[1]}""")
|
{body_split[1]}""")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def rewrite_links(category, md_name):
|
||||||
|
"""Rewrite links in generated documentation to make them
|
||||||
|
compatible between rustdoc and the book.
|
||||||
|
"""
|
||||||
|
html_name = f"{md_name[:-3]}.html"
|
||||||
|
target_path = os.path.join("book", category, html_name)
|
||||||
|
|
||||||
|
with open(target_path, "r") as f:
|
||||||
|
html = f.read()
|
||||||
|
|
||||||
|
html = html.replace(
|
||||||
|
"fn@crate::", "",
|
||||||
|
).replace(
|
||||||
|
"crate::", "",
|
||||||
|
).replace(
|
||||||
|
"fn@", "",
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(target_path, "w") as f:
|
||||||
|
f.write(html)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -99,6 +99,7 @@
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
|
|
||||||
|
- [header](utilities/header.md)
|
||||||
- [is_err](utilities/is_err.md)
|
- [is_err](utilities/is_err.md)
|
||||||
- [is_none](utilities/is_none.md)
|
- [is_none](utilities/is_none.md)
|
||||||
- [is_ok](utilities/is_ok.md)
|
- [is_ok](utilities/is_ok.md)
|
||||||
|
@ -113,6 +114,8 @@
|
||||||
# Intl
|
# Intl
|
||||||
|
|
||||||
- [use_intl_number_format](intl/use_intl_number_format.md)
|
- [use_intl_number_format](intl/use_intl_number_format.md)
|
||||||
|
- [use_locale](intl/use_locale.md)
|
||||||
|
- [use_locales](intl/use_locales.md)
|
||||||
|
|
||||||
# @Math
|
# @Math
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.demo-container button ~ button {
|
.demo-container button + button {
|
||||||
margin-left: 0.8rem;
|
margin-left: 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,4 +134,4 @@
|
||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
border-style: dashed;
|
border-style: dashed;
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
3
docs/book/src/intl/use_locale.md
Normal file
3
docs/book/src/intl/use_locale.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# use_locale
|
||||||
|
|
||||||
|
<!-- cmdrun python3 ../extract_doc_comment.py use_locale -->
|
3
docs/book/src/intl/use_locales.md
Normal file
3
docs/book/src/intl/use_locales.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# use_locales
|
||||||
|
|
||||||
|
<!-- cmdrun python3 ../extract_doc_comment.py use_locales -->
|
|
@ -12,6 +12,6 @@
|
||||||
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
|
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
|
||||||
<a href="https://leptos-use.rs/server_side_rendering.html"><img src="https://img.shields.io/badge/-SSR-%236a214b" alt="SSR"></a>
|
<a href="https://leptos-use.rs/server_side_rendering.html"><img src="https://img.shields.io/badge/-SSR-%236a214b" alt="SSR"></a>
|
||||||
<a href="./get_started.html"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
|
<a href="./get_started.html"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
|
||||||
<a href="./functions.html"><img src="https://img.shields.io/badge/-77%20functions-%23EF3939" alt="77 Functions" /></a>
|
<a href="./functions.html"><img src="https://img.shields.io/badge/-82%20functions-%23EF3939" alt="82 Functions" /></a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
3
docs/book/src/utilities/header.md
Normal file
3
docs/book/src/utilities/header.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# header
|
||||||
|
|
||||||
|
<!-- cmdrun python3 ../extract_doc_comment.py utils/header -->
|
|
@ -38,6 +38,8 @@ members = [
|
||||||
"use_interval",
|
"use_interval",
|
||||||
"use_interval_fn",
|
"use_interval_fn",
|
||||||
"use_intl_number_format",
|
"use_intl_number_format",
|
||||||
|
"use_locale",
|
||||||
|
"use_locales",
|
||||||
"use_media_query",
|
"use_media_query",
|
||||||
"use_mouse",
|
"use_mouse",
|
||||||
"use_mouse_in_element",
|
"use_mouse_in_element",
|
||||||
|
|
|
@ -8,6 +8,7 @@ crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = { version = "0.7", optional = true }
|
axum = { version = "0.7", optional = true }
|
||||||
|
codee = "0.1"
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
console_log = "1"
|
console_log = "1"
|
||||||
cfg-if = "1"
|
cfg-if = "1"
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
use crate::error_template::{AppError, ErrorTemplate};
|
use crate::error_template::{AppError, ErrorTemplate};
|
||||||
|
use codee::string::FromToStringCodec;
|
||||||
use leptos::ev::{keypress, KeyboardEvent};
|
use leptos::ev::{keypress, KeyboardEvent};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_meta::*;
|
use leptos_meta::*;
|
||||||
use leptos_router::*;
|
use leptos_router::*;
|
||||||
use leptos_use::storage::{use_local_storage, use_local_storage_with_options, UseStorageOptions};
|
use leptos_use::storage::{use_local_storage, use_local_storage_with_options, UseStorageOptions};
|
||||||
use leptos_use::utils::FromToStringCodec;
|
|
||||||
use leptos_use::{
|
use leptos_use::{
|
||||||
use_color_mode_with_options, use_cookie_with_options, use_debounce_fn, use_event_listener,
|
use_color_mode_with_options, use_cookie_with_options, use_debounce_fn, use_event_listener,
|
||||||
use_interval, use_intl_number_format, use_preferred_dark, use_timestamp, use_window, ColorMode,
|
use_interval, use_intl_number_format, use_locales, use_preferred_dark, use_timestamp,
|
||||||
UseColorModeOptions, UseColorModeReturn, UseCookieOptions, UseIntervalReturn,
|
use_window, ColorMode, UseColorModeOptions, UseColorModeReturn, UseCookieOptions,
|
||||||
UseIntlNumberFormatOptions,
|
UseIntervalReturn, UseIntlNumberFormatOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
|
@ -78,17 +78,18 @@ fn HomePage() -> impl IntoView {
|
||||||
|
|
||||||
let (test_cookie, _) = use_cookie_with_options::<String, FromToStringCodec>(
|
let (test_cookie, _) = use_cookie_with_options::<String, FromToStringCodec>(
|
||||||
"test-cookie",
|
"test-cookie",
|
||||||
UseCookieOptions::<String, _>::default()
|
UseCookieOptions::<String, _, _>::default()
|
||||||
.max_age(3000)
|
.max_age(3000)
|
||||||
.default_value(Some("Bogus string".to_owned())),
|
.default_value(Some("Bogus string".to_owned())),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let locales = use_locales();
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<Html class=move || mode.get().to_string()/>
|
<Html class=move || mode.get().to_string()/>
|
||||||
|
|
||||||
<h1>Leptos-Use SSR Example</h1>
|
<h1>Leptos-Use SSR Example</h1>
|
||||||
<button on:click=on_click>Click Me: {count}</button>
|
<button on:click=on_click>Click Me: {count}</button>
|
||||||
<p>Locale zh-Hans-CN-u-nu-hanidec: {zh_count}</p>
|
|
||||||
<p>Press any key: {key}</p>
|
<p>Press any key: {key}</p>
|
||||||
<p>Debounced called: {debounce_value}</p>
|
<p>Debounced called: {debounce_value}</p>
|
||||||
<p>Color mode: {move || format!("{:?}", mode.get())}</p>
|
<p>Color mode: {move || format!("{:?}", mode.get())}</p>
|
||||||
|
@ -99,7 +100,10 @@ fn HomePage() -> impl IntoView {
|
||||||
<p>Dark preferred: {is_dark_preferred}</p>
|
<p>Dark preferred: {is_dark_preferred}</p>
|
||||||
<LocalStorageTest/>
|
<LocalStorageTest/>
|
||||||
<p>Test cookie: {move || test_cookie().unwrap_or("<Expired>".to_string())}</p>
|
<p>Test cookie: {move || test_cookie().unwrap_or("<Expired>".to_string())}</p>
|
||||||
|
<pre>{move || format!("Locales:\n {}", locales().join("\n "))}</pre>
|
||||||
|
|
||||||
|
<p>Locale zh-Hans-CN-u-nu-hanidec: {zh_count}</p>
|
||||||
|
|
||||||
<Show when={move || count() > 0 }>
|
<Show when={move || count() > 0 }>
|
||||||
<div>Greater than 0 </div>
|
<div>Greater than 0 </div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
|
@ -5,6 +5,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||||
|
codee = "0.1"
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
console_log = "1"
|
console_log = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
use codee::string::FromToStringCodec;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_use::docs::demo_or_body;
|
use leptos_use::docs::demo_or_body;
|
||||||
use leptos_use::utils::FromToStringCodec;
|
|
||||||
use leptos_use::{use_broadcast_channel, UseBroadcastChannelReturn};
|
use leptos_use::{use_broadcast_channel, UseBroadcastChannelReturn};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
|
@ -46,8 +46,8 @@ fn Demo() -> impl IntoView {
|
||||||
<p>"Received message: " {move || message().as_ref().unwrap().to_string()}</p>
|
<p>"Received message: " {move || message().as_ref().unwrap().to_string()}</p>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
<Show when=move || error().is_some()>
|
<Show when=move || error.with(|e| e.is_some())>
|
||||||
<p>"Error: " {move || format!("{:?}", error().as_ref().unwrap())}</p>
|
<p>"Error: " {move || error.with(|e| format!("{:?}", e.as_ref().unwrap()))}</p>
|
||||||
</Show>
|
</Show>
|
||||||
</Show>
|
</Show>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_use::docs::{demo_or_body, Note};
|
use leptos_use::docs::{demo_or_body, Note};
|
||||||
use leptos_use::{use_clipboard, use_permission, UseClipboardReturn};
|
use leptos_use::{
|
||||||
|
use_clipboard_with_options, use_permission, UseClipboardOptions, UseClipboardReturn,
|
||||||
|
};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn Demo() -> impl IntoView {
|
fn Demo() -> impl IntoView {
|
||||||
|
@ -11,7 +13,7 @@ fn Demo() -> impl IntoView {
|
||||||
text,
|
text,
|
||||||
copied,
|
copied,
|
||||||
copy,
|
copy,
|
||||||
} = use_clipboard();
|
} = use_clipboard_with_options(UseClipboardOptions::default().read(true));
|
||||||
|
|
||||||
let permission_read = use_permission("clipboard-read");
|
let permission_read = use_permission("clipboard-read");
|
||||||
let permission_write = use_permission("clipboard-write");
|
let permission_write = use_permission("clipboard-write");
|
||||||
|
|
|
@ -5,6 +5,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||||
|
codee = "0.1"
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
console_log = "1"
|
console_log = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_use::docs::demo_or_body;
|
use leptos_use::docs::demo_or_body;
|
||||||
use leptos_use::use_cookie;
|
use leptos_use::use_cookie;
|
||||||
use leptos_use::utils::FromToStringCodec;
|
use codee::string::FromToStringCodec;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
|
|
16
examples/use_locale/Cargo.toml
Normal file
16
examples/use_locale/Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[package]
|
||||||
|
name = "use_locale"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||||
|
console_error_panic_hook = "0.1"
|
||||||
|
console_log = "1"
|
||||||
|
log = "0.4"
|
||||||
|
leptos-use = { path = "../..", features = ["docs"] }
|
||||||
|
web-sys = "0.3"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
wasm-bindgen = "0.2"
|
||||||
|
wasm-bindgen-test = "0.3.0"
|
23
examples/use_locale/README.md
Normal file
23
examples/use_locale/README.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
A simple example for `use_locale`.
|
||||||
|
|
||||||
|
If you don't have it installed already, install [Trunk](https://trunkrs.dev/) and [Tailwind](https://tailwindcss.com/docs/installation)
|
||||||
|
as well as the nightly toolchain for Rust and the wasm32-unknown-unknown target:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo install trunk
|
||||||
|
npm install -D tailwindcss @tailwindcss/forms
|
||||||
|
rustup toolchain install nightly
|
||||||
|
rustup target add wasm32-unknown-unknown
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, open two terminals. In the first one, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
npx tailwindcss -i ./input.css -o ./style/output.css --watch
|
||||||
|
```
|
||||||
|
|
||||||
|
In the second one, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
trunk serve --open
|
||||||
|
```
|
2
examples/use_locale/Trunk.toml
Normal file
2
examples/use_locale/Trunk.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[build]
|
||||||
|
public_url = "/demo/"
|
7
examples/use_locale/index.html
Normal file
7
examples/use_locale/index.html
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link data-trunk rel="css" href="style/output.css">
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
3
examples/use_locale/input.css
Normal file
3
examples/use_locale/input.css
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
2
examples/use_locale/rust-toolchain.toml
Normal file
2
examples/use_locale/rust-toolchain.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[toolchain]
|
||||||
|
channel = "nightly"
|
21
examples/use_locale/src/main.rs
Normal file
21
examples/use_locale/src/main.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
use leptos::*;
|
||||||
|
use leptos_use::docs::demo_or_body;
|
||||||
|
use leptos_use::use_locale;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn Demo() -> impl IntoView {
|
||||||
|
let locale = use_locale(["en", "de", "fr"]);
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<p>Locale: <code class="font-bold">{locale}</code></p>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
_ = console_log::init_with_level(log::Level::Debug);
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
|
||||||
|
mount_to(demo_or_body(), || {
|
||||||
|
view! { <Demo/> }
|
||||||
|
})
|
||||||
|
}
|
330
examples/use_locale/style/output.css
Normal file
330
examples/use_locale/style/output.css
Normal file
|
@ -0,0 +1,330 @@
|
||||||
|
[type='text'],input:where(:not([type])),[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: #6b7280;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 0px;
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='text']:focus, input:where(:not([type])):focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
|
||||||
|
outline: 2px solid transparent;
|
||||||
|
outline-offset: 2px;
|
||||||
|
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
|
||||||
|
--tw-ring-offset-width: 0px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: #2563eb;
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
|
border-color: #2563eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::-moz-placeholder, textarea::-moz-placeholder {
|
||||||
|
color: #6b7280;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::placeholder,textarea::placeholder {
|
||||||
|
color: #6b7280;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-datetime-edit-fields-wrapper {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-date-and-time-value {
|
||||||
|
min-height: 1.5em;
|
||||||
|
text-align: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-datetime-edit {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||||
|
background-position: right 0.5rem center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 1.5em 1.5em;
|
||||||
|
padding-right: 2.5rem;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
|
||||||
|
[multiple],[size]:where(select:not([size="1"])) {
|
||||||
|
background-image: initial;
|
||||||
|
background-position: initial;
|
||||||
|
background-repeat: unset;
|
||||||
|
background-size: initial;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
-webkit-print-color-adjust: unset;
|
||||||
|
print-color-adjust: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox'],[type='radio'] {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
padding: 0;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-origin: border-box;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 1rem;
|
||||||
|
width: 1rem;
|
||||||
|
color: #2563eb;
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: #6b7280;
|
||||||
|
border-width: 1px;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox'] {
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='radio'] {
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:focus,[type='radio']:focus {
|
||||||
|
outline: 2px solid transparent;
|
||||||
|
outline-offset: 2px;
|
||||||
|
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
|
||||||
|
--tw-ring-offset-width: 2px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: #2563eb;
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:checked,[type='radio']:checked {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:checked {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
[type='checkbox']:checked {
|
||||||
|
-webkit-appearance: auto;
|
||||||
|
-moz-appearance: auto;
|
||||||
|
appearance: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='radio']:checked {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
[type='radio']:checked {
|
||||||
|
-webkit-appearance: auto;
|
||||||
|
-moz-appearance: auto;
|
||||||
|
appearance: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:indeterminate {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
[type='checkbox']:indeterminate {
|
||||||
|
-webkit-appearance: auto;
|
||||||
|
-moz-appearance: auto;
|
||||||
|
appearance: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='file'] {
|
||||||
|
background: unset;
|
||||||
|
border-color: inherit;
|
||||||
|
border-width: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: unset;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='file']:focus {
|
||||||
|
outline: 1px solid ButtonText;
|
||||||
|
outline: 1px auto -webkit-focus-ring-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
*, ::before, ::after {
|
||||||
|
--tw-border-spacing-x: 0;
|
||||||
|
--tw-border-spacing-y: 0;
|
||||||
|
--tw-translate-x: 0;
|
||||||
|
--tw-translate-y: 0;
|
||||||
|
--tw-rotate: 0;
|
||||||
|
--tw-skew-x: 0;
|
||||||
|
--tw-skew-y: 0;
|
||||||
|
--tw-scale-x: 1;
|
||||||
|
--tw-scale-y: 1;
|
||||||
|
--tw-pan-x: ;
|
||||||
|
--tw-pan-y: ;
|
||||||
|
--tw-pinch-zoom: ;
|
||||||
|
--tw-scroll-snap-strictness: proximity;
|
||||||
|
--tw-gradient-from-position: ;
|
||||||
|
--tw-gradient-via-position: ;
|
||||||
|
--tw-gradient-to-position: ;
|
||||||
|
--tw-ordinal: ;
|
||||||
|
--tw-slashed-zero: ;
|
||||||
|
--tw-numeric-figure: ;
|
||||||
|
--tw-numeric-spacing: ;
|
||||||
|
--tw-numeric-fraction: ;
|
||||||
|
--tw-ring-inset: ;
|
||||||
|
--tw-ring-offset-width: 0px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: rgb(59 130 246 / 0.5);
|
||||||
|
--tw-ring-offset-shadow: 0 0 #0000;
|
||||||
|
--tw-ring-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow-colored: 0 0 #0000;
|
||||||
|
--tw-blur: ;
|
||||||
|
--tw-brightness: ;
|
||||||
|
--tw-contrast: ;
|
||||||
|
--tw-grayscale: ;
|
||||||
|
--tw-hue-rotate: ;
|
||||||
|
--tw-invert: ;
|
||||||
|
--tw-saturate: ;
|
||||||
|
--tw-sepia: ;
|
||||||
|
--tw-drop-shadow: ;
|
||||||
|
--tw-backdrop-blur: ;
|
||||||
|
--tw-backdrop-brightness: ;
|
||||||
|
--tw-backdrop-contrast: ;
|
||||||
|
--tw-backdrop-grayscale: ;
|
||||||
|
--tw-backdrop-hue-rotate: ;
|
||||||
|
--tw-backdrop-invert: ;
|
||||||
|
--tw-backdrop-opacity: ;
|
||||||
|
--tw-backdrop-saturate: ;
|
||||||
|
--tw-backdrop-sepia: ;
|
||||||
|
--tw-contain-size: ;
|
||||||
|
--tw-contain-layout: ;
|
||||||
|
--tw-contain-paint: ;
|
||||||
|
--tw-contain-style: ;
|
||||||
|
}
|
||||||
|
|
||||||
|
::backdrop {
|
||||||
|
--tw-border-spacing-x: 0;
|
||||||
|
--tw-border-spacing-y: 0;
|
||||||
|
--tw-translate-x: 0;
|
||||||
|
--tw-translate-y: 0;
|
||||||
|
--tw-rotate: 0;
|
||||||
|
--tw-skew-x: 0;
|
||||||
|
--tw-skew-y: 0;
|
||||||
|
--tw-scale-x: 1;
|
||||||
|
--tw-scale-y: 1;
|
||||||
|
--tw-pan-x: ;
|
||||||
|
--tw-pan-y: ;
|
||||||
|
--tw-pinch-zoom: ;
|
||||||
|
--tw-scroll-snap-strictness: proximity;
|
||||||
|
--tw-gradient-from-position: ;
|
||||||
|
--tw-gradient-via-position: ;
|
||||||
|
--tw-gradient-to-position: ;
|
||||||
|
--tw-ordinal: ;
|
||||||
|
--tw-slashed-zero: ;
|
||||||
|
--tw-numeric-figure: ;
|
||||||
|
--tw-numeric-spacing: ;
|
||||||
|
--tw-numeric-fraction: ;
|
||||||
|
--tw-ring-inset: ;
|
||||||
|
--tw-ring-offset-width: 0px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: rgb(59 130 246 / 0.5);
|
||||||
|
--tw-ring-offset-shadow: 0 0 #0000;
|
||||||
|
--tw-ring-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow-colored: 0 0 #0000;
|
||||||
|
--tw-blur: ;
|
||||||
|
--tw-brightness: ;
|
||||||
|
--tw-contrast: ;
|
||||||
|
--tw-grayscale: ;
|
||||||
|
--tw-hue-rotate: ;
|
||||||
|
--tw-invert: ;
|
||||||
|
--tw-saturate: ;
|
||||||
|
--tw-sepia: ;
|
||||||
|
--tw-drop-shadow: ;
|
||||||
|
--tw-backdrop-blur: ;
|
||||||
|
--tw-backdrop-brightness: ;
|
||||||
|
--tw-backdrop-contrast: ;
|
||||||
|
--tw-backdrop-grayscale: ;
|
||||||
|
--tw-backdrop-hue-rotate: ;
|
||||||
|
--tw-backdrop-invert: ;
|
||||||
|
--tw-backdrop-opacity: ;
|
||||||
|
--tw-backdrop-saturate: ;
|
||||||
|
--tw-backdrop-sepia: ;
|
||||||
|
--tw-contain-size: ;
|
||||||
|
--tw-contain-layout: ;
|
||||||
|
--tw-contain-paint: ;
|
||||||
|
--tw-contain-style: ;
|
||||||
|
}
|
||||||
|
|
||||||
|
.static {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-bold {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[--brand-color\] {
|
||||||
|
color: var(--brand-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-green-600 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(22 163 74 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.opacity-75 {
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.dark\:text-green-500 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(34 197 94 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
}
|
15
examples/use_locale/tailwind.config.js
Normal file
15
examples/use_locale/tailwind.config.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: {
|
||||||
|
files: ["*.html", "./src/**/*.rs", "../../src/docs/**/*.rs"],
|
||||||
|
},
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
corePlugins: {
|
||||||
|
preflight: false,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
require('@tailwindcss/forms'),
|
||||||
|
],
|
||||||
|
}
|
16
examples/use_locales/Cargo.toml
Normal file
16
examples/use_locales/Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[package]
|
||||||
|
name = "use_locales"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||||
|
console_error_panic_hook = "0.1"
|
||||||
|
console_log = "1"
|
||||||
|
log = "0.4"
|
||||||
|
leptos-use = { path = "../..", features = ["docs"] }
|
||||||
|
web-sys = "0.3"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
wasm-bindgen = "0.2"
|
||||||
|
wasm-bindgen-test = "0.3.0"
|
23
examples/use_locales/README.md
Normal file
23
examples/use_locales/README.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
A simple example for `use_locales`.
|
||||||
|
|
||||||
|
If you don't have it installed already, install [Trunk](https://trunkrs.dev/) and [Tailwind](https://tailwindcss.com/docs/installation)
|
||||||
|
as well as the nightly toolchain for Rust and the wasm32-unknown-unknown target:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo install trunk
|
||||||
|
npm install -D tailwindcss @tailwindcss/forms
|
||||||
|
rustup toolchain install nightly
|
||||||
|
rustup target add wasm32-unknown-unknown
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, open two terminals. In the first one, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
npx tailwindcss -i ./input.css -o ./style/output.css --watch
|
||||||
|
```
|
||||||
|
|
||||||
|
In the second one, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
trunk serve --open
|
||||||
|
```
|
2
examples/use_locales/Trunk.toml
Normal file
2
examples/use_locales/Trunk.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[build]
|
||||||
|
public_url = "/demo/"
|
7
examples/use_locales/index.html
Normal file
7
examples/use_locales/index.html
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link data-trunk rel="css" href="style/output.css">
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
3
examples/use_locales/input.css
Normal file
3
examples/use_locales/input.css
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
2
examples/use_locales/rust-toolchain.toml
Normal file
2
examples/use_locales/rust-toolchain.toml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[toolchain]
|
||||||
|
channel = "nightly"
|
21
examples/use_locales/src/main.rs
Normal file
21
examples/use_locales/src/main.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
use leptos::*;
|
||||||
|
use leptos_use::docs::demo_or_body;
|
||||||
|
use leptos_use::use_locales;
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn Demo() -> impl IntoView {
|
||||||
|
let locales = use_locales();
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<pre>{move || format!("Locales:\n {}", locales().join("\n "))}</pre>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
_ = console_log::init_with_level(log::Level::Debug);
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
|
||||||
|
mount_to(demo_or_body(), || {
|
||||||
|
view! { <Demo/> }
|
||||||
|
})
|
||||||
|
}
|
289
examples/use_locales/style/output.css
Normal file
289
examples/use_locales/style/output.css
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
[type='text'],[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: #6b7280;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 0px;
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
padding-left: 0.75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='text']:focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus {
|
||||||
|
outline: 2px solid transparent;
|
||||||
|
outline-offset: 2px;
|
||||||
|
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
|
||||||
|
--tw-ring-offset-width: 0px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: #2563eb;
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
|
border-color: #2563eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::-moz-placeholder, textarea::-moz-placeholder {
|
||||||
|
color: #6b7280;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::placeholder,textarea::placeholder {
|
||||||
|
color: #6b7280;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-datetime-edit-fields-wrapper {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-date-and-time-value {
|
||||||
|
min-height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field {
|
||||||
|
padding-top: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||||
|
background-position: right 0.5rem center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 1.5em 1.5em;
|
||||||
|
padding-right: 2.5rem;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
|
||||||
|
[multiple] {
|
||||||
|
background-image: initial;
|
||||||
|
background-position: initial;
|
||||||
|
background-repeat: unset;
|
||||||
|
background-size: initial;
|
||||||
|
padding-right: 0.75rem;
|
||||||
|
-webkit-print-color-adjust: unset;
|
||||||
|
print-color-adjust: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox'],[type='radio'] {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
padding: 0;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-origin: border-box;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: 1rem;
|
||||||
|
width: 1rem;
|
||||||
|
color: #2563eb;
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: #6b7280;
|
||||||
|
border-width: 1px;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox'] {
|
||||||
|
border-radius: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='radio'] {
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:focus,[type='radio']:focus {
|
||||||
|
outline: 2px solid transparent;
|
||||||
|
outline-offset: 2px;
|
||||||
|
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
|
||||||
|
--tw-ring-offset-width: 2px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: #2563eb;
|
||||||
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:checked,[type='radio']:checked {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:checked {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='radio']:checked {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e");
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:indeterminate {
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus {
|
||||||
|
border-color: transparent;
|
||||||
|
background-color: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='file'] {
|
||||||
|
background: unset;
|
||||||
|
border-color: inherit;
|
||||||
|
border-width: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: unset;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
[type='file']:focus {
|
||||||
|
outline: 1px solid ButtonText;
|
||||||
|
outline: 1px auto -webkit-focus-ring-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
*, ::before, ::after {
|
||||||
|
--tw-border-spacing-x: 0;
|
||||||
|
--tw-border-spacing-y: 0;
|
||||||
|
--tw-translate-x: 0;
|
||||||
|
--tw-translate-y: 0;
|
||||||
|
--tw-rotate: 0;
|
||||||
|
--tw-skew-x: 0;
|
||||||
|
--tw-skew-y: 0;
|
||||||
|
--tw-scale-x: 1;
|
||||||
|
--tw-scale-y: 1;
|
||||||
|
--tw-pan-x: ;
|
||||||
|
--tw-pan-y: ;
|
||||||
|
--tw-pinch-zoom: ;
|
||||||
|
--tw-scroll-snap-strictness: proximity;
|
||||||
|
--tw-gradient-from-position: ;
|
||||||
|
--tw-gradient-via-position: ;
|
||||||
|
--tw-gradient-to-position: ;
|
||||||
|
--tw-ordinal: ;
|
||||||
|
--tw-slashed-zero: ;
|
||||||
|
--tw-numeric-figure: ;
|
||||||
|
--tw-numeric-spacing: ;
|
||||||
|
--tw-numeric-fraction: ;
|
||||||
|
--tw-ring-inset: ;
|
||||||
|
--tw-ring-offset-width: 0px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: rgb(59 130 246 / 0.5);
|
||||||
|
--tw-ring-offset-shadow: 0 0 #0000;
|
||||||
|
--tw-ring-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow-colored: 0 0 #0000;
|
||||||
|
--tw-blur: ;
|
||||||
|
--tw-brightness: ;
|
||||||
|
--tw-contrast: ;
|
||||||
|
--tw-grayscale: ;
|
||||||
|
--tw-hue-rotate: ;
|
||||||
|
--tw-invert: ;
|
||||||
|
--tw-saturate: ;
|
||||||
|
--tw-sepia: ;
|
||||||
|
--tw-drop-shadow: ;
|
||||||
|
--tw-backdrop-blur: ;
|
||||||
|
--tw-backdrop-brightness: ;
|
||||||
|
--tw-backdrop-contrast: ;
|
||||||
|
--tw-backdrop-grayscale: ;
|
||||||
|
--tw-backdrop-hue-rotate: ;
|
||||||
|
--tw-backdrop-invert: ;
|
||||||
|
--tw-backdrop-opacity: ;
|
||||||
|
--tw-backdrop-saturate: ;
|
||||||
|
--tw-backdrop-sepia: ;
|
||||||
|
}
|
||||||
|
|
||||||
|
::backdrop {
|
||||||
|
--tw-border-spacing-x: 0;
|
||||||
|
--tw-border-spacing-y: 0;
|
||||||
|
--tw-translate-x: 0;
|
||||||
|
--tw-translate-y: 0;
|
||||||
|
--tw-rotate: 0;
|
||||||
|
--tw-skew-x: 0;
|
||||||
|
--tw-skew-y: 0;
|
||||||
|
--tw-scale-x: 1;
|
||||||
|
--tw-scale-y: 1;
|
||||||
|
--tw-pan-x: ;
|
||||||
|
--tw-pan-y: ;
|
||||||
|
--tw-pinch-zoom: ;
|
||||||
|
--tw-scroll-snap-strictness: proximity;
|
||||||
|
--tw-gradient-from-position: ;
|
||||||
|
--tw-gradient-via-position: ;
|
||||||
|
--tw-gradient-to-position: ;
|
||||||
|
--tw-ordinal: ;
|
||||||
|
--tw-slashed-zero: ;
|
||||||
|
--tw-numeric-figure: ;
|
||||||
|
--tw-numeric-spacing: ;
|
||||||
|
--tw-numeric-fraction: ;
|
||||||
|
--tw-ring-inset: ;
|
||||||
|
--tw-ring-offset-width: 0px;
|
||||||
|
--tw-ring-offset-color: #fff;
|
||||||
|
--tw-ring-color: rgb(59 130 246 / 0.5);
|
||||||
|
--tw-ring-offset-shadow: 0 0 #0000;
|
||||||
|
--tw-ring-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow: 0 0 #0000;
|
||||||
|
--tw-shadow-colored: 0 0 #0000;
|
||||||
|
--tw-blur: ;
|
||||||
|
--tw-brightness: ;
|
||||||
|
--tw-contrast: ;
|
||||||
|
--tw-grayscale: ;
|
||||||
|
--tw-hue-rotate: ;
|
||||||
|
--tw-invert: ;
|
||||||
|
--tw-saturate: ;
|
||||||
|
--tw-sepia: ;
|
||||||
|
--tw-drop-shadow: ;
|
||||||
|
--tw-backdrop-blur: ;
|
||||||
|
--tw-backdrop-brightness: ;
|
||||||
|
--tw-backdrop-contrast: ;
|
||||||
|
--tw-backdrop-grayscale: ;
|
||||||
|
--tw-backdrop-hue-rotate: ;
|
||||||
|
--tw-backdrop-invert: ;
|
||||||
|
--tw-backdrop-opacity: ;
|
||||||
|
--tw-backdrop-saturate: ;
|
||||||
|
--tw-backdrop-sepia: ;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-\[--brand-color\] {
|
||||||
|
color: var(--brand-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-green-600 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(22 163 74 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.opacity-75 {
|
||||||
|
opacity: 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.dark\:text-green-500 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(34 197 94 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
}
|
15
examples/use_locales/tailwind.config.js
Normal file
15
examples/use_locales/tailwind.config.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: {
|
||||||
|
files: ["*.html", "./src/**/*.rs", "../../src/docs/**/*.rs"],
|
||||||
|
},
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
corePlugins: {
|
||||||
|
preflight: false,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
require('@tailwindcss/forms'),
|
||||||
|
],
|
||||||
|
}
|
|
@ -4,14 +4,14 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
codee = { path = "../../../codee", features = ["json_serde"] }
|
codee = { version = "0.1", features = ["json_serde"] }
|
||||||
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
console_log = "1"
|
console_log = "1"
|
||||||
log = "0.4"
|
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||||
leptos-use = { path = "../..", features = ["docs"] }
|
leptos-use = { path = "../..", features = ["docs"] }
|
||||||
web-sys = "0.3"
|
log = "0.4"
|
||||||
serde = "1.0.163"
|
serde = "1.0.163"
|
||||||
|
web-sys = "0.3"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
wasm-bindgen = "0.2"
|
wasm-bindgen = "0.2"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_use::docs::{demo_or_body, Note};
|
use leptos_use::docs::{demo_or_body, Note};
|
||||||
use leptos_use::storage::use_local_storage;
|
use leptos_use::storage::use_local_storage;
|
||||||
use leptos_use::utils::JsonCodec;
|
use codee::string::JsonSerdeCodec;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||||
|
@ -25,8 +25,8 @@ impl Default for BananaState {
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn Demo() -> impl IntoView {
|
fn Demo() -> impl IntoView {
|
||||||
let (state, set_state, reset) = use_local_storage::<BananaState, JsonCodec>("banana-state");
|
let (state, set_state, reset) = use_local_storage::<BananaState, JsonSerdeCodec>("banana-state");
|
||||||
let (state2, _, _) = use_local_storage::<BananaState, JsonCodec>("banana-state");
|
let (state2, _, _) = use_local_storage::<BananaState, JsonSerdeCodec>("banana-state");
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<input
|
<input
|
||||||
|
|
|
@ -5,7 +5,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||||
codee = { path = "../../../codee", features = ["msgpack_serde"] }
|
codee = { version = "0.1", features = ["msgpack_serde"] }
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
console_log = "1"
|
console_log = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
|
@ -6,12 +6,14 @@ use std::marker::PhantomData;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
/// Used as an argument type to make it easily possible to pass either
|
/// Used as an argument type to make it easily possible to pass either
|
||||||
|
///
|
||||||
/// * a `web_sys` element that implements `E` (for example `EventTarget`, `Element` or `HtmlElement`),
|
/// * a `web_sys` element that implements `E` (for example `EventTarget`, `Element` or `HtmlElement`),
|
||||||
/// * an `Option<T>` where `T` is the web_sys element,
|
/// * an `Option<T>` where `T` is the web_sys element,
|
||||||
/// * a `Signal<T>` where `T` is the web_sys element,
|
/// * a `Signal<T>` where `T` is the web_sys element,
|
||||||
/// * a `Signal<Option<T>>` where `T` is the web_sys element,
|
/// * a `Signal<Option<T>>` where `T` is the web_sys element,
|
||||||
/// * a `NodeRef`
|
/// * a `NodeRef`
|
||||||
/// into a function. Used for example in [`use_event_listener`].
|
///
|
||||||
|
/// into a function. Used for example in [`fn@crate::use_event_listener`].
|
||||||
pub enum ElementMaybeSignal<T, E>
|
pub enum ElementMaybeSignal<T, E>
|
||||||
where
|
where
|
||||||
T: Into<E> + Clone + 'static,
|
T: Into<E> + Clone + 'static,
|
||||||
|
|
|
@ -7,12 +7,14 @@ use std::marker::PhantomData;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
/// Used as an argument type to make it easily possible to pass either
|
/// Used as an argument type to make it easily possible to pass either
|
||||||
|
///
|
||||||
/// * a `web_sys` element that implements `E` (for example `EventTarget` or `Element`),
|
/// * a `web_sys` element that implements `E` (for example `EventTarget` or `Element`),
|
||||||
/// * an `Option<T>` where `T` is the web_sys element,
|
/// * an `Option<T>` where `T` is the web_sys element,
|
||||||
/// * a `Signal<T>` where `T` is the web_sys element,
|
/// * a `Signal<T>` where `T` is the web_sys element,
|
||||||
/// * a `Signal<Option<T>>` where `T` is the web_sys element,
|
/// * a `Signal<Option<T>>` where `T` is the web_sys element,
|
||||||
/// * a `NodeRef`
|
/// * a `NodeRef`
|
||||||
/// into a function. Used for example in [`use_event_listener`].
|
///
|
||||||
|
/// into a function. Used for example in [`fn@crate::use_event_listener`].
|
||||||
pub enum ElementsMaybeSignal<T, E>
|
pub enum ElementsMaybeSignal<T, E>
|
||||||
where
|
where
|
||||||
T: Into<E> + Clone + 'static,
|
T: Into<E> + Clone + 'static,
|
||||||
|
|
|
@ -25,7 +25,6 @@ mod is_none;
|
||||||
mod is_ok;
|
mod is_ok;
|
||||||
mod is_some;
|
mod is_some;
|
||||||
mod on_click_outside;
|
mod on_click_outside;
|
||||||
mod use_user_media;
|
|
||||||
mod signal_debounced;
|
mod signal_debounced;
|
||||||
mod signal_throttled;
|
mod signal_throttled;
|
||||||
mod sync_signal;
|
mod sync_signal;
|
||||||
|
@ -58,6 +57,8 @@ mod use_intersection_observer;
|
||||||
mod use_interval;
|
mod use_interval;
|
||||||
mod use_interval_fn;
|
mod use_interval_fn;
|
||||||
mod use_intl_number_format;
|
mod use_intl_number_format;
|
||||||
|
mod use_locale;
|
||||||
|
mod use_locales;
|
||||||
mod use_media_query;
|
mod use_media_query;
|
||||||
mod use_mouse;
|
mod use_mouse;
|
||||||
mod use_mouse_in_element;
|
mod use_mouse_in_element;
|
||||||
|
@ -75,6 +76,7 @@ mod use_throttle_fn;
|
||||||
mod use_timeout_fn;
|
mod use_timeout_fn;
|
||||||
mod use_timestamp;
|
mod use_timestamp;
|
||||||
mod use_to_string;
|
mod use_to_string;
|
||||||
|
mod use_user_media;
|
||||||
mod use_web_notification;
|
mod use_web_notification;
|
||||||
mod use_websocket;
|
mod use_websocket;
|
||||||
mod use_window;
|
mod use_window;
|
||||||
|
@ -91,7 +93,6 @@ pub use is_none::*;
|
||||||
pub use is_ok::*;
|
pub use is_ok::*;
|
||||||
pub use is_some::*;
|
pub use is_some::*;
|
||||||
pub use on_click_outside::*;
|
pub use on_click_outside::*;
|
||||||
pub use use_user_media::*;
|
|
||||||
pub use signal_debounced::*;
|
pub use signal_debounced::*;
|
||||||
pub use signal_throttled::*;
|
pub use signal_throttled::*;
|
||||||
pub use sync_signal::*;
|
pub use sync_signal::*;
|
||||||
|
@ -124,6 +125,8 @@ pub use use_intersection_observer::*;
|
||||||
pub use use_interval::*;
|
pub use use_interval::*;
|
||||||
pub use use_interval_fn::*;
|
pub use use_interval_fn::*;
|
||||||
pub use use_intl_number_format::*;
|
pub use use_intl_number_format::*;
|
||||||
|
pub use use_locale::*;
|
||||||
|
pub use use_locales::*;
|
||||||
pub use use_media_query::*;
|
pub use use_media_query::*;
|
||||||
pub use use_mouse::*;
|
pub use use_mouse::*;
|
||||||
pub use use_mouse_in_element::*;
|
pub use use_mouse_in_element::*;
|
||||||
|
@ -141,6 +144,7 @@ pub use use_throttle_fn::*;
|
||||||
pub use use_timeout_fn::*;
|
pub use use_timeout_fn::*;
|
||||||
pub use use_timestamp::*;
|
pub use use_timestamp::*;
|
||||||
pub use use_to_string::*;
|
pub use use_to_string::*;
|
||||||
|
pub use use_user_media::*;
|
||||||
pub use use_web_notification::*;
|
pub use use_web_notification::*;
|
||||||
pub use use_websocket::*;
|
pub use use_websocket::*;
|
||||||
pub use use_window::*;
|
pub use use_window::*;
|
||||||
|
|
|
@ -45,9 +45,9 @@ cfg_if! { if #[cfg(not(feature = "ssr"))] {
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// > This function uses [Event.composedPath()](https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath)
|
/// > This function uses [Event.composedPath()](https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath)
|
||||||
/// which is **not** supported by IE 11, Edge 18 and below.
|
/// > which is **not** supported by IE 11, Edge 18 and below.
|
||||||
/// If you are targeting these browsers, we recommend you to include
|
/// > If you are targeting these browsers, we recommend you to include
|
||||||
/// [this code snippet](https://gist.github.com/sibbng/13e83b1dd1b733317ce0130ef07d4efd) on your project.
|
/// > [this code snippet](https://gist.github.com/sibbng/13e83b1dd1b733317ce0130ef07d4efd) on your project.
|
||||||
///
|
///
|
||||||
/// ## Excluding Elements
|
/// ## Excluding Elements
|
||||||
///
|
///
|
||||||
|
|
|
@ -2,14 +2,19 @@ use super::{use_storage_with_options, StorageType, UseStorageOptions};
|
||||||
use codee::{Decoder, Encoder};
|
use codee::{Decoder, Encoder};
|
||||||
use leptos::signal_prelude::*;
|
use leptos::signal_prelude::*;
|
||||||
|
|
||||||
|
#[allow(rustdoc::bare_urls)]
|
||||||
/// Reactive [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
|
/// Reactive [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
|
||||||
///
|
///
|
||||||
/// LocalStorage stores data in the browser with no expiration time. Access is given to all pages from the same origin (e.g., all pages from "https://example.com" share the same origin). While data doesn't expire the user can view, modify and delete all data stored. Browsers allow 5MB of data to be stored.
|
/// LocalStorage stores data in the browser with no expiration time. Access is given to all pages
|
||||||
|
/// from the same origin (e.g., all pages from "https://example.com" share the same origin).
|
||||||
|
/// While data doesn't expire the user can view, modify and delete all data stored.
|
||||||
|
/// Browsers allow 5MB of data to be stored.
|
||||||
///
|
///
|
||||||
/// This is contrast to [`use_session_storage`] which clears data when the page session ends and is not shared.
|
/// This is contrast to [`fn@crate::storage::use_session_storage`] which clears data when the page session ends and is not shared.
|
||||||
///
|
///
|
||||||
/// ## Usage
|
/// ## Usage
|
||||||
/// See [`use_storage`] for more details on how to use.
|
///
|
||||||
|
/// See [`fn@crate::storage::use_storage`] for more details on how to use.
|
||||||
pub fn use_local_storage<T, C>(
|
pub fn use_local_storage<T, C>(
|
||||||
key: impl AsRef<str>,
|
key: impl AsRef<str>,
|
||||||
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
|
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||||
|
|
|
@ -6,10 +6,10 @@ use leptos::signal_prelude::*;
|
||||||
///
|
///
|
||||||
/// SessionStorages stores data in the browser that is deleted when the page session ends. A page session ends when the browser closes the tab. Data is not shared between pages. While data doesn't expire the user can view, modify and delete all data stored. Browsers allow 5MB of data to be stored.
|
/// SessionStorages stores data in the browser that is deleted when the page session ends. A page session ends when the browser closes the tab. Data is not shared between pages. While data doesn't expire the user can view, modify and delete all data stored. Browsers allow 5MB of data to be stored.
|
||||||
///
|
///
|
||||||
/// Use [`use_local_storage`] to store data that is shared amongst all pages with the same origin and persists between page sessions.
|
/// Use [`fn@crate::storage::use_local_storage`] to store data that is shared amongst all pages with the same origin and persists between page sessions.
|
||||||
///
|
///
|
||||||
/// ## Usage
|
/// ## Usage
|
||||||
/// See [`use_storage`] for more details on how to use.
|
/// See [`fn@crate::storage::use_storage`] for more details on how to use.
|
||||||
pub fn use_session_storage<T, C>(
|
pub fn use_session_storage<T, C>(
|
||||||
key: impl AsRef<str>,
|
key: impl AsRef<str>,
|
||||||
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
|
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||||
|
|
|
@ -23,15 +23,15 @@ const INTERNAL_STORAGE_EVENT: &str = "leptos-use-storage";
|
||||||
///
|
///
|
||||||
/// Pass a [`StorageType`] to determine the kind of key-value browser storage to use.
|
/// Pass a [`StorageType`] to determine the kind of key-value browser storage to use.
|
||||||
/// The specified key is where data is stored. All values are stored as UTF-16 strings which
|
/// The specified key is where data is stored. All values are stored as UTF-16 strings which
|
||||||
/// is then encoded and decoded via the given [`Codec`]. This value is synced with other calls using
|
/// is then encoded and decoded via the given `*Codec`. This value is synced with other calls using
|
||||||
/// the same key on the smae page and across tabs for local storage.
|
/// the same key on the same page and across tabs for local storage.
|
||||||
/// See [`UseStorageOptions`] to see how behavior can be further customised.
|
/// See [`UseStorageOptions`] to see how behavior can be further customised.
|
||||||
///
|
///
|
||||||
/// Values are (en)decoded via the given codec. You can use any of the string codecs or a
|
/// Values are (en)decoded via the given codec. You can use any of the string codecs or a
|
||||||
/// binary codec wrapped in [`Base64`].
|
/// binary codec wrapped in `Base64`.
|
||||||
///
|
///
|
||||||
/// > Please check [the codec chapter](https://leptos-use.rs/codecs.html) to see what codecs are
|
/// > Please check [the codec chapter](https://leptos-use.rs/codecs.html) to see what codecs are
|
||||||
/// available and what feature flags they require.
|
/// > available and what feature flags they require.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
|
@ -276,13 +276,17 @@ where
|
||||||
let notify = create_trigger();
|
let notify = create_trigger();
|
||||||
|
|
||||||
// Refetch from storage. Keeps track of how many times we've been notified. Does not increment for calls to set_data
|
// Refetch from storage. Keeps track of how many times we've been notified. Does not increment for calls to set_data
|
||||||
let notify_id = create_memo::<usize>(move |prev| {
|
let notify_id = create_memo::<usize>({
|
||||||
notify.track();
|
let fetch_from_storage = fetch_from_storage.clone();
|
||||||
match prev {
|
|
||||||
None => 1, // Avoid async fetch of initial value
|
move |prev| {
|
||||||
Some(prev) => {
|
notify.track();
|
||||||
fetch_from_storage();
|
match prev {
|
||||||
prev + 1
|
None => 1, // Avoid async fetch of initial value
|
||||||
|
Some(prev) => {
|
||||||
|
fetch_from_storage();
|
||||||
|
prev + 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -391,7 +395,7 @@ pub enum UseStorageError<E, D> {
|
||||||
ItemCodecError(CodecError<E, D>),
|
ItemCodecError(CodecError<E, D>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Options for use with [`use_local_storage_with_options`], [`use_session_storage_with_options`] and [`use_storage_with_options`].
|
/// Options for use with [`fn@crate::storage::use_local_storage_with_options`], [`fn@crate::storage::use_session_storage_with_options`] and [`use_storage_with_options`].
|
||||||
#[derive(DefaultBuilder)]
|
#[derive(DefaultBuilder)]
|
||||||
pub struct UseStorageOptions<T, E, D>
|
pub struct UseStorageOptions<T, E, D>
|
||||||
where
|
where
|
||||||
|
|
|
@ -37,6 +37,7 @@ use std::hash::Hash;
|
||||||
/// ## Breakpoints
|
/// ## Breakpoints
|
||||||
///
|
///
|
||||||
/// There are many predefined breakpoints for major UI frameworks. The following are provided.
|
/// There are many predefined breakpoints for major UI frameworks. The following are provided.
|
||||||
|
///
|
||||||
/// * [`breakpoints_tailwind`]
|
/// * [`breakpoints_tailwind`]
|
||||||
/// * [`breakpoints_bootstrap_v5`]
|
/// * [`breakpoints_bootstrap_v5`]
|
||||||
/// * [`breakpoints_material`]
|
/// * [`breakpoints_material`]
|
||||||
|
@ -107,7 +108,7 @@ use std::hash::Hash;
|
||||||
///
|
///
|
||||||
/// ## Server-Side Rendering
|
/// ## Server-Side Rendering
|
||||||
///
|
///
|
||||||
/// Since internally this uses [`use_media_query`], which returns always `false` on the server,
|
/// Since internally this uses [`fn@crate::use_media_query`], which returns always `false` on the server,
|
||||||
/// the returned methods also will return `false`.
|
/// the returned methods also will return `false`.
|
||||||
pub fn use_breakpoints<K: Eq + Hash + Debug + Clone>(
|
pub fn use_breakpoints<K: Eq + Hash + Debug + Clone>(
|
||||||
breakpoints: HashMap<K, u32>,
|
breakpoints: HashMap<K, u32>,
|
||||||
|
@ -276,7 +277,7 @@ impl<K: Eq + Hash + Debug + Clone> UseBreakpointsReturn<K> {
|
||||||
|
|
||||||
/// Breakpoint keys for Tailwind V2
|
/// Breakpoint keys for Tailwind V2
|
||||||
///
|
///
|
||||||
/// See [https://tailwindcss.com/docs/breakpoints]
|
/// See <https://tailwindcss.com/docs/breakpoints>
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum BreakpointsTailwind {
|
pub enum BreakpointsTailwind {
|
||||||
Sm,
|
Sm,
|
||||||
|
@ -288,7 +289,7 @@ pub enum BreakpointsTailwind {
|
||||||
|
|
||||||
/// Breakpoint definitions for Tailwind V2
|
/// Breakpoint definitions for Tailwind V2
|
||||||
///
|
///
|
||||||
/// See [https://tailwindcss.com/docs/breakpoints]
|
/// See <https://tailwindcss.com/docs/breakpoints>
|
||||||
pub fn breakpoints_tailwind() -> HashMap<BreakpointsTailwind, u32> {
|
pub fn breakpoints_tailwind() -> HashMap<BreakpointsTailwind, u32> {
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
(BreakpointsTailwind::Sm, 640),
|
(BreakpointsTailwind::Sm, 640),
|
||||||
|
@ -301,7 +302,7 @@ pub fn breakpoints_tailwind() -> HashMap<BreakpointsTailwind, u32> {
|
||||||
|
|
||||||
/// Breakpoint keys for Bootstrap V5
|
/// Breakpoint keys for Bootstrap V5
|
||||||
///
|
///
|
||||||
/// See [https://getbootstrap.com/docs/5.0/layout/breakpoints]
|
/// See <https://getbootstrap.com/docs/5.0/layout/breakpoints>
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum BreakpointsBootstrapV5 {
|
pub enum BreakpointsBootstrapV5 {
|
||||||
Sm,
|
Sm,
|
||||||
|
@ -313,7 +314,7 @@ pub enum BreakpointsBootstrapV5 {
|
||||||
|
|
||||||
/// Breakpoint definitions for Bootstrap V5
|
/// Breakpoint definitions for Bootstrap V5
|
||||||
///
|
///
|
||||||
/// See [https://getbootstrap.com/docs/5.0/layout/breakpoints]
|
/// <https://getbootstrap.com/docs/5.0/layout/breakpoints>
|
||||||
pub fn breakpoints_bootstrap_v5() -> HashMap<BreakpointsBootstrapV5, u32> {
|
pub fn breakpoints_bootstrap_v5() -> HashMap<BreakpointsBootstrapV5, u32> {
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
(BreakpointsBootstrapV5::Sm, 576),
|
(BreakpointsBootstrapV5::Sm, 576),
|
||||||
|
@ -326,7 +327,7 @@ pub fn breakpoints_bootstrap_v5() -> HashMap<BreakpointsBootstrapV5, u32> {
|
||||||
|
|
||||||
/// Breakpoint keys for Material UI V5
|
/// Breakpoint keys for Material UI V5
|
||||||
///
|
///
|
||||||
/// See [https://mui.com/material-ui/customization/breakpoints/]
|
/// See <https://mui.com/material-ui/customization/breakpoints/>
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum BreakpointsMaterial {
|
pub enum BreakpointsMaterial {
|
||||||
Xs,
|
Xs,
|
||||||
|
@ -338,7 +339,7 @@ pub enum BreakpointsMaterial {
|
||||||
|
|
||||||
/// Breakpoint definitions for Material UI V5
|
/// Breakpoint definitions for Material UI V5
|
||||||
///
|
///
|
||||||
/// See [https://mui.com/material-ui/customization/breakpoints/]
|
/// See <https://mui.com/material-ui/customization/breakpoints/>
|
||||||
pub fn breakpoints_material() -> HashMap<BreakpointsMaterial, u32> {
|
pub fn breakpoints_material() -> HashMap<BreakpointsMaterial, u32> {
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
(BreakpointsMaterial::Xs, 1),
|
(BreakpointsMaterial::Xs, 1),
|
||||||
|
@ -351,7 +352,7 @@ pub fn breakpoints_material() -> HashMap<BreakpointsMaterial, u32> {
|
||||||
|
|
||||||
/// Breakpoint keys for Ant Design
|
/// Breakpoint keys for Ant Design
|
||||||
///
|
///
|
||||||
/// See [https://ant.design/components/layout/#breakpoint-width]
|
/// See <https://ant.design/components/layout/#breakpoint-width>
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum BreakpointsAntDesign {
|
pub enum BreakpointsAntDesign {
|
||||||
Xs,
|
Xs,
|
||||||
|
@ -364,7 +365,7 @@ pub enum BreakpointsAntDesign {
|
||||||
|
|
||||||
/// Breakpoint definitions for Ant Design
|
/// Breakpoint definitions for Ant Design
|
||||||
///
|
///
|
||||||
/// See [https://ant.design/components/layout/#breakpoint-width]
|
/// See <https://ant.design/components/layout/#breakpoint-width>
|
||||||
pub fn breakpoints_ant_design() -> HashMap<BreakpointsAntDesign, u32> {
|
pub fn breakpoints_ant_design() -> HashMap<BreakpointsAntDesign, u32> {
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
(BreakpointsAntDesign::Xs, 480),
|
(BreakpointsAntDesign::Xs, 480),
|
||||||
|
@ -378,7 +379,7 @@ pub fn breakpoints_ant_design() -> HashMap<BreakpointsAntDesign, u32> {
|
||||||
|
|
||||||
/// Breakpoint keys for Quasar V2
|
/// Breakpoint keys for Quasar V2
|
||||||
///
|
///
|
||||||
/// See [https://quasar.dev/style/breakpoints]
|
/// See <https://quasar.dev/style/breakpoints>
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum BreakpointsQuasar {
|
pub enum BreakpointsQuasar {
|
||||||
Xs,
|
Xs,
|
||||||
|
@ -390,7 +391,7 @@ pub enum BreakpointsQuasar {
|
||||||
|
|
||||||
/// Breakpoint definitions for Quasar V2
|
/// Breakpoint definitions for Quasar V2
|
||||||
///
|
///
|
||||||
/// See [https://quasar.dev/style/breakpoints]
|
/// See <https://quasar.dev/style/breakpoints>
|
||||||
pub fn breakpoints_quasar() -> HashMap<BreakpointsQuasar, u32> {
|
pub fn breakpoints_quasar() -> HashMap<BreakpointsQuasar, u32> {
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
(BreakpointsQuasar::Xs, 1),
|
(BreakpointsQuasar::Xs, 1),
|
||||||
|
@ -401,32 +402,32 @@ pub fn breakpoints_quasar() -> HashMap<BreakpointsQuasar, u32> {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Breakpoint keys for Sematic UI
|
/// Breakpoint keys for Semantic UI
|
||||||
///
|
///
|
||||||
/// See [https://semantic-ui.com/elements/container.html]
|
/// See <https://semantic-ui.com/elements/container.html>
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum BreakpointsSematic {
|
pub enum BreakpointsSemantic {
|
||||||
Mobile,
|
Mobile,
|
||||||
Tablet,
|
Tablet,
|
||||||
SmallMonitor,
|
SmallMonitor,
|
||||||
LargeMonitor,
|
LargeMonitor,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Breakpoint definitions for Sematic UI
|
/// Breakpoint definitions for Semantic UI
|
||||||
///
|
///
|
||||||
/// See [https://semantic-ui.com/elements/container.html]
|
/// See <https://semantic-ui.com/elements/container.html>
|
||||||
pub fn breakpoints_sematic() -> HashMap<BreakpointsSematic, u32> {
|
pub fn breakpoints_semantic() -> HashMap<BreakpointsSemantic, u32> {
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
(BreakpointsSematic::Mobile, 1),
|
(BreakpointsSemantic::Mobile, 1),
|
||||||
(BreakpointsSematic::Tablet, 768),
|
(BreakpointsSemantic::Tablet, 768),
|
||||||
(BreakpointsSematic::SmallMonitor, 992),
|
(BreakpointsSemantic::SmallMonitor, 992),
|
||||||
(BreakpointsSematic::LargeMonitor, 1200),
|
(BreakpointsSemantic::LargeMonitor, 1200),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Breakpoint keys for Master CSS
|
/// Breakpoint keys for Master CSS
|
||||||
///
|
///
|
||||||
/// See [https://docs.master.co/css/breakpoints]
|
/// See <https://docs.master.co/css/breakpoints>
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum BreakpointsMasterCss {
|
pub enum BreakpointsMasterCss {
|
||||||
Xxxs,
|
Xxxs,
|
||||||
|
@ -443,7 +444,7 @@ pub enum BreakpointsMasterCss {
|
||||||
|
|
||||||
/// Breakpoint definitions for Master CSS
|
/// Breakpoint definitions for Master CSS
|
||||||
///
|
///
|
||||||
/// See [https://docs.master.co/css/breakpoints]
|
/// See <https://docs.master.co/css/breakpoints>
|
||||||
pub fn breakpoints_master_css() -> HashMap<BreakpointsMasterCss, u32> {
|
pub fn breakpoints_master_css() -> HashMap<BreakpointsMasterCss, u32> {
|
||||||
HashMap::from([
|
HashMap::from([
|
||||||
(BreakpointsMasterCss::Xxxs, 360),
|
(BreakpointsMasterCss::Xxxs, 360),
|
||||||
|
|
|
@ -45,10 +45,10 @@ use wasm_bindgen::JsValue;
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Values are (en)decoded via the given codec. You can use any of the string codecs or a
|
/// Values are (en)decoded via the given codec. You can use any of the string codecs or a
|
||||||
/// binary codec wrapped in [`Base64`].
|
/// binary codec wrapped in `Base64`.
|
||||||
///
|
///
|
||||||
/// > Please check [the codec chapter](https://leptos-use.rs/codecs.html) to see what codecs are
|
/// > Please check [the codec chapter](https://leptos-use.rs/codecs.html) to see what codecs are
|
||||||
/// available and what feature flags they require.
|
/// > available and what feature flags they require.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
|
|
|
@ -11,7 +11,7 @@ use leptos::*;
|
||||||
/// Without user permission, reading or altering the clipboard contents is not permitted.
|
/// Without user permission, reading or altering the clipboard contents is not permitted.
|
||||||
///
|
///
|
||||||
/// > This function requires `--cfg=web_sys_unstable_apis` to be activated as
|
/// > This function requires `--cfg=web_sys_unstable_apis` to be activated as
|
||||||
/// [described in the wasm-bindgen guide](https://rustwasm.github.io/docs/wasm-bindgen/web-sys/unstable-apis.html).
|
/// > [described in the wasm-bindgen guide](https://rustwasm.github.io/docs/wasm-bindgen/web-sys/unstable-apis.html).
|
||||||
///
|
///
|
||||||
/// ## Demo
|
/// ## Demo
|
||||||
///
|
///
|
||||||
|
@ -29,14 +29,14 @@ use leptos::*;
|
||||||
///
|
///
|
||||||
/// view! {
|
/// view! {
|
||||||
/// <Show
|
/// <Show
|
||||||
/// when=is_supported
|
/// when=move || is_supported.get()
|
||||||
/// fallback=move || view! { <p>Your browser does not support Clipboard API</p> }
|
/// fallback=move || view! { <p>Your browser does not support Clipboard API</p> }
|
||||||
/// >
|
/// >
|
||||||
/// <button on:click={
|
/// <button on:click={
|
||||||
/// let copy = copy.clone();
|
/// let copy = copy.clone();
|
||||||
/// move |_| copy("Hello!")
|
/// move |_| copy("Hello!")
|
||||||
/// }>
|
/// }>
|
||||||
/// <Show when=copied fallback=move || "Copy">
|
/// <Show when=move || copied.get() fallback=move || "Copy">
|
||||||
/// "Copied!"
|
/// "Copied!"
|
||||||
/// </Show>
|
/// </Show>
|
||||||
/// </button>
|
/// </button>
|
||||||
|
@ -89,7 +89,7 @@ pub fn use_clipboard_with_options(
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_supported.get() && read {
|
if is_supported.get() && read {
|
||||||
let _ = use_event_listener(window(), copy, update_text.clone());
|
let _ = use_event_listener(window(), copy, update_text);
|
||||||
let _ = use_event_listener(window(), cut, update_text);
|
let _ = use_event_listener(window(), cut, update_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +127,8 @@ pub fn use_clipboard_with_options(
|
||||||
pub struct UseClipboardOptions {
|
pub struct UseClipboardOptions {
|
||||||
/// When `true` event handlers are added so that the returned signal `text` is updated whenever the clipboard changes.
|
/// When `true` event handlers are added so that the returned signal `text` is updated whenever the clipboard changes.
|
||||||
/// Defaults to `false`.
|
/// Defaults to `false`.
|
||||||
|
///
|
||||||
|
/// > Please note that clipboard changes are only detected when copying or cutting text inside the same document.
|
||||||
read: bool,
|
read: bool,
|
||||||
|
|
||||||
/// After how many milliseconds after copying should the returned signal `copied` be set to `false`?
|
/// After how many milliseconds after copying should the returned signal `copied` be set to `false`?
|
||||||
|
|
|
@ -36,7 +36,7 @@ use wasm_bindgen::JsCast;
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// By default, it will match with users' browser preference using [`use_preferred_dark`] (a.k.a. `ColorMode::Auto`).
|
/// By default, it will match with users' browser preference using [`fn@crate::use_preferred_dark`] (a.k.a. `ColorMode::Auto`).
|
||||||
/// When reading the signal, it will by default return the current color mode (`ColorMode::Dark`, `ColorMode::Light` or
|
/// When reading the signal, it will by default return the current color mode (`ColorMode::Dark`, `ColorMode::Light` or
|
||||||
/// your custom modes `ColorMode::Custom("some-custom")`). The `ColorMode::Auto` variant can
|
/// your custom modes `ColorMode::Custom("some-custom")`). The `ColorMode::Auto` variant can
|
||||||
/// be included in the returned modes by enabling the `emit_auto` option and using [`use_color_mode_with_options`].
|
/// be included in the returned modes by enabling the `emit_auto` option and using [`use_color_mode_with_options`].
|
||||||
|
@ -87,7 +87,7 @@ use wasm_bindgen::JsCast;
|
||||||
///
|
///
|
||||||
/// To persist color mode in a cookie, use `use_cookie_with_options` and specify `.cookie_enabled(true)`.
|
/// To persist color mode in a cookie, use `use_cookie_with_options` and specify `.cookie_enabled(true)`.
|
||||||
///
|
///
|
||||||
/// > Note: To work with SSR you have to add the `axum` or `actix` feature as described in [`use_cookie`].
|
/// > Note: To work with SSR you have to add the `axum` or `actix` feature as described in [`fn@crate::use_cookie`].
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
|
@ -116,13 +116,13 @@ use wasm_bindgen::JsCast;
|
||||||
///
|
///
|
||||||
/// If `cookie_enabled` is set to `true`, cookies will be used and if present this value will be used
|
/// If `cookie_enabled` is set to `true`, cookies will be used and if present this value will be used
|
||||||
/// on the server as well as on the client. Please note that you have to add the `axum` or `actix`
|
/// on the server as well as on the client. Please note that you have to add the `axum` or `actix`
|
||||||
/// feature as described in [`use_cookie`].
|
/// feature as described in [`fn@crate::use_cookie`].
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// * [`use_preferred_dark`]
|
/// * [`fn@crate::use_preferred_dark`]
|
||||||
/// * [`use_storage`]
|
/// * [`fn@crate::storage::use_storage`]
|
||||||
/// * [`use_cookie`]
|
/// * [`fn@crate::use_cookie`]
|
||||||
pub fn use_color_mode() -> UseColorModeReturn {
|
pub fn use_color_mode() -> UseColorModeReturn {
|
||||||
use_color_mode_with_options(UseColorModeOptions::default())
|
use_color_mode_with_options(UseColorModeOptions::default())
|
||||||
}
|
}
|
||||||
|
@ -426,7 +426,7 @@ where
|
||||||
/// To get the default behaviour back you can call the provided `default_handler` function.
|
/// To get the default behaviour back you can call the provided `default_handler` function.
|
||||||
/// It takes two parameters:
|
/// It takes two parameters:
|
||||||
/// - `mode: ColorMode`: The color mode to change to.
|
/// - `mode: ColorMode`: The color mode to change to.
|
||||||
/// -`default_handler: Rc<dyn Fn(ColorMode)>`: The default handler that would have been called if the `on_changed` handler had not been specified.
|
/// - `default_handler: Rc<dyn Fn(ColorMode)>`: The default handler that would have been called if the `on_changed` handler had not been specified.
|
||||||
on_changed: OnChangedFn,
|
on_changed: OnChangedFn,
|
||||||
|
|
||||||
/// When provided, `useStorage` will be skipped.
|
/// When provided, `useStorage` will be skipped.
|
||||||
|
@ -508,9 +508,9 @@ pub struct UseColorModeReturn {
|
||||||
/// Main value setter signal of the color mode
|
/// Main value setter signal of the color mode
|
||||||
pub set_mode: WriteSignal<ColorMode>,
|
pub set_mode: WriteSignal<ColorMode>,
|
||||||
|
|
||||||
/// Direct access to the returned signal of [`use_storage`] if enabled or [`UseColorModeOptions::storage_signal`] if provided
|
/// Direct access to the returned signal of [`fn@crate::storage::use_storage`] if enabled or [`UseColorModeOptions::storage_signal`] if provided
|
||||||
pub store: Signal<ColorMode>,
|
pub store: Signal<ColorMode>,
|
||||||
/// Direct write access to the returned signal of [`use_storage`] if enabled or [`UseColorModeOptions::storage_signal`] if provided
|
/// Direct write access to the returned signal of [`fn@crate::storage::use_storage`] if enabled or [`UseColorModeOptions::storage_signal`] if provided
|
||||||
pub set_store: WriteSignal<ColorMode>,
|
pub set_store: WriteSignal<ColorMode>,
|
||||||
|
|
||||||
/// Signal of the system's preferred color mode that you would get from a media query
|
/// Signal of the system's preferred color mode that you would get from a media query
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#![allow(clippy::too_many_arguments)]
|
#![allow(clippy::too_many_arguments)]
|
||||||
|
|
||||||
use crate::core::now;
|
use crate::core::now;
|
||||||
|
use crate::utils::get_header;
|
||||||
use codee::{CodecError, Decoder, Encoder};
|
use codee::{CodecError, Decoder, Encoder};
|
||||||
use cookie::time::{Duration, OffsetDateTime};
|
use cookie::time::{Duration, OffsetDateTime};
|
||||||
pub use cookie::SameSite;
|
pub use cookie::SameSite;
|
||||||
|
@ -11,7 +12,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
/// SSR-friendly and reactive cookie access.
|
/// SSR-friendly and reactive cookie access.
|
||||||
///
|
///
|
||||||
/// You can use this function multiple times in your for the same cookie and they're signals will synchronize
|
/// You can use this function multiple times for the same cookie and their signals will synchronize
|
||||||
/// (even across windows/tabs). But there is no way to listen to changes to `document.cookie` directly so in case
|
/// (even across windows/tabs). But there is no way to listen to changes to `document.cookie` directly so in case
|
||||||
/// something outside of this function changes the cookie, the signal will **not** be updated.
|
/// something outside of this function changes the cookie, the signal will **not** be updated.
|
||||||
///
|
///
|
||||||
|
@ -57,10 +58,10 @@ use std::rc::Rc;
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Values are (en)decoded via the given codec. You can use any of the string codecs or a
|
/// Values are (en)decoded via the given codec. You can use any of the string codecs or a
|
||||||
/// binary codec wrapped in [`Base64`].
|
/// binary codec wrapped in `Base64`.
|
||||||
///
|
///
|
||||||
/// > Please check [the codec chapter](https://leptos-use.rs/codecs.html) to see what codecs are
|
/// > Please check [the codec chapter](https://leptos-use.rs/codecs.html) to see what codecs are
|
||||||
/// available and what feature flags they require.
|
/// > available and what feature flags they require.
|
||||||
///
|
///
|
||||||
/// ## Cookie attributes
|
/// ## Cookie attributes
|
||||||
///
|
///
|
||||||
|
@ -92,14 +93,14 @@ use std::rc::Rc;
|
||||||
/// the HTTP response header according to options (if provided).
|
/// the HTTP response header according to options (if provided).
|
||||||
/// The returned `WriteSignal` may not affect the cookie headers on the server! It will try and write
|
/// The returned `WriteSignal` may not affect the cookie headers on the server! It will try and write
|
||||||
/// the headers buy if this happens after the headers have already been streamed to the client then
|
/// the headers buy if this happens after the headers have already been streamed to the client then
|
||||||
/// this will have no effect.
|
/// this will have no effect.
|
||||||
///
|
///
|
||||||
/// > If you're using `axum` you have to enable the `"axum"` feature in your Cargo.toml.
|
/// > If you're using `axum` you have to enable the `"axum"` feature in your Cargo.toml.
|
||||||
/// > In case it's `actix-web` enable the feature `"actix"`, for `spin` enable `"spin"`.
|
/// > In case it's `actix-web` enable the feature `"actix"`, for `spin` enable `"spin"`.
|
||||||
///
|
///
|
||||||
/// ### Bring your own header
|
/// ### Bring your own header
|
||||||
///
|
///
|
||||||
/// In case you're neither using Axum nor Actix, or the default implementation is not to your liking,
|
/// In case you're neither using Axum, Actix nor Spin, or the default implementation is not to your liking,
|
||||||
/// you can provide your own way of reading and writing the cookie header value.
|
/// you can provide your own way of reading and writing the cookie header value.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -136,10 +137,6 @@ use std::rc::Rc;
|
||||||
/// # view! {}
|
/// # view! {}
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
|
||||||
/// ## Create Your Own Custom Codec
|
|
||||||
///
|
|
||||||
/// All you need to do is to implement the [`StringCodec`] trait together with `Default` and `Clone`.
|
|
||||||
pub fn use_cookie<T, C>(cookie_name: &str) -> (Signal<Option<T>>, WriteSignal<Option<T>>)
|
pub fn use_cookie<T, C>(cookie_name: &str) -> (Signal<Option<T>>, WriteSignal<Option<T>>)
|
||||||
where
|
where
|
||||||
C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>,
|
C: Encoder<T, Encoded = String> + Decoder<T, Encoded = str>,
|
||||||
|
@ -363,6 +360,8 @@ where
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
{
|
{
|
||||||
if !readonly {
|
if !readonly {
|
||||||
|
let cookie_name = cookie_name.to_owned();
|
||||||
|
|
||||||
create_isomorphic_effect(move |_| {
|
create_isomorphic_effect(move |_| {
|
||||||
let value = cookie
|
let value = cookie
|
||||||
.with(|cookie| {
|
.with(|cookie| {
|
||||||
|
@ -373,20 +372,27 @@ where
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.flatten();
|
.flatten();
|
||||||
jar.update_value(|jar| {
|
|
||||||
write_server_cookie(
|
jar.update_value({
|
||||||
cookie_name,
|
let domain = domain.clone();
|
||||||
value,
|
let path = path.clone();
|
||||||
jar,
|
let ssr_set_cookie = Rc::clone(&ssr_set_cookie);
|
||||||
max_age,
|
|
||||||
expires,
|
|jar| {
|
||||||
domain,
|
write_server_cookie(
|
||||||
path,
|
&cookie_name,
|
||||||
same_site,
|
value,
|
||||||
secure,
|
jar,
|
||||||
http_only,
|
max_age,
|
||||||
ssr_set_cookie,
|
expires,
|
||||||
)
|
domain,
|
||||||
|
path,
|
||||||
|
same_site,
|
||||||
|
secure,
|
||||||
|
http_only,
|
||||||
|
ssr_set_cookie,
|
||||||
|
)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -491,78 +497,7 @@ impl<T, E, D> Default for UseCookieOptions<T, E, D> {
|
||||||
path: None,
|
path: None,
|
||||||
same_site: None,
|
same_site: None,
|
||||||
ssr_cookies_header_getter: Rc::new(move || {
|
ssr_cookies_header_getter: Rc::new(move || {
|
||||||
#[cfg(feature = "ssr")]
|
get_header!(COOKIE, use_cookie, ssr_cookies_header_getter)
|
||||||
{
|
|
||||||
#[cfg(all(feature = "actix", feature = "axum"))]
|
|
||||||
compile_error!("You can only enable one of features \"actix\" and \"axum\" at the same time");
|
|
||||||
|
|
||||||
#[cfg(all(feature = "actix", feature = "spin"))]
|
|
||||||
compile_error!("You can only enable one of features \"actix\" and \"spin\" at the same time");
|
|
||||||
|
|
||||||
#[cfg(all(feature = "axum", feature = "spin"))]
|
|
||||||
compile_error!("You can only enable one of features \"axum\" and \"spin\" at the same time");
|
|
||||||
|
|
||||||
#[cfg(feature = "actix")]
|
|
||||||
const COOKIE: http0_2::HeaderName = http0_2::header::COOKIE;
|
|
||||||
#[cfg(any(feature = "axum", feature = "spin"))]
|
|
||||||
const COOKIE: http1::HeaderName = http1::header::COOKIE;
|
|
||||||
|
|
||||||
#[cfg(feature = "actix")]
|
|
||||||
type HeaderValue = http0_2::HeaderValue;
|
|
||||||
#[cfg(feature = "axum")]
|
|
||||||
type HeaderValue = http1::HeaderValue;
|
|
||||||
|
|
||||||
#[cfg(any(feature = "axum", feature = "actix", feature = "spin"))]
|
|
||||||
let headers;
|
|
||||||
#[cfg(feature = "actix")]
|
|
||||||
{
|
|
||||||
headers = use_context::<actix_web::HttpRequest>()
|
|
||||||
.map(|req| req.headers().clone());
|
|
||||||
}
|
|
||||||
#[cfg(feature = "axum")]
|
|
||||||
{
|
|
||||||
headers = use_context::<http1::request::Parts>().map(|parts| parts.headers);
|
|
||||||
}
|
|
||||||
#[cfg(feature = "spin")]
|
|
||||||
{
|
|
||||||
headers = use_context::<leptos_spin::RequestParts>()
|
|
||||||
.map(|parts| parts.headers().clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(all(
|
|
||||||
not(feature = "axum"),
|
|
||||||
not(feature = "actix"),
|
|
||||||
not(feature = "spin")
|
|
||||||
))]
|
|
||||||
{
|
|
||||||
leptos::logging::warn!("If you're using use_cookie without the feature `axum`, `actix` or `spin` enabled, you should provide the option `ssr_cookies_header_getter`");
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(any(feature = "axum", feature = "actix"))]
|
|
||||||
{
|
|
||||||
headers.map(|headers| {
|
|
||||||
headers
|
|
||||||
.get(COOKIE)
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or_else(|| HeaderValue::from_static(""))
|
|
||||||
.to_str()
|
|
||||||
.unwrap_or_default()
|
|
||||||
.to_owned()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
#[cfg(feature = "spin")]
|
|
||||||
{
|
|
||||||
headers.and_then(|headers| {
|
|
||||||
headers
|
|
||||||
.iter()
|
|
||||||
.find(|(key, _)| **key == COOKIE)
|
|
||||||
.and_then(|(_, value)| String::from_utf8(value.to_vec()).ok())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "ssr"))]
|
|
||||||
None
|
|
||||||
}),
|
}),
|
||||||
ssr_set_cookie: Rc::new(|cookie: &Cookie| {
|
ssr_set_cookie: Rc::new(|cookie: &Cookie| {
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
|
|
|
@ -45,7 +45,7 @@ cfg_if! { if #[cfg(not(feature = "ssr"))] {
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// - [`use_resize_observer`]
|
/// - [`fn@crate::use_resize_observer`]
|
||||||
pub fn use_element_size<El, T>(target: El) -> UseElementSizeReturn
|
pub fn use_element_size<El, T>(target: El) -> UseElementSizeReturn
|
||||||
where
|
where
|
||||||
El: Into<ElementMaybeSignal<T, web_sys::Element>> + Clone,
|
El: Into<ElementMaybeSignal<T, web_sys::Element>> + Clone,
|
||||||
|
|
|
@ -40,7 +40,7 @@ use crate::{use_intersection_observer_with_options, UseIntersectionObserverOptio
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// * [`use_intersection_observer`]
|
/// * [`fn@crate::use_intersection_observer`]
|
||||||
pub fn use_element_visibility<El, T>(target: El) -> Signal<bool>
|
pub fn use_element_visibility<El, T>(target: El) -> Signal<bool>
|
||||||
where
|
where
|
||||||
El: Into<ElementMaybeSignal<T, web_sys::Element>>,
|
El: Into<ElementMaybeSignal<T, web_sys::Element>>,
|
||||||
|
|
|
@ -19,11 +19,10 @@ use thiserror::Error;
|
||||||
/// ## Usage
|
/// ## Usage
|
||||||
///
|
///
|
||||||
/// Values are decoded via the given decoder. You can use any of the string codecs or a
|
/// Values are decoded via the given decoder. You can use any of the string codecs or a
|
||||||
/// binary codec wrapped in [`Base64`].
|
/// binary codec wrapped in `Base64`.
|
||||||
///
|
///
|
||||||
/// > Please check [the codec chapter](https://leptos-use.rs/codecs.html) to see what codecs are
|
/// > Please check [the codec chapter](https://leptos-use.rs/codecs.html) to see what codecs are
|
||||||
/// available and what feature flags they require.
|
/// > available and what feature flags they require.
|
||||||
///
|
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
|
@ -47,10 +46,6 @@ use thiserror::Error;
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// ### Create Your Own Custom Codec
|
|
||||||
///
|
|
||||||
/// All you need to do is to implement the [`StringCodec`] trait together with `Default` and `Clone`.
|
|
||||||
///
|
|
||||||
/// ### Named Events
|
/// ### Named Events
|
||||||
///
|
///
|
||||||
/// You can define named events when using `use_event_source_with_options`.
|
/// You can define named events when using `use_event_source_with_options`.
|
||||||
|
|
|
@ -52,7 +52,7 @@ cfg_if! { if #[cfg(not(feature = "ssr"))] {
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// * [`use_element_visibility`]
|
/// * [`fn@crate::use_element_visibility`]
|
||||||
pub fn use_intersection_observer<El, T, F>(
|
pub fn use_intersection_observer<El, T, F>(
|
||||||
target: El,
|
target: El,
|
||||||
callback: F,
|
callback: F,
|
||||||
|
|
|
@ -484,7 +484,7 @@ pub struct UseIntlNumberFormatOptions {
|
||||||
|
|
||||||
/// The currency to use in currency formatting.
|
/// The currency to use in currency formatting.
|
||||||
/// Possible values are the ISO 4217 currency codes, such as "USD" for the US dollar, "EUR" for the euro,
|
/// Possible values are the ISO 4217 currency codes, such as "USD" for the US dollar, "EUR" for the euro,
|
||||||
/// or "CNY" for the Chinese RMB — see the [Current currency & funds code list](https://www.six-group.com/en/products-services/financial-information/data-standards.html#scrollTo=currency-codes.
|
/// or "CNY" for the Chinese RMB — see the [Current currency & funds code list](https://www.six-group.com/en/products-services/financial-information/data-standards.html#scrollTo=currency-codes).
|
||||||
/// There is no default value; if the style is `Currency`, the currency property must be provided.
|
/// There is no default value; if the style is `Currency`, the currency property must be provided.
|
||||||
#[builder(into)]
|
#[builder(into)]
|
||||||
currency: Option<String>,
|
currency: Option<String>,
|
||||||
|
|
77
src/use_locale.rs
Normal file
77
src/use_locale.rs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
use crate::{use_locales_with_options, UseLocalesOptions};
|
||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
/// Reactive locale matching.
|
||||||
|
///
|
||||||
|
/// Returns the first matching locale given by [`fn@crate::use_locales`] that is also found in
|
||||||
|
/// the `supported` list. In case there is no match, then the first locale in `supported` will be
|
||||||
|
/// returned. If `supported` is empty, the empty string is returned.
|
||||||
|
///
|
||||||
|
/// Matching is done by checking if an accepted locale from `use_locales` starts with a supported
|
||||||
|
/// locale. If a match is found the locale from the `supported` list is returned.
|
||||||
|
///
|
||||||
|
/// ## Demo
|
||||||
|
///
|
||||||
|
/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_locale)
|
||||||
|
///
|
||||||
|
/// ## Usage
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use leptos::*;
|
||||||
|
/// # use leptos_use::use_locale;
|
||||||
|
/// #
|
||||||
|
/// # #[component]
|
||||||
|
/// # fn Demo() -> impl IntoView {
|
||||||
|
/// let locale = use_locale(["en", "de", "fr"]);
|
||||||
|
/// #
|
||||||
|
/// # view! { }
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Server-Side Rendering
|
||||||
|
///
|
||||||
|
/// See [`fn@crate::use_locales`]
|
||||||
|
pub fn use_locale<S>(supported: S) -> Signal<String>
|
||||||
|
where
|
||||||
|
S: IntoIterator,
|
||||||
|
S::Item: Into<String> + Clone + 'static,
|
||||||
|
{
|
||||||
|
use_locale_with_options(supported, UseLocaleOptions::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Version of [`fn@crate::use_locale`] that takes a `UseLocaleOptions`. See [`fn@crate::use_locale`] for how to use.
|
||||||
|
pub fn use_locale_with_options<S>(supported: S, options: UseLocaleOptions) -> Signal<String>
|
||||||
|
where
|
||||||
|
S: IntoIterator,
|
||||||
|
S::Item: Into<String> + Clone + 'static,
|
||||||
|
{
|
||||||
|
let locales = use_locales_with_options(options);
|
||||||
|
|
||||||
|
let supported = supported.into_iter().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
Signal::derive(move || {
|
||||||
|
let supported = supported.clone();
|
||||||
|
|
||||||
|
locales.with(|locales| {
|
||||||
|
let mut first_supported = None;
|
||||||
|
|
||||||
|
for s in supported {
|
||||||
|
let s = s.into();
|
||||||
|
|
||||||
|
if first_supported.is_none() {
|
||||||
|
first_supported = Some(s.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
for locale in locales {
|
||||||
|
if locale.starts_with(&s) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
first_supported.unwrap_or_else(|| "".to_string())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type UseLocaleOptions = UseLocalesOptions;
|
114
src/use_locales.rs
Normal file
114
src/use_locales.rs
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
use crate::utils::get_header;
|
||||||
|
use default_struct_builder::DefaultBuilder;
|
||||||
|
use leptos::*;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
/// Reactive locales.
|
||||||
|
///
|
||||||
|
/// If called on the client-side this function returns the value of
|
||||||
|
/// [`navigator.languages`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/languages)
|
||||||
|
/// and listens for changes to that property.
|
||||||
|
///
|
||||||
|
/// See "Server-Side Rendering" below.
|
||||||
|
///
|
||||||
|
/// ## Demo
|
||||||
|
///
|
||||||
|
/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_locales)
|
||||||
|
///
|
||||||
|
/// ## Usage
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use leptos::*;
|
||||||
|
/// # use leptos_use::use_locales;
|
||||||
|
/// #
|
||||||
|
/// # #[component]
|
||||||
|
/// # fn Demo() -> impl IntoView {
|
||||||
|
/// let locales = use_locales();
|
||||||
|
/// #
|
||||||
|
/// # view! { }
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Server-Side Rendering
|
||||||
|
///
|
||||||
|
/// On the server this returns the parsed value of the `accept-language` header.
|
||||||
|
///
|
||||||
|
/// > If you're using `axum` you have to enable the `"axum"` feature in your Cargo.toml.
|
||||||
|
/// > In case it's `actix-web` enable the feature `"actix"`, for `spin` enable `"spin"`.
|
||||||
|
///
|
||||||
|
/// ### Bring your own header
|
||||||
|
///
|
||||||
|
/// In case you're neither using Axum, Actix nor Spin, or the default implementation is not to your liking,
|
||||||
|
/// you can provide your own way of reading and writing the cookie header value using the option
|
||||||
|
/// [`crate::UseLocalesOptions::ssr_lang_header_getter`].
|
||||||
|
pub fn use_locales() -> Signal<Vec<String>> {
|
||||||
|
use_locales_with_options(UseLocalesOptions::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Version of [`fn@crate::use_locales`] that takes a `UseLocalesOptions`. See [`fn@crate::use_locales`] for how to use.
|
||||||
|
pub fn use_locales_with_options(options: UseLocalesOptions) -> Signal<Vec<String>> {
|
||||||
|
#[cfg(not(feature = "ssr"))]
|
||||||
|
{
|
||||||
|
let _ = options;
|
||||||
|
|
||||||
|
let read_navigator_languages = || {
|
||||||
|
let window = crate::use_window();
|
||||||
|
let navigator = window.navigator();
|
||||||
|
navigator
|
||||||
|
.map(|navigator| navigator.languages().to_vec())
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|x| x.as_string())
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
};
|
||||||
|
|
||||||
|
let (locales, set_locales) = create_signal(read_navigator_languages());
|
||||||
|
|
||||||
|
let _ = crate::use_event_listener(crate::use_window(), ev::languagechange, move |_| {
|
||||||
|
set_locales.update(|locales| *locales = read_navigator_languages());
|
||||||
|
});
|
||||||
|
|
||||||
|
locales.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
{
|
||||||
|
let UseLocalesOptions {
|
||||||
|
ssr_lang_header_getter,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
let accept_language = ssr_lang_header_getter().unwrap_or_default();
|
||||||
|
|
||||||
|
let locales = accept_language
|
||||||
|
.split(',')
|
||||||
|
.map(|locale| {
|
||||||
|
locale
|
||||||
|
.split_once(';')
|
||||||
|
.map(|x| x.0)
|
||||||
|
.unwrap_or(locale)
|
||||||
|
.to_owned()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
Signal::derive(move || locales.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Options for [`fn@crate::use_locales_with_options`].
|
||||||
|
#[derive(DefaultBuilder)]
|
||||||
|
pub struct UseLocalesOptions {
|
||||||
|
/// Getter function to return the string value of the accept languange header.
|
||||||
|
/// When you use one of the features `"axum"`, `"actix"` or `"spin"` there's a valid default implementation provided.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
ssr_lang_header_getter: Rc<dyn Fn() -> Option<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for UseLocalesOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
ssr_lang_header_getter: Rc::new(move || {
|
||||||
|
get_header!(ACCEPT_LANGUAGE, use_locale, ssr_lang_header_getter)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,8 +36,8 @@ use std::rc::Rc;
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// * [`use_preferred_dark`]
|
/// * [`fn@crate::use_preferred_dark`]
|
||||||
/// * [`use_preferred_contrast`]
|
/// * [`fn@crate::use_preferred_contrast`]
|
||||||
pub fn use_media_query(query: impl Into<MaybeSignal<String>>) -> Signal<bool> {
|
pub fn use_media_query(query: impl Into<MaybeSignal<String>>) -> Signal<bool> {
|
||||||
let query = query.into();
|
let query = query.into();
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ use std::fmt::Display;
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// * [`use_media_query`]
|
/// * [`fn@crate::use_media_query`]
|
||||||
/// * [`use_preferred_dark`]
|
/// * [`fn@crate::use_preferred_dark`]
|
||||||
pub fn use_preferred_contrast() -> Signal<PreferredContrast> {
|
pub fn use_preferred_contrast() -> Signal<PreferredContrast> {
|
||||||
let is_more = use_media_query("(prefers-contrast: more)");
|
let is_more = use_media_query("(prefers-contrast: more)");
|
||||||
let is_less = use_media_query("(prefers-contrast: less)");
|
let is_less = use_media_query("(prefers-contrast: less)");
|
||||||
|
|
|
@ -24,8 +24,8 @@ use leptos::*;
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// * [`use_media_query`]
|
/// * [`fn@crate::use_media_query`]
|
||||||
/// * [`use_preferred_contrast`]
|
/// * [`fn@crate::use_preferred_contrast`]
|
||||||
pub fn use_preferred_dark() -> Signal<bool> {
|
pub fn use_preferred_dark() -> Signal<bool> {
|
||||||
use_media_query("(prefers-color-scheme: dark)")
|
use_media_query("(prefers-color-scheme: dark)")
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ pub fn use_raf_fn_with_options(
|
||||||
let previous_frame_timestamp = Cell::new(0.0_f64);
|
let previous_frame_timestamp = Cell::new(0.0_f64);
|
||||||
|
|
||||||
move |timestamp: f64| {
|
move |timestamp: f64| {
|
||||||
if !is_active.get_untracked() {
|
if !is_active.try_get_untracked().unwrap_or_default() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +165,6 @@ pub struct UseRafFnCallbackArgs {
|
||||||
/// Time elapsed between this and the last frame.
|
/// Time elapsed between this and the last frame.
|
||||||
pub delta: f64,
|
pub delta: f64,
|
||||||
|
|
||||||
/// Time elapsed since the creation of the web page. See [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#the_time_origin Time origin).
|
/// Time elapsed since the creation of the web page. See [MDN Docs](https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#the_time_origin) Time origin.
|
||||||
pub timestamp: f64,
|
pub timestamp: f64,
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ cfg_if! { if #[cfg(not(feature = "ssr"))] {
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// - [`use_element_size`]
|
/// * [`fn@crate::use_element_size`]
|
||||||
pub fn use_resize_observer<El, T, F>(
|
pub fn use_resize_observer<El, T, F>(
|
||||||
target: El, // TODO : multiple elements?
|
target: El, // TODO : multiple elements?
|
||||||
callback: F,
|
callback: F,
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
use leptos::leptos_dom::helpers::TimeoutHandle;
|
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use std::cell::Cell;
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
/// Wrapper for `setTimeout` with controls.
|
/// Wrapper for `setTimeout` with controls.
|
||||||
///
|
///
|
||||||
|
@ -31,6 +27,11 @@ use std::time::Duration;
|
||||||
/// # view! { }
|
/// # view! { }
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Server-Side Rendering
|
||||||
|
///
|
||||||
|
/// On the server the callback will never be run. The returned functions are all no-ops and
|
||||||
|
/// `is_pending` will always be `false`.
|
||||||
pub fn use_timeout_fn<CbFn, Arg, D>(
|
pub fn use_timeout_fn<CbFn, Arg, D>(
|
||||||
callback: CbFn,
|
callback: CbFn,
|
||||||
delay: D,
|
delay: D,
|
||||||
|
@ -40,65 +41,86 @@ where
|
||||||
Arg: 'static,
|
Arg: 'static,
|
||||||
D: Into<MaybeSignal<f64>>,
|
D: Into<MaybeSignal<f64>>,
|
||||||
{
|
{
|
||||||
let delay = delay.into();
|
|
||||||
|
|
||||||
let (is_pending, set_pending) = create_signal(false);
|
let (is_pending, set_pending) = create_signal(false);
|
||||||
|
|
||||||
let timer = Rc::new(Cell::new(None::<TimeoutHandle>));
|
let start;
|
||||||
|
let stop;
|
||||||
|
|
||||||
let clear = {
|
#[cfg(not(feature = "ssr"))]
|
||||||
let timer = Rc::clone(&timer);
|
{
|
||||||
|
use leptos::leptos_dom::helpers::TimeoutHandle;
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
move || {
|
let delay = delay.into();
|
||||||
if let Some(timer) = timer.take() {
|
|
||||||
timer.clear();
|
let timer = Rc::new(Cell::new(None::<TimeoutHandle>));
|
||||||
|
|
||||||
|
let clear = {
|
||||||
|
let timer = Rc::clone(&timer);
|
||||||
|
|
||||||
|
move || {
|
||||||
|
if let Some(timer) = timer.take() {
|
||||||
|
timer.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
let stop = {
|
stop = {
|
||||||
let clear = clear.clone();
|
let clear = clear.clone();
|
||||||
|
|
||||||
move || {
|
move || {
|
||||||
set_pending.set(false);
|
set_pending.set(false);
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let start = {
|
start = {
|
||||||
let timer = Rc::clone(&timer);
|
let timer = Rc::clone(&timer);
|
||||||
let callback = callback.clone();
|
let callback = callback.clone();
|
||||||
|
|
||||||
move |arg: Arg| {
|
move |arg: Arg| {
|
||||||
set_pending.set(true);
|
set_pending.set(true);
|
||||||
|
|
||||||
let handle = set_timeout_with_handle(
|
let handle = set_timeout_with_handle(
|
||||||
{
|
{
|
||||||
let timer = Rc::clone(&timer);
|
let timer = Rc::clone(&timer);
|
||||||
let callback = callback.clone();
|
let callback = callback.clone();
|
||||||
|
|
||||||
move || {
|
move || {
|
||||||
set_pending.set(false);
|
set_pending.set(false);
|
||||||
timer.set(None);
|
timer.set(None);
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
let prev = SpecialNonReactiveZone::enter();
|
let prev = SpecialNonReactiveZone::enter();
|
||||||
|
|
||||||
callback(arg);
|
callback(arg);
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
SpecialNonReactiveZone::exit(prev);
|
SpecialNonReactiveZone::exit(prev);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Duration::from_millis(delay.get_untracked() as u64),
|
Duration::from_millis(delay.get_untracked() as u64),
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
timer.set(handle);
|
timer.set(handle);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
on_cleanup(clear);
|
on_cleanup(clear);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
{
|
||||||
|
let _ = set_pending;
|
||||||
|
let _ = callback;
|
||||||
|
let _ = delay;
|
||||||
|
|
||||||
|
start = move |_: Arg| ();
|
||||||
|
stop = move || ();
|
||||||
|
}
|
||||||
|
|
||||||
UseTimeoutFnReturn {
|
UseTimeoutFnReturn {
|
||||||
is_pending: is_pending.into(),
|
is_pending: is_pending.into(),
|
||||||
|
|
|
@ -155,10 +155,10 @@ pub struct UseTimestampOptions {
|
||||||
/// Interval type for [`UseTimestampOptions`].
|
/// Interval type for [`UseTimestampOptions`].
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||||
pub enum TimestampInterval {
|
pub enum TimestampInterval {
|
||||||
/// use [`use_raf_fn`] for updating the timestamp
|
/// use [`fn@crate::use_raf_fn`] for updating the timestamp
|
||||||
RequestAnimationFrame,
|
RequestAnimationFrame,
|
||||||
|
|
||||||
/// use [`use_interval_fn`] for updating the timestamp
|
/// use [`fn@crate::use_interval_fn`] for updating the timestamp
|
||||||
Interval(u64),
|
Interval(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ use js_sys::Array;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use web_sys::{BinaryType, CloseEvent, Event, MessageEvent, WebSocket};
|
use web_sys::{BinaryType, CloseEvent, Event, MessageEvent, WebSocket};
|
||||||
|
|
||||||
|
#[allow(rustdoc::bare_urls)]
|
||||||
/// Creating and managing a [Websocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) connection.
|
/// Creating and managing a [Websocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) connection.
|
||||||
///
|
///
|
||||||
/// ## Demo
|
/// ## Demo
|
||||||
|
@ -27,7 +28,7 @@ use web_sys::{BinaryType, CloseEvent, Event, MessageEvent, WebSocket};
|
||||||
/// Values are (en)decoded via the given codec. You can use any of the codecs, string or binary.
|
/// Values are (en)decoded via the given codec. You can use any of the codecs, string or binary.
|
||||||
///
|
///
|
||||||
/// > Please check [the codec chapter](https://leptos-use.rs/codecs.html) to see what codecs are
|
/// > Please check [the codec chapter](https://leptos-use.rs/codecs.html) to see what codecs are
|
||||||
/// available and what feature flags they require.
|
/// > available and what feature flags they require.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
|
@ -247,6 +248,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Version of [`use_websocket`] that takes `UseWebSocketOptions`. See [`use_websocket`] for how to use.
|
/// Version of [`use_websocket`] that takes `UseWebSocketOptions`. See [`use_websocket`] for how to use.
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn use_websocket_with_options<T, C>(
|
pub fn use_websocket_with_options<T, C>(
|
||||||
url: &str,
|
url: &str,
|
||||||
options: UseWebSocketOptions<
|
options: UseWebSocketOptions<
|
||||||
|
|
|
@ -54,7 +54,7 @@ impl UseWindow {
|
||||||
navigator(&self) -> Option<web_sys::Navigator>
|
navigator(&self) -> Option<web_sys::Navigator>
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Returns the same as [`use_document`].
|
/// Returns the same as [`fn@use_document`].
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn document(&self) -> UseDocument {
|
pub fn document(&self) -> UseDocument {
|
||||||
use_document()
|
use_document()
|
||||||
|
|
76
src/utils/header.rs
Normal file
76
src/utils/header.rs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#[cfg(feature = "actix")]
|
||||||
|
use http0_2::HeaderName;
|
||||||
|
#[cfg(any(feature = "axum", feature = "spin"))]
|
||||||
|
use http1::HeaderName;
|
||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
/// Get the value of the header with the given name.
|
||||||
|
///
|
||||||
|
/// This function is only meant to be used on the server.
|
||||||
|
/// So it is only defined when the feature `"ssr"` is enabled together with one of the
|
||||||
|
/// features `"axum"`, `"actix"` or `"spin"`.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// # use leptos_use::utils::header;
|
||||||
|
/// #
|
||||||
|
/// let content_len = header(http::header::CONTENT_LENGTH);
|
||||||
|
/// ```
|
||||||
|
pub fn header<N>(name: N) -> Option<String>
|
||||||
|
where
|
||||||
|
N: Into<HeaderName>,
|
||||||
|
{
|
||||||
|
let name = name.into();
|
||||||
|
|
||||||
|
#[cfg(all(feature = "actix", feature = "axum"))]
|
||||||
|
compile_error!("You can only enable one of features \"actix\" and \"axum\" at the same time");
|
||||||
|
|
||||||
|
#[cfg(all(feature = "actix", feature = "spin"))]
|
||||||
|
compile_error!("You can only enable one of features \"actix\" and \"spin\" at the same time");
|
||||||
|
|
||||||
|
#[cfg(all(feature = "axum", feature = "spin"))]
|
||||||
|
compile_error!("You can only enable one of features \"axum\" and \"spin\" at the same time");
|
||||||
|
|
||||||
|
#[cfg(feature = "actix")]
|
||||||
|
type HeaderValue = http0_2::HeaderValue;
|
||||||
|
#[cfg(feature = "axum")]
|
||||||
|
type HeaderValue = http1::HeaderValue;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "axum", feature = "actix", feature = "spin"))]
|
||||||
|
let headers;
|
||||||
|
#[cfg(feature = "actix")]
|
||||||
|
{
|
||||||
|
headers = use_context::<actix_web::HttpRequest>().map(|req| req.headers().clone());
|
||||||
|
}
|
||||||
|
#[cfg(feature = "axum")]
|
||||||
|
{
|
||||||
|
headers = use_context::<http1::request::Parts>().map(|parts| parts.headers);
|
||||||
|
}
|
||||||
|
#[cfg(feature = "spin")]
|
||||||
|
{
|
||||||
|
headers = use_context::<leptos_spin::RequestParts>().map(|parts| parts.headers().clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "axum", feature = "actix"))]
|
||||||
|
{
|
||||||
|
headers.map(|headers| {
|
||||||
|
headers
|
||||||
|
.get(name)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| HeaderValue::from_static(""))
|
||||||
|
.to_str()
|
||||||
|
.unwrap_or_default()
|
||||||
|
.to_owned()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(feature = "spin")]
|
||||||
|
{
|
||||||
|
headers.and_then(|headers| {
|
||||||
|
headers
|
||||||
|
.iter()
|
||||||
|
.find(|(key, _)| **key == name)
|
||||||
|
.and_then(|(_, value)| String::from_utf8(value.to_vec()).ok())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
36
src/utils/header_macro.rs
Normal file
36
src/utils/header_macro.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
macro_rules! get_header {
|
||||||
|
(
|
||||||
|
$header_name:ident,
|
||||||
|
$function_name:ident,
|
||||||
|
$option_name:ident
|
||||||
|
$(,)?
|
||||||
|
) => {
|
||||||
|
if cfg!(feature = "ssr") {
|
||||||
|
#[cfg(all(
|
||||||
|
not(feature = "axum"),
|
||||||
|
not(feature = "actix"),
|
||||||
|
not(feature = "spin")
|
||||||
|
))]
|
||||||
|
{
|
||||||
|
leptos::logging::warn!(
|
||||||
|
"If you're using `{}` with SSR but without any of the features `axum`, `actix` or `spin` enabled, you have to provide the option `{}`",
|
||||||
|
stringify!($function_name),
|
||||||
|
stringify!($option_name)
|
||||||
|
);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "actix")]
|
||||||
|
const $header_name: http0_2::HeaderName = http0_2::header::$header_name;
|
||||||
|
#[cfg(any(feature = "axum", feature = "spin"))]
|
||||||
|
const $header_name: http1::HeaderName = http1::header::$header_name;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "axum", feature = "actix", feature = "spin"))]
|
||||||
|
crate::utils::header($header_name)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use get_header;
|
|
@ -1,4 +1,10 @@
|
||||||
mod filters;
|
mod filters;
|
||||||
|
#[cfg(all(
|
||||||
|
feature = "ssr",
|
||||||
|
any(feature = "axum", feature = "actix", feature = "spin")
|
||||||
|
))]
|
||||||
|
mod header;
|
||||||
|
mod header_macro;
|
||||||
mod is;
|
mod is;
|
||||||
mod js;
|
mod js;
|
||||||
mod js_value_from_to_string;
|
mod js_value_from_to_string;
|
||||||
|
@ -7,6 +13,12 @@ mod signal_filtered;
|
||||||
mod use_derive_signal;
|
mod use_derive_signal;
|
||||||
|
|
||||||
pub use filters::*;
|
pub use filters::*;
|
||||||
|
#[cfg(all(
|
||||||
|
feature = "ssr",
|
||||||
|
any(feature = "axum", feature = "actix", feature = "spin")
|
||||||
|
))]
|
||||||
|
pub use header::*;
|
||||||
|
pub(crate) use header_macro::*;
|
||||||
pub use is::*;
|
pub use is::*;
|
||||||
pub(crate) use js_value_from_to_string::*;
|
pub(crate) use js_value_from_to_string::*;
|
||||||
pub use pausable::*;
|
pub use pausable::*;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/// Macro to easily create helper functions that derive a signal using a piece of code.
|
/// Macro to easily create helper functions that derive a signal using a piece of code.
|
||||||
///
|
///
|
||||||
/// See [`is_ok`] or [`use_to_string`] as examples.
|
/// See [`fn@crate::is_ok`] or [`fn@crate::use_to_string`] as examples.
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! use_derive_signal {
|
macro_rules! use_derive_signal {
|
||||||
(
|
(
|
||||||
|
|
|
@ -34,7 +34,7 @@ use leptos::*;
|
||||||
///
|
///
|
||||||
/// Please note that if the current component is cleaned up before the debounced callback is called, the debounced callback will not be called.
|
/// Please note that if the current component is cleaned up before the debounced callback is called, the debounced callback will not be called.
|
||||||
///
|
///
|
||||||
/// There's also `watch_debounced_with_options` where you can specify the other watch options (except `filter`).
|
/// There's also [`watch_debounced_with_options`] where you can specify the other watch options (except `filter`).
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
|
@ -70,8 +70,8 @@ use leptos::*;
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// * [`watch`]
|
/// * `leptos::watch`
|
||||||
/// * [`watch_throttled`]
|
/// * [`fn@crate::watch_throttled`]
|
||||||
pub fn watch_debounced<W, T, DFn, CFn>(deps: DFn, callback: CFn, ms: f64) -> impl Fn() + Clone
|
pub fn watch_debounced<W, T, DFn, CFn>(deps: DFn, callback: CFn, ms: f64) -> impl Fn() + Clone
|
||||||
where
|
where
|
||||||
DFn: Fn() -> W + 'static,
|
DFn: Fn() -> W + 'static,
|
||||||
|
@ -82,7 +82,8 @@ where
|
||||||
watch_with_options(deps, callback, WatchOptions::default().debounce(ms))
|
watch_with_options(deps, callback, WatchOptions::default().debounce(ms))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Version of `watch_debounced` that accepts `WatchDebouncedOptions`. See [`watch_debounced`] for how to use.
|
/// Version of `watch_debounced` that accepts `WatchDebouncedOptions`.
|
||||||
|
/// See [`watch_debounced`] for how to use.
|
||||||
pub fn watch_debounced_with_options<W, T, DFn, CFn>(
|
pub fn watch_debounced_with_options<W, T, DFn, CFn>(
|
||||||
deps: DFn,
|
deps: DFn,
|
||||||
callback: CFn,
|
callback: CFn,
|
||||||
|
|
|
@ -52,7 +52,7 @@ use leptos::*;
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// * [`watch`]
|
/// * `leptos::watch`
|
||||||
pub fn watch_pausable<W, T, DFn, CFn>(
|
pub fn watch_pausable<W, T, DFn, CFn>(
|
||||||
deps: DFn,
|
deps: DFn,
|
||||||
callback: CFn,
|
callback: CFn,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{watch_with_options, ThrottleOptions, WatchOptions};
|
use crate::{watch_with_options, ThrottleOptions, WatchOptions};
|
||||||
use default_struct_builder::DefaultBuilder;
|
use default_struct_builder::DefaultBuilder;
|
||||||
|
|
||||||
/// A throttled version of [`watch`].
|
/// A throttled version of `leptos::watch`.
|
||||||
///
|
///
|
||||||
/// ## Demo
|
/// ## Demo
|
||||||
///
|
///
|
||||||
|
@ -69,8 +69,8 @@ use default_struct_builder::DefaultBuilder;
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// * [`watch`]
|
/// * `leptos::watch`
|
||||||
/// * [`watch_debounced`]
|
/// * [`fn@crate::watch_debounced`]
|
||||||
pub fn watch_throttled<W, T, DFn, CFn>(deps: DFn, callback: CFn, ms: f64) -> impl Fn() + Clone
|
pub fn watch_throttled<W, T, DFn, CFn>(deps: DFn, callback: CFn, ms: f64) -> impl Fn() + Clone
|
||||||
where
|
where
|
||||||
DFn: Fn() -> W + 'static,
|
DFn: Fn() -> W + 'static,
|
||||||
|
@ -81,7 +81,7 @@ where
|
||||||
watch_with_options(deps, callback, WatchOptions::default().throttle(ms))
|
watch_with_options(deps, callback, WatchOptions::default().throttle(ms))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Version of `watch_throttled` that accepts `WatchThrottledOptions`. See [`watch_throttled`] for how to use.
|
/// Version of [`fn@watch_throttled`] that accepts `WatchThrottledOptions`. See [`watch_throttled`] for how to use.
|
||||||
pub fn watch_throttled_with_options<W, T, DFn, CFn>(
|
pub fn watch_throttled_with_options<W, T, DFn, CFn>(
|
||||||
deps: DFn,
|
deps: DFn,
|
||||||
callback: CFn,
|
callback: CFn,
|
||||||
|
|
|
@ -38,7 +38,8 @@ use std::rc::Rc;
|
||||||
///
|
///
|
||||||
/// ## Filters
|
/// ## Filters
|
||||||
///
|
///
|
||||||
/// The callback can be throttled or debounced. Please see [`watch_throttled`] and [`watch_debounced`] for details.
|
/// The callback can be throttled or debounced. Please see [`fn@crate::watch_throttled`]
|
||||||
|
/// and [`fn@crate::watch_debounced`] for details.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
|
@ -86,10 +87,8 @@ use std::rc::Rc;
|
||||||
///
|
///
|
||||||
/// ## See also
|
/// ## See also
|
||||||
///
|
///
|
||||||
/// * [`watch_throttled`]
|
/// * [`fn@crate::watch_throttled`]
|
||||||
/// * [`watch_debounced`]
|
/// * [`fn@crate::watch_debounced`]
|
||||||
|
|
||||||
/// Version of `watch` that accepts `WatchOptions`. See [`watch`] for how to use.
|
|
||||||
pub fn watch_with_options<W, T, DFn, CFn>(
|
pub fn watch_with_options<W, T, DFn, CFn>(
|
||||||
deps: DFn,
|
deps: DFn,
|
||||||
callback: CFn,
|
callback: CFn,
|
||||||
|
|
|
@ -20,7 +20,7 @@ use crate::{watch_with_options, WatchOptions};
|
||||||
///
|
///
|
||||||
/// ### Callback Function
|
/// ### Callback Function
|
||||||
///
|
///
|
||||||
/// Same as [`watch`], the callback will be called with `callback(input, prev_input, prev_return)`.
|
/// Same as [`fn@crate::watch`], the callback will be called with `callback(input, prev_input, prev_return)`.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
|
@ -39,7 +39,7 @@ use crate::{watch_with_options, WatchOptions};
|
||||||
///
|
///
|
||||||
/// ### Computed
|
/// ### Computed
|
||||||
///
|
///
|
||||||
/// Same as [`watch`], you can pass a getter function to calculate on each change.
|
/// Same as [`fn@crate::watch`], you can pass a getter function to calculate on each change.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
|
@ -59,7 +59,7 @@ use crate::{watch_with_options, WatchOptions};
|
||||||
///
|
///
|
||||||
/// ### Options
|
/// ### Options
|
||||||
///
|
///
|
||||||
/// Options and defaults are same as [`watch_with_options`].
|
/// Options and defaults are same as [`fn@watch_with_options`].
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
|
|
|
@ -22,19 +22,23 @@ use leptos::*;
|
||||||
/// #
|
/// #
|
||||||
/// # view! { }
|
/// # view! { }
|
||||||
/// # }
|
/// # }
|
||||||
/// ```{{#if feature}}
|
/// ```
|
||||||
|
///
|
||||||
|
/// ## Server-Side Rendering
|
||||||
|
/// {{#if feature}}
|
||||||
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
||||||
|
|
||||||
pub fn {{ function_name }}() -> {{ to_pascal_case function_name }}Return {
|
pub fn {{ function_name }}() -> {{ to_pascal_case function_name }}Return {
|
||||||
{{ function_name }}_with_options({{ to_pascal_case function_name }}Options::default())
|
{{ function_name }}_with_options({{ to_pascal_case function_name }}Options::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Version of [`{{ function_name }}`] that takes a `{{ to_pascal_case function_name }}Options`. See [`{{ function_name }}`] for how to use.{{#if feature}}
|
/// Version of [`fn@crate::{{ function_name }}`] that takes a `{{ to_pascal_case function_name }}Options`. See [`fn@crate::{{ function_name }}`] for how to use.{{#if feature}}
|
||||||
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
||||||
pub fn {{ function_name }}_with_options(options: {{ to_pascal_case function_name }}Options) -> {{ to_pascal_case function_name }}Return {
|
pub fn {{ function_name }}_with_options(options: {{ to_pascal_case function_name }}Options) -> {{ to_pascal_case function_name }}Return {
|
||||||
{{ to_pascal_case function_name }}Return {}
|
{{ to_pascal_case function_name }}Return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Options for [`{{ function_name }}_with_options`].{{#if feature}}
|
/// Options for [`fn@crate::{{ function_name }}_with_options`].{{#if feature}}
|
||||||
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
||||||
#[derive(DefaultBuilder)]
|
#[derive(DefaultBuilder)]
|
||||||
pub struct {{ to_pascal_case function_name }}Options {}
|
pub struct {{ to_pascal_case function_name }}Options {}
|
||||||
|
@ -45,6 +49,6 @@ impl Default for {{ to_pascal_case function_name }}Options {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return type of [`{{ function_name }}`].{{#if feature}}
|
/// Return type of [`fn@crate::{{ function_name }}`].{{#if feature}}
|
||||||
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
||||||
pub struct {{ to_pascal_case function_name }}Return {}
|
pub struct {{ to_pascal_case function_name }}Return {}
|
Loading…
Add table
Reference in a new issue