diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index e2c8ca1..8187b1c 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,6 +1,6 @@
# These are supported funding model platforms
-github: [Synphonyte]# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+github: [Synphonyte] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d06c55f..95f75d3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -30,13 +30,13 @@ jobs:
- name: Check formatting
run: cargo fmt --check
- name: Clippy
- run: cargo clippy --features prost,serde,docs,math --tests -- -D warnings
+ run: cargo clippy --features docs,math --tests -- -D warnings
- name: Run tests (general)
- run: cargo test --features math,docs,ssr,prost,serde
+ run: cargo test --features math,docs,ssr
- name: Run tests (axum)
- run: cargo test --features math,docs,ssr,prost,serde,axum --doc use_cookie::use_cookie
+ run: cargo test --features math,docs,ssr,axum --doc use_cookie::use_cookie
- name: Run tests (actix)
- run: cargo test --features math,docs,ssr,prost,serde,actix --doc use_cookie::use_cookie
+ run: cargo test --features math,docs,ssr,actix --doc use_cookie::use_cookie
#### mdbook
- name: Install mdbook I
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index d43d0b4..68ee5cf 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -23,10 +23,10 @@ jobs:
- name: Check formatting
run: cargo fmt --check
- name: Clippy
- run: cargo clippy --features prost,serde,docs,math --tests -- -D warnings
+ run: cargo clippy --features docs,math --tests -- -D warnings
- name: Run tests (general)
- run: cargo test --features math,docs,ssr,prost,serde
+ run: cargo test --features math,docs,ssr
- name: Run tests (axum)
- run: cargo test --features math,docs,ssr,prost,serde,axum --doc use_cookie::use_cookie
+ run: cargo test --features math,docs,ssr,axum --doc use_cookie::use_cookie
- name: Run tests (actix)
- run: cargo test --features math,docs,ssr,prost,serde,actix --doc use_cookie::use_cookie
+ run: cargo test --features math,docs,ssr,actix --doc use_cookie::use_cookie
diff --git a/.idea/leptos-use.iml b/.idea/leptos-use.iml
index 66b8cda..7d56fcb 100644
--- a/.idea/leptos-use.iml
+++ b/.idea/leptos-use.iml
@@ -76,6 +76,7 @@
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e2f8130..f0ab304 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,80 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Updated to Leptos 0.7
+## [Unreleased]
+
+### New Functions 🚀
+
+- `use_user_media`
+
+### New Features 🚀
+
+- Codecs:
+ - All codecs now live in their own crate `codee`
+ - There are now binary codecs in addition to string codecs.
+ - `FromToBytesCodec`
+ - `WebpackSerdeCodec`
+ - `BincodeSerdeCodec`
+ - `ProstCodec` (see also the section "Breaking Changes 🛠" below)
+ - Every binary codec can be used as a string codec with the `Base64` wrapper which encodes the binary data as a
+ base64
+ string.
+ - This required feature `base64`
+ - It can be wrapped for example like this: `Base64`.
+ - There is now an `OptionCodec` wrapper that allows to wrap any string codec that encodes `T` to encode `Option`.
+ - Use it like this: `OptionCodec>`.
+
+- `ElementMaybeSignal` is now implemented for `websys::HtmlElement` (thanks to @blorbb).
+- `UseStorageOptions` now has `delay_during_hydration` which has to be used when you conditionally show parts of
+ the DOM controlled by a value from storage. This leads to hydration errors which can be fixed by setting this new
+ option to `true`.
+- `cookie::SameSite` is now re-exported
+- Changing the signal returned by `use_cookie` now tries and changes the headers during SSR.
+- New book chapter about codecs
+- The macro `use_derive_signal!` is now exported (thanks to @mscofield0).
+
+### Breaking Changes 🛠
+
+- `UseStorageOptions` and `UseEventSourceOptions` no longer accept a `codec` value because this is already provided as a
+ generic parameter to the respective function calls.
+- Codecs have been refactored. There are now two traits that codecs implement: `Encoder` and `Decoder`. The
+ trait `StringCodec` is gone. The methods are now associated methods and their params now always take references.
+ - `JsonCodec` has been renamed to `JsonSerdeCodec`.
+ - 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
+ this: `Base64`. You have to enable both features `prost` and `base64` for this.
+ - All of these structs, traits and features now live in their own crate called `codee`
+- `use_websocket`:
+ - `UseWebsocketOptions` has been renamed to `UseWebSocketOptions` (uppercase S) to be consistent with the return
+ type.
+ - `UseWebSocketOptions::reconnect_limit` and `UseEventSourceOptions::reconnect_limit` is now `ReconnectLimit`
+ instead
+ of `u64`. Use `ReconnectLimit::Infinite` for infinite retries or `ReconnectLimit::Limited(...)` for limited
+ retries.
+ - `use_websocket` now uses codecs to send typed messages over the network.
+ - When calling you have give type parameters for the message type and the
+ codec: `use_websocket::`
+ - You can use binary or string codecs.
+ - The `UseWebSocketReturn::send` closure now takes a `&T` which is encoded using the codec.
+ - The `UseWebSocketReturn::message` signal now returns an `Option` which is decoded using the codec.
+ - `UseWebSocketReturn::send_bytes` and `UseWebSocketReturn::message_bytes` are gone.
+ - `UseWebSocketOptions::on_message` and `UseWebSocketOptions::on_message_bytes` have been renamed
+ to `on_message_raw` and `on_message_raw_bytes`.
+ - The new `UseWebSocketOptions::on_message` takes a `&T`.
+ - `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.
+
+### Fixes 🍕
+
+- Fixed auto-reconnect in `use_websocket`
+- Fixed typo in compiler error messages in `use_cookie` (thanks to @SleeplessOne1917).
+
+## [0.10.10] - 2024-05-10
+
+### Change 🔥
+
+- Added compile-time warning when you use `ssr` feature with `wasm32`. You can enable `wasm_ssr` to remove the warning.
+
## [0.10.9] - 2024-04-27
### Fixes 🍕
@@ -117,7 +191,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- You can now convert `leptos::html::HtmlElement` into `Element(s)MaybeSignal`. This should make functions a lot
easier to use in directives.
- There's now a chapter in the book especially for `Element(s)MaybeSignal`.
-- Throttled or debounced callbacks (in watch_* or *_fn) no longer are called after the containing scope was cleaned up.
+- Throttled or debounced callbacks (in watch\__ or _\_fn) no longer are called after the containing scope was cleaned
+ up.
- The document returned from `use_document` now supports the methods `query_selector` and `query_selector_all`.
## [0.9.0] - 2023-12-06
@@ -147,7 +222,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `use_scroll` now uses `try_get_untracked` in the debounced callback to avoid panics if the context has been destroyed
while the callback was waiting to be called.
- `use_idle` works properly now (no more idles too early).
-- `use_web_notification` doesn't panic on the server anymore.
+- `use_web_notification` doesn't panic on the server anymore.
## [0.8.2] - 2023-11-09
@@ -221,7 +296,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- takes now a `&str` instead of a `String` as its `url` parameter.
- same for the returned `send` method.
- The `ready_state` return type is now renamed to `ConnectionReadyState` instead of `UseWebSocketReadyState`.
- - The returned signals `ready_state`, `message`, `message_bytes` have now the type
+ - The returned signals `ready_state`, `message`, `message_bytes` have now the type
`Signal<...>` instead of `ReadSignal<...>` to make them more consistent with other functions.
- The options `reconnect_limit` and `reconnect_interval` now take a `u64` instead of `Option` to improve DX.
- The option `manual` has been renamed to `immediate` to make it more consistent with other functions.
@@ -469,4 +544,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Other Changes
-- Better and more beautiful demo integration into the guide.
\ No newline at end of file
+- Better and more beautiful demo integration into the guide.
diff --git a/Cargo.toml b/Cargo.toml
index 179e113..810b7a0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "leptos-use"
-version = "0.10.9"
+version = "0.10.10"
edition = "2021"
authors = ["Marc-Stefan Cassola"]
categories = ["gui", "web-programming"]
@@ -15,8 +15,8 @@ homepage = "https://leptos-use.rs"
[dependencies]
actix-web = { version = "4", optional = true, default-features = false }
async-trait = "0.1"
-base64 = { version = "0.21", optional = true }
cfg-if = "1"
+codee = "0.1"
cookie = { version = "0.18", features = ["percent-encode"] }
default-struct-builder = "0.5"
futures-util = "0.3"
@@ -32,11 +32,7 @@ leptos_actix = { version = "0.6", optional = true }
leptos-spin = { version = "0.2", optional = true }
num = { version = "0.4", optional = true }
paste = "1"
-prost = { version = "0.12", optional = true }
-rmp-serde = { version = "1.1", optional = true }
send_wrapper = "0.6.0"
-serde = { version = "1", optional = true }
-serde_json = { version = "1", optional = true }
thiserror = "1"
wasm-bindgen = "0.2.92"
wasm-bindgen-futures = "0.4"
@@ -78,6 +74,7 @@ features = [
"MediaDevices",
"MediaQueryList",
"MediaStream",
+ "MediaStreamConstraints",
"MediaStreamTrack",
"MessageEvent",
"MouseEvent",
@@ -136,17 +133,19 @@ features = [
getrandom = { version = "0.2", features = ["js"] }
leptos_meta = "0.7.0-alpha"
rand = "0.8"
+codee = { version = "0.1", features = ["json_serde", "msgpack_serde", "base64", "prost"] }
+serde = { version = "1", features = ["derive"] }
[features]
actix = ["dep:actix-web", "dep:leptos_actix", "dep:http0_2"]
axum = ["dep:leptos_axum", "dep:http1"]
docs = []
math = ["num"]
-prost = ["base64", "dep:prost"]
-serde = ["dep:serde", "serde_json"]
spin = ["dep:leptos-spin", "dep:http1"]
ssr = []
-msgpack = ["dep:rmp-serde", "dep:serde"]
+wasm_ssr = []
[package.metadata.docs.rs]
-features = ["math", "docs", "ssr", "prost", "serde"]
+features = ["math", "docs", "ssr"]
+rustdoc-args = ["--cfg=web_sys_unstable_apis"]
+rustc-args = ["--cfg=web_sys_unstable_apis"]
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..7ef2a97
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,17 @@
+use std::env;
+
+fn main() {
+ let ssr = env::var("CARGO_FEATURE_SSR").is_ok();
+ let wasm_ssr = env::var("CARGO_FEATURE_WASM_SSR").is_ok();
+ let wasm32 = env::var("CARGO_CFG_TARGET_ARCH").expect("should be present in the build script")
+ == "wasm32";
+ if ssr && wasm32 && !wasm_ssr {
+ println!(
+ "cargo::warning=You have enabled the `ssr` feature for a wasm32 target. \
+This is probably not what you want. Please check https://leptos-use.rs/server_side_rendering.html \
+for how to use the `ssr` feature correctly.\n \
+If you're building for wasm32 on the server you can enable the `wasm_ssr` feature to get rid of \
+this warning."
+ );
+ }
+}
diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md
index 51ca13f..502a1a6 100644
--- a/docs/book/src/SUMMARY.md
+++ b/docs/book/src/SUMMARY.md
@@ -2,8 +2,10 @@
[Introduction](introduction.md)
[Get Started](get_started.md)
+[Options](options.md)
[Element Parameters](element_parameters.md)
[Server-Side Rendering](server_side_rendering.md)
+[Encoding and Decoding Data](codecs.md)
[Changelog](changelog.md)
[Functions](functions.md)
@@ -47,6 +49,7 @@
- [use_preferred_contrast](browser/use_preferred_contrast.md)
- [use_preferred_dark](browser/use_preferred_dark.md)
- [use_service_worker](browser/use_service_worker.md)
+- [use_user_media](browser/use_user_media.md)
- [use_web_notification](browser/use_web_notification.md)
# Sensors
@@ -65,6 +68,7 @@
- [use_event_source](network/use_event_source.md)
- [use_websocket](network/use_websocket.md)
+
# Animation
@@ -94,12 +98,14 @@
- [use_sorted](iterable/use_sorted.md)
# Utilities
+
- [is_err](utilities/is_err.md)
- [is_none](utilities/is_none.md)
- [is_ok](utilities/is_ok.md)
- [is_some](utilities/is_some.md)
- [use_cycle_list](utilities/use_cycle_list.md)
- [use_debounce_fn](utilities/use_debounce_fn.md)
+- [use_derive_signal!](utilities/use_derive_signal.md)
- [use_supported](utilities/use_supported.md)
- [use_throttle_fn](utilities/use_throttle_fn.md)
- [use_to_string](utilities/use_to_string.md)
diff --git a/docs/book/src/browser/use_user_media.md b/docs/book/src/browser/use_user_media.md
new file mode 100644
index 0000000..3e39cca
--- /dev/null
+++ b/docs/book/src/browser/use_user_media.md
@@ -0,0 +1,3 @@
+# use_user_media
+
+
diff --git a/docs/book/src/codecs.md b/docs/book/src/codecs.md
new file mode 100644
index 0000000..2e54fa2
--- /dev/null
+++ b/docs/book/src/codecs.md
@@ -0,0 +1,156 @@
+# Encoding and Decoding Data
+
+Several functions encode and decode data for storing it and/or sending it over the network. To do this, codecs
+located at [`src/utils/codecs`](https://github.com/Synphonyte/leptos-use/tree/main/src/utils/codecs) are used. They
+implement the traits [`Encoder`](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/mod.rs#L9) with the
+method `encode` and [`Decoder`](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/mod.rs#L17) with the
+method `decode`.
+
+There are two types of codecs: One that encodes as binary data (`Vec[u8]`) and another type that encodes as
+strings (`String`). There is also an adapter
+[`Base64`](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/string/base64.rs) that can be used to
+wrap a binary codec and make it a string codec by representing the binary data as a base64 string.
+
+## Available Codecs
+
+### String Codecs
+
+- [**`FromToStringCodec`
+ **](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/string/from_to_string.rs)
+- [**`JsonSerdeCodec`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/string/json_serde.rs)**
+
+### Binary Codecs
+
+- [**`FromToBytesCodec`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/binary/from_to_bytes.rs)
+- [**`BincodeSerdeCodec`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/binary/bincode_serde.rs)
+- [**`MsgpackSerdeCodec`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/binary/msgpack_serde.rs)
+
+### Adapters
+
+- [**`Base64`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/string/base64.rs) —
+ Wraps a binary codec and make it a string codec by representing the binary data as a base64 string.
+- [**`OptionCodec`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/option.rs) —
+ Wraps a string codec that encodes `T` to create a codec that encodes `Option`.
+
+## Example
+
+In this example, a codec is given to [`use_cookie`](browser/use_cookie.md) that stores data as a string in the JSON
+format. Since cookies can only store strings, we have to use string codecs here.
+
+```rust,noplayground
+# use leptos::*;
+# use leptos_use::use_cookie;
+# use serde::{Deserialize, Serialize};
+
+# #[component]
+# pub fn App(cx: Scope) -> impl IntoView {
+#[derive(Serialize, Deserialize, Clone)]
+struct MyState {
+ chicken_count: i32,
+ egg_count: i32,
+}
+
+let (cookie, set_cookie) = use_cookie::("my-state-cookie");
+# view! {}
+# }
+```
+
+## Custom Codecs
+
+If you don't find a suitable codecs for your needs, you can implement your own; it's straightforward! If you want to
+create a string codec, you can look
+at [`JsonSerdeCodec`](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/string/json_serde.rs).
+In case it's a binary codec, have a look
+at [`BincodeSerdeCodec`](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/binary/bincode_serde.rs).
+
+## Versioning
+
+Versioning is the process of handling long-term data that can outlive our code.
+
+For example, we could have a settings struct whose members change over time. We might eventually
+add timezone support, and we might then remove support for a thousands separator for numbers.
+Each change results in a new possible version of the stored data. If we stored these settings
+in browser storage, we would need to handle all possible versions of the data format that can
+occur. If we don't offer versioning, then all settings could revert to the default every time we
+encounter an old format.
+
+How best to handle versioning depends on the codec involved:
+
+- The `FromToStringCodec` can avoid versioning entirely by keeping
+ to primitive types. In our example above, we could have decomposed the settings struct into
+ separate timezone and number separator fields. These would be encoded as strings and stored as
+ two separate key-value fields in the browser rather than a single field. If a field is missing,
+ then the value intentionally would fall back to the default without interfering with the other
+ field.
+
+- The `ProstCodec` uses [Protocol buffers](https://protobuf.dev/overview/)
+ designed to solve the problem of long-term storage. It provides semantics for versioning that
+ are not present in JSON or other formats.
+
+- The codecs that use serde under the hood can rely on serde or by
+ providing their own manual version handling. See the next sections for more details.
+
+### Rely on `serde`
+
+A simple way to avoid complex versioning is to rely on serde's [field attributes](https://serde.rs/field-attrs.html)
+such as [`serde(default)`](https://serde.rs/field-attrs.html#default)
+and [`serde(rename = "...")`](https://serde.rs/field-attrs.html#rename).
+
+### Manual Version Handling
+
+We look at the example of the `JsonSerdeCodec` in this section.
+
+To implement version handling, we parse the JSON generically then transform the
+resulting `JsValue` before decoding it into our struct again.
+
+Let's look at an example.
+
+ ```rust,noplayground
+ # use leptos::*;
+ # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions};
+ # use serde::{Deserialize, Serialize};
+ # use serde_json::json;
+ # use leptos_use::utils::{Encoder, Decoder};
+ #
+ # pub fn Demo() -> impl IntoView {
+ #[derive(Serialize, Deserialize, Clone, Default, PartialEq)]
+ pub struct MyState {
+ pub hello: String,
+ // This field was added in a later version
+ pub greeting: String,
+ }
+
+ pub struct MyStateCodec;
+
+ impl Encoder for MyStateCodec {
+ type Error = serde_json::Error;
+ type Encoded = String;
+
+ fn encode(val: &MyState) -> Result {
+ serde_json::to_string(val)
+ }
+ }
+
+ impl Decoder for MyStateCodec {
+ type Error = serde_json::Error;
+ type Encoded = str;
+
+ fn decode(stored_value: &Self::Encoded) -> Result {
+ let mut val: serde_json::Value = serde_json::from_str(stored_value)?;
+ // add "greeting": "Hello" to the object if it's missing
+ if let Some(obj) = val.as_object_mut() {
+ if !obj.contains_key("greeting") {
+ obj.insert("greeting".to_string(), json!("Hello"));
+ }
+ serde_json::from_value(val)
+ } else {
+ Ok(MyState::default())
+ }
+ }
+ }
+
+ // Then use it like the following just as any other codec.
+ let (get, set, remove) = use_local_storage::("my-struct-key");
+ # view! { }
+ # }
+ ```
diff --git a/docs/book/src/demo.css b/docs/book/src/demo.css
index 809ee87..f092756 100644
--- a/docs/book/src/demo.css
+++ b/docs/book/src/demo.css
@@ -64,7 +64,7 @@
cursor: not-allowed;
}
-.demo-container button ~ button {
+.demo-container button + button {
margin-left: 0.8rem;
}
@@ -134,4 +134,4 @@
border-width: 2px;
border-style: dashed;
padding: 1.5rem;
-}
\ No newline at end of file
+}
diff --git a/docs/book/src/options.md b/docs/book/src/options.md
new file mode 100644
index 0000000..fe312ca
--- /dev/null
+++ b/docs/book/src/options.md
@@ -0,0 +1,22 @@
+# Options
+
+Most functions in Leptos-Use come with a version `..._with_options`. For example `use_css_var` has a
+version `use_css_var_with_options`. As the name suggests, you can provide additional options to those versions of the
+functions.
+
+These options are defined as structs with the corresponding PascalCase name. For our example `use_css_var_with_options`
+the name of the struct is `UseCssVarOptions`. Every option struct implements `Default` and the builder pattern to
+make it easy to change only the values needed. This can look like the following example.
+
+```rust
+let (color, set_color) = use_css_var_with_options(
+ "--color",
+ UseCssVarOptions::default()
+ .target(el)
+ .initial_value("#eee"),
+);
+```
+
+Here only the values `target` and `initial_value` are changed and everything else is left to default.
+
+TODO : automatic conversion like Fn and Option
\ No newline at end of file
diff --git a/docs/book/src/server_side_rendering.md b/docs/book/src/server_side_rendering.md
index a61d69d..d8cc92a 100644
--- a/docs/book/src/server_side_rendering.md
+++ b/docs/book/src/server_side_rendering.md
@@ -54,6 +54,13 @@ By adding `"leptos-use/ssr"` to the `ssr` feature of your project, it will only
be enabled when your project is built with `ssr`, and you will get the server
functions server-side, and the client functions client-side.
+## WASM on the server
+
+If you enable `ssr` in your project on a `wasm32` target architecture, you will get
+a compile-time warning in the console because it is a common mistake that users enable `ssr` globally.
+If you're using `wasm32` on the server however you can safely disable this warning by
+enabling the `wasm_ssr` feature together with `ssr`.
+
## Functions with Target Elements
A lot of functions like `use_resize_observer` and `use_element_size` are only useful when a target HTML/SVG element is
diff --git a/docs/book/src/utilities/use_derive_signal.md b/docs/book/src/utilities/use_derive_signal.md
new file mode 100644
index 0000000..a9ee135
--- /dev/null
+++ b/docs/book/src/utilities/use_derive_signal.md
@@ -0,0 +1,5 @@
+# use_derive_signal!
+
+Macro to easily create helper functions that derive a signal using a piece of code.
+
+See [`is_ok`](is_ok.md) or [`use_to_string`](use_to_string.md) as examples.
diff --git a/examples/Cargo.toml b/examples/Cargo.toml
index 4d56bbf..f428959 100644
--- a/examples/Cargo.toml
+++ b/examples/Cargo.toml
@@ -55,6 +55,7 @@ members = [
"use_throttle_fn",
"use_timeout_fn",
"use_timestamp",
+ "use_user_media",
"use_web_notification",
"use_websocket",
"use_webtransport",
diff --git a/examples/ssr/src/app.rs b/examples/ssr/src/app.rs
index 1ab9506..3f25751 100644
--- a/examples/ssr/src/app.rs
+++ b/examples/ssr/src/app.rs
@@ -3,7 +3,7 @@ use leptos::ev::{keypress, KeyboardEvent};
use leptos::prelude::*;
use leptos_meta::*;
use leptos_router::*;
-use leptos_use::storage::use_local_storage;
+use leptos_use::storage::{use_local_storage, use_local_storage_with_options, UseStorageOptions};
use leptos_use::utils::FromToStringCodec;
use leptos_use::{
use_color_mode_with_options, use_cookie_with_options, use_debounce_fn, use_event_listener,
@@ -40,7 +40,10 @@ pub fn App() -> impl IntoView {
#[component]
fn HomePage() -> impl IntoView {
// Creates a reactive value to update the button
- let (count, set_count, _) = use_local_storage::("count-state");
+ let (count, set_count, _) = use_local_storage_with_options::(
+ "count-state",
+ UseStorageOptions::default().delay_during_hydration(true),
+ );
let on_click = move |_| set_count.update(|count| *count += 1);
let nf = use_intl_number_format(
@@ -96,6 +99,10 @@ fn HomePage() -> impl IntoView {
Dark preferred: {is_dark_preferred}
Test cookie: {move || test_cookie().unwrap_or("".to_string())}
+
+ 0 }>
+
Greater than 0
+
}
}
diff --git a/examples/use_storage/Cargo.toml b/examples/use_storage/Cargo.toml
index a4ba692..4a53065 100644
--- a/examples/use_storage/Cargo.toml
+++ b/examples/use_storage/Cargo.toml
@@ -4,11 +4,12 @@ version = "0.1.0"
edition = "2021"
[dependencies]
+codee = { path = "../../../codee", features = ["json_serde"] }
leptos = { version = "0.6", features = ["nightly", "csr"] }
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
-leptos-use = { path = "../..", features = ["docs", "prost", "serde"] }
+leptos-use = { path = "../..", features = ["docs"] }
web-sys = "0.3"
serde = "1.0.163"
diff --git a/examples/use_user_media/Cargo.toml b/examples/use_user_media/Cargo.toml
new file mode 100644
index 0000000..ffd38b8
--- /dev/null
+++ b/examples/use_user_media/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "use_user_media"
+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"
diff --git a/examples/use_user_media/README.md b/examples/use_user_media/README.md
new file mode 100644
index 0000000..8b47003
--- /dev/null
+++ b/examples/use_user_media/README.md
@@ -0,0 +1,23 @@
+A simple example for `use_user_media`.
+
+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
+```
diff --git a/examples/use_user_media/Trunk.toml b/examples/use_user_media/Trunk.toml
new file mode 100644
index 0000000..3e4be08
--- /dev/null
+++ b/examples/use_user_media/Trunk.toml
@@ -0,0 +1,2 @@
+[build]
+public_url = "/demo/"
\ No newline at end of file
diff --git a/examples/use_user_media/index.html b/examples/use_user_media/index.html
new file mode 100644
index 0000000..ae249a6
--- /dev/null
+++ b/examples/use_user_media/index.html
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/examples/use_user_media/input.css b/examples/use_user_media/input.css
new file mode 100644
index 0000000..bd6213e
--- /dev/null
+++ b/examples/use_user_media/input.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
\ No newline at end of file
diff --git a/examples/use_user_media/rust-toolchain.toml b/examples/use_user_media/rust-toolchain.toml
new file mode 100644
index 0000000..271800c
--- /dev/null
+++ b/examples/use_user_media/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "nightly"
\ No newline at end of file
diff --git a/examples/use_user_media/src/main.rs b/examples/use_user_media/src/main.rs
new file mode 100644
index 0000000..54d406c
--- /dev/null
+++ b/examples/use_user_media/src/main.rs
@@ -0,0 +1,57 @@
+use leptos::*;
+use leptos_use::docs::demo_or_body;
+use leptos_use::{use_user_media, UseUserMediaReturn};
+
+#[component]
+fn Demo() -> impl IntoView {
+ let video_ref = create_node_ref::();
+
+ let UseUserMediaReturn {
+ stream,
+ enabled,
+ set_enabled,
+ ..
+ } = use_user_media();
+
+ create_effect(move |_| {
+ match stream.get() {
+ Some(Ok(s)) => {
+ video_ref.get().map(|v| v.set_src_object(Some(&s)));
+ return;
+ }
+ Some(Err(e)) => logging::error!("Failed to get media stream: {:?}", e),
+ None => logging::log!("No stream yet"),
+ }
+
+ video_ref.get().map(|v| v.set_src_object(None));
+ });
+
+ view! {
+
/// }
/// # }
/// ```
///
+/// Here is another example using `msgpack` for encoding and decoding. This means that only binary
+/// messages can be sent or received. For this to work you have to enable the **`msgpack_serde` feature** flag.
+///
+/// ```
+/// # use leptos::*;
+/// # use codee::binary::MsgpackSerdeCodec;
+/// # use leptos_use::{use_websocket, UseWebSocketReturn};
+/// # use serde::{Deserialize, Serialize};
+/// #
+/// # #[component]
+/// # fn Demo() -> impl IntoView {
+/// #[derive(Serialize, Deserialize)]
+/// struct SomeData {
+/// name: String,
+/// count: i32,
+/// }
+///
+/// let UseWebSocketReturn {
+/// message,
+/// send,
+/// ..
+/// } = use_websocket::("wss://some.websocket.server/");
+///
+/// let send_data = move || {
+/// send(&SomeData {
+/// name: "John Doe".to_string(),
+/// count: 42,
+/// });
+/// };
+/// #
+/// # view! {}
+/// }
+/// ```
+///
/// ## Relative Paths
///
/// If the provided `url` is relative, it will be resolved relative to the current page.
@@ -105,11 +141,11 @@ use web_sys::{BinaryType, CloseEvent, Event, MessageEvent, WebSocket};
/// #[derive(Clone)]
/// pub struct WebsocketContext {
/// pub message: Signal