From af2fcb188cd18497cc3ecadafa2ecd154923394a Mon Sep 17 00:00:00 2001
From: Hector Candelaria
Date: Thu, 18 Jul 2024 00:04:57 -0400
Subject: [PATCH 01/26] Fix: correct button misalignment
Replaced the CSS selector `~` with `+` to ensure proper spacing between adjacent buttons. This adjustment targets only the immediate sibling buttons.
---
docs/book/src/demo.css | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
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
+}
From 2bc537292067842a8481746d106de49d7c78fca3 Mon Sep 17 00:00:00 2001
From: Hector Candelaria
Date: Thu, 18 Jul 2024 00:09:06 -0400
Subject: [PATCH 02/26] Docs: correct grammar in function comment
Updated comment to fix grammar.
---
src/use_cookie.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/use_cookie.rs b/src/use_cookie.rs
index e61192f..67336f8 100644
--- a/src/use_cookie.rs
+++ b/src/use_cookie.rs
@@ -11,7 +11,7 @@ use std::rc::Rc;
/// 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
/// something outside of this function changes the cookie, the signal will **not** be updated.
///
From c6005079e12c4e55b9042623291d6aec610a12e1 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Fri, 26 Jul 2024 10:18:09 +0100
Subject: [PATCH 03/26] fixed signal out of scope issue with use_raf_fn.
Fixes #135
---
CHANGELOG.md | 1 +
src/use_raf_fn.rs | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0bf1185..c1c06a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -70,6 +70,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed auto-reconnect in `use_websocket`
- Fixed typo in compiler error messages in `use_cookie` (thanks to @SleeplessOne1917).
+- Fixed potential signal out of scope issue with `use_raf_fn`
## [0.10.10] - 2024-05-10
diff --git a/src/use_raf_fn.rs b/src/use_raf_fn.rs
index a5010db..d390cd1 100644
--- a/src/use_raf_fn.rs
+++ b/src/use_raf_fn.rs
@@ -89,7 +89,7 @@ pub fn use_raf_fn_with_options(
let previous_frame_timestamp = Cell::new(0.0_f64);
move |timestamp: f64| {
- if !is_active.get_untracked() {
+ if !is_active.try_get_untracked().unwrap_or_default() {
return;
}
From ffd4f0a6fe97b83fea126d8257e9541d1cddc6f7 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Fri, 26 Jul 2024 10:36:39 +0100
Subject: [PATCH 04/26] fixed compile error with use_storage
---
CHANGELOG.md | 3 ++-
src/storage/use_storage.rs | 18 +++++++++++-------
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c1c06a3..d9734c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -44,8 +44,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `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.
+ this: `Base64`.
- 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`:
- `UseWebsocketOptions` has been renamed to `UseWebSocketOptions` (uppercase S) to be consistent with the return
type.
diff --git a/src/storage/use_storage.rs b/src/storage/use_storage.rs
index 1c31fea..73eaa35 100644
--- a/src/storage/use_storage.rs
+++ b/src/storage/use_storage.rs
@@ -276,13 +276,17 @@ where
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
- let notify_id = create_memo::(move |prev| {
- notify.track();
- match prev {
- None => 1, // Avoid async fetch of initial value
- Some(prev) => {
- fetch_from_storage();
- prev + 1
+ let notify_id = create_memo::({
+ let fetch_from_storage = fetch_from_storage.clone();
+
+ move |prev| {
+ notify.track();
+ match prev {
+ None => 1, // Avoid async fetch of initial value
+ Some(prev) => {
+ fetch_from_storage();
+ prev + 1
+ }
}
}
});
From 17cfb8a23bb99ff6c815131b1772de71271ea0a8 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Fri, 26 Jul 2024 10:56:39 +0100
Subject: [PATCH 05/26] clarified read option docs for use_clipboard.
Closes #119
---
.idea/leptos-use.iml | 1 +
examples/use_clipboard/src/main.rs | 6 ++++--
src/use_clipboard.rs | 2 ++
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/.idea/leptos-use.iml b/.idea/leptos-use.iml
index 7d56fcb..b65a8a2 100644
--- a/.idea/leptos-use.iml
+++ b/.idea/leptos-use.iml
@@ -77,6 +77,7 @@
+
diff --git a/examples/use_clipboard/src/main.rs b/examples/use_clipboard/src/main.rs
index e7852b3..ebfbf63 100644
--- a/examples/use_clipboard/src/main.rs
+++ b/examples/use_clipboard/src/main.rs
@@ -1,6 +1,8 @@
use leptos::*;
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]
fn Demo() -> impl IntoView {
@@ -11,7 +13,7 @@ fn Demo() -> impl IntoView {
text,
copied,
copy,
- } = use_clipboard();
+ } = use_clipboard_with_options(UseClipboardOptions::default().read(true));
let permission_read = use_permission("clipboard-read");
let permission_write = use_permission("clipboard-write");
diff --git a/src/use_clipboard.rs b/src/use_clipboard.rs
index 78c7eb9..2d4ab26 100644
--- a/src/use_clipboard.rs
+++ b/src/use_clipboard.rs
@@ -127,6 +127,8 @@ pub fn use_clipboard_with_options(
pub struct UseClipboardOptions {
/// When `true` event handlers are added so that the returned signal `text` is updated whenever the clipboard changes.
/// Defaults to `false`.
+ ///
+ /// > Please note that clipboard changes are only detected when copying or cutting text inside the same document.
read: bool,
/// After how many milliseconds after copying should the returned signal `copied` be set to `false`?
From e21ed8ec31560414fa93a1310ff77fbb6168b745 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?=
Date: Sat, 27 Jul 2024 18:10:38 +0200
Subject: [PATCH 06/26] Make rustdocs links work with the book
---
docs/book/post_build.py | 26 ++++++++++++++++-
src/core/element_maybe_signal.rs | 2 +-
src/core/elements_maybe_signal.rs | 2 +-
src/storage/use_local_storage.rs | 11 +++++--
src/storage/use_session_storage.rs | 4 +--
src/storage/use_storage.rs | 8 ++---
src/use_breakpoints.rs | 47 +++++++++++++++---------------
src/use_broadcast_channel.rs | 2 +-
src/use_color_mode.rs | 16 +++++-----
src/use_cookie.rs | 6 +---
src/use_element_size.rs | 2 +-
src/use_element_visibility.rs | 2 +-
src/use_event_source.rs | 6 +---
src/use_intersection_observer.rs | 2 +-
src/use_intl_number_format.rs | 2 +-
src/use_media_query.rs | 4 +--
src/use_preferred_contrast.rs | 4 +--
src/use_preferred_dark.rs | 4 +--
src/use_raf_fn.rs | 2 +-
src/use_resize_observer.rs | 2 +-
src/use_timestamp.rs | 4 +--
src/use_websocket.rs | 1 +
src/use_window.rs | 2 +-
src/utils/use_derive_signal.rs | 2 +-
src/watch_debounced.rs | 9 +++---
src/watch_pausable.rs | 2 +-
src/watch_throttled.rs | 8 ++---
src/watch_with_options.rs | 7 +++--
src/whenever.rs | 6 ++--
29 files changed, 110 insertions(+), 85 deletions(-)
diff --git a/docs/book/post_build.py b/docs/book/post_build.py
index 1abc3a2..fc9fc3a 100644
--- a/docs/book/post_build.py
+++ b/docs/book/post_build.py
@@ -14,6 +14,7 @@ def main():
for file in os.listdir(category_dir):
if file.endswith(".md") and (len(sys.argv) == 1 or (sys.argv[1] in file)):
build_and_copy_demo(category, file)
+ rewrite_links(category, file)
def build_and_copy_demo(category, md_name):
@@ -24,7 +25,8 @@ def build_and_copy_demo(category, md_name):
code = p.wait()
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")
target_path = os.path.join("book", category, name, "demo")
@@ -61,5 +63,27 @@ def build_and_copy_demo(category, md_name):
{body_split[1]}""")
+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__':
main()
diff --git a/src/core/element_maybe_signal.rs b/src/core/element_maybe_signal.rs
index 26c1216..6d25d41 100644
--- a/src/core/element_maybe_signal.rs
+++ b/src/core/element_maybe_signal.rs
@@ -11,7 +11,7 @@ use std::ops::Deref;
/// * a `Signal` where `T` is the web_sys element,
/// * a `Signal>` where `T` is the web_sys element,
/// * 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
where
T: Into + Clone + 'static,
diff --git a/src/core/elements_maybe_signal.rs b/src/core/elements_maybe_signal.rs
index e1f7f7b..c8446d9 100644
--- a/src/core/elements_maybe_signal.rs
+++ b/src/core/elements_maybe_signal.rs
@@ -12,7 +12,7 @@ use std::ops::Deref;
/// * a `Signal` where `T` is the web_sys element,
/// * a `Signal>` where `T` is the web_sys element,
/// * 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
where
T: Into + Clone + 'static,
diff --git a/src/storage/use_local_storage.rs b/src/storage/use_local_storage.rs
index 41811e6..c542a17 100644
--- a/src/storage/use_local_storage.rs
+++ b/src/storage/use_local_storage.rs
@@ -2,14 +2,19 @@ use super::{use_storage_with_options, StorageType, UseStorageOptions};
use codee::{Decoder, Encoder};
use leptos::signal_prelude::*;
+#[allow(rustdoc::bare_urls)]
/// 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
-/// 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(
key: impl AsRef,
) -> (Signal, WriteSignal, impl Fn() + Clone)
diff --git a/src/storage/use_session_storage.rs b/src/storage/use_session_storage.rs
index b377edf..c7fff9d 100644
--- a/src/storage/use_session_storage.rs
+++ b/src/storage/use_session_storage.rs
@@ -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.
///
-/// 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
-/// 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(
key: impl AsRef,
) -> (Signal, WriteSignal, impl Fn() + Clone)
diff --git a/src/storage/use_storage.rs b/src/storage/use_storage.rs
index 73eaa35..4f9c2af 100644
--- a/src/storage/use_storage.rs
+++ b/src/storage/use_storage.rs
@@ -23,12 +23,12 @@ const INTERNAL_STORAGE_EVENT: &str = "leptos-use-storage";
///
/// 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
-/// 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.
+/// is then encoded and decoded via the given `*Codec`. This value is synced with other calls using
+/// the same key on the same page and across tabs for local storage.
/// 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
-/// 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
/// available and what feature flags they require.
@@ -395,7 +395,7 @@ pub enum UseStorageError {
ItemCodecError(CodecError),
}
-/// 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)]
pub struct UseStorageOptions
where
diff --git a/src/use_breakpoints.rs b/src/use_breakpoints.rs
index 548da84..c8b3ae6 100644
--- a/src/use_breakpoints.rs
+++ b/src/use_breakpoints.rs
@@ -37,6 +37,7 @@ use std::hash::Hash;
/// ## Breakpoints
///
/// There are many predefined breakpoints for major UI frameworks. The following are provided.
+///
/// * [`breakpoints_tailwind`]
/// * [`breakpoints_bootstrap_v5`]
/// * [`breakpoints_material`]
@@ -107,7 +108,7 @@ use std::hash::Hash;
///
/// ## 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`.
pub fn use_breakpoints(
breakpoints: HashMap,
@@ -276,7 +277,7 @@ impl UseBreakpointsReturn {
/// Breakpoint keys for Tailwind V2
///
-/// See [https://tailwindcss.com/docs/breakpoints]
+/// See
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BreakpointsTailwind {
Sm,
@@ -288,7 +289,7 @@ pub enum BreakpointsTailwind {
/// Breakpoint definitions for Tailwind V2
///
-/// See [https://tailwindcss.com/docs/breakpoints]
+/// See
pub fn breakpoints_tailwind() -> HashMap {
HashMap::from([
(BreakpointsTailwind::Sm, 640),
@@ -301,7 +302,7 @@ pub fn breakpoints_tailwind() -> HashMap {
/// Breakpoint keys for Bootstrap V5
///
-/// See [https://getbootstrap.com/docs/5.0/layout/breakpoints]
+/// See
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BreakpointsBootstrapV5 {
Sm,
@@ -313,7 +314,7 @@ pub enum BreakpointsBootstrapV5 {
/// Breakpoint definitions for Bootstrap V5
///
-/// See [https://getbootstrap.com/docs/5.0/layout/breakpoints]
+///
pub fn breakpoints_bootstrap_v5() -> HashMap {
HashMap::from([
(BreakpointsBootstrapV5::Sm, 576),
@@ -326,7 +327,7 @@ pub fn breakpoints_bootstrap_v5() -> HashMap {
/// Breakpoint keys for Material UI V5
///
-/// See [https://mui.com/material-ui/customization/breakpoints/]
+/// See
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BreakpointsMaterial {
Xs,
@@ -338,7 +339,7 @@ pub enum BreakpointsMaterial {
/// Breakpoint definitions for Material UI V5
///
-/// See [https://mui.com/material-ui/customization/breakpoints/]
+/// See
pub fn breakpoints_material() -> HashMap {
HashMap::from([
(BreakpointsMaterial::Xs, 1),
@@ -351,7 +352,7 @@ pub fn breakpoints_material() -> HashMap {
/// Breakpoint keys for Ant Design
///
-/// See [https://ant.design/components/layout/#breakpoint-width]
+/// See
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BreakpointsAntDesign {
Xs,
@@ -364,7 +365,7 @@ pub enum BreakpointsAntDesign {
/// Breakpoint definitions for Ant Design
///
-/// See [https://ant.design/components/layout/#breakpoint-width]
+/// See
pub fn breakpoints_ant_design() -> HashMap {
HashMap::from([
(BreakpointsAntDesign::Xs, 480),
@@ -378,7 +379,7 @@ pub fn breakpoints_ant_design() -> HashMap {
/// Breakpoint keys for Quasar V2
///
-/// See [https://quasar.dev/style/breakpoints]
+/// See
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BreakpointsQuasar {
Xs,
@@ -390,7 +391,7 @@ pub enum BreakpointsQuasar {
/// Breakpoint definitions for Quasar V2
///
-/// See [https://quasar.dev/style/breakpoints]
+/// See
pub fn breakpoints_quasar() -> HashMap {
HashMap::from([
(BreakpointsQuasar::Xs, 1),
@@ -401,32 +402,32 @@ pub fn breakpoints_quasar() -> HashMap {
])
}
-/// Breakpoint keys for Sematic UI
+/// Breakpoint keys for Semantic UI
///
-/// See [https://semantic-ui.com/elements/container.html]
+/// See
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub enum BreakpointsSematic {
+pub enum BreakpointsSemantic {
Mobile,
Tablet,
SmallMonitor,
LargeMonitor,
}
-/// Breakpoint definitions for Sematic UI
+/// Breakpoint definitions for Semantic UI
///
-/// See [https://semantic-ui.com/elements/container.html]
-pub fn breakpoints_sematic() -> HashMap {
+/// See
+pub fn breakpoints_semantic() -> HashMap {
HashMap::from([
- (BreakpointsSematic::Mobile, 1),
- (BreakpointsSematic::Tablet, 768),
- (BreakpointsSematic::SmallMonitor, 992),
- (BreakpointsSematic::LargeMonitor, 1200),
+ (BreakpointsSemantic::Mobile, 1),
+ (BreakpointsSemantic::Tablet, 768),
+ (BreakpointsSemantic::SmallMonitor, 992),
+ (BreakpointsSemantic::LargeMonitor, 1200),
])
}
/// Breakpoint keys for Master CSS
///
-/// See [https://docs.master.co/css/breakpoints]
+/// See
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BreakpointsMasterCss {
Xxxs,
@@ -443,7 +444,7 @@ pub enum BreakpointsMasterCss {
/// Breakpoint definitions for Master CSS
///
-/// See [https://docs.master.co/css/breakpoints]
+/// See
pub fn breakpoints_master_css() -> HashMap {
HashMap::from([
(BreakpointsMasterCss::Xxxs, 360),
diff --git a/src/use_broadcast_channel.rs b/src/use_broadcast_channel.rs
index fe9d823..37cc0c5 100644
--- a/src/use_broadcast_channel.rs
+++ b/src/use_broadcast_channel.rs
@@ -45,7 +45,7 @@ use wasm_bindgen::JsValue;
/// ```
///
/// 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
/// available and what feature flags they require.
diff --git a/src/use_color_mode.rs b/src/use_color_mode.rs
index 5e0ba98..66cdd39 100644
--- a/src/use_color_mode.rs
+++ b/src/use_color_mode.rs
@@ -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
/// 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`].
@@ -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)`.
///
-/// > 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
/// # 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
/// 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
///
-/// * [`use_preferred_dark`]
-/// * [`use_storage`]
-/// * [`use_cookie`]
+/// * [`fn@crate::use_preferred_dark`]
+/// * [`fn@crate::storage::use_storage`]
+/// * [`fn@crate::use_cookie`]
pub fn use_color_mode() -> UseColorModeReturn {
use_color_mode_with_options(UseColorModeOptions::default())
}
@@ -508,9 +508,9 @@ pub struct UseColorModeReturn {
/// Main value setter signal of the color mode
pub set_mode: WriteSignal,
- /// 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,
- /// 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,
/// Signal of the system's preferred color mode that you would get from a media query
diff --git a/src/use_cookie.rs b/src/use_cookie.rs
index 67336f8..4ac3811 100644
--- a/src/use_cookie.rs
+++ b/src/use_cookie.rs
@@ -57,7 +57,7 @@ use std::rc::Rc;
/// ```
///
/// 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
/// available and what feature flags they require.
@@ -136,10 +136,6 @@ use std::rc::Rc;
/// # 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(cookie_name: &str) -> (Signal>, WriteSignal >)
where
C: Encoder + Decoder,
diff --git a/src/use_element_size.rs b/src/use_element_size.rs
index 8b178bc..648e6a5 100644
--- a/src/use_element_size.rs
+++ b/src/use_element_size.rs
@@ -45,7 +45,7 @@ cfg_if! { if #[cfg(not(feature = "ssr"))] {
///
/// ## See also
///
-/// - [`use_resize_observer`]
+/// - [`fn@crate::use_resize_observer`]
pub fn use_element_size(target: El) -> UseElementSizeReturn
where
El: Into> + Clone,
diff --git a/src/use_element_visibility.rs b/src/use_element_visibility.rs
index 23a9543..2199788 100644
--- a/src/use_element_visibility.rs
+++ b/src/use_element_visibility.rs
@@ -40,7 +40,7 @@ use crate::{use_intersection_observer_with_options, UseIntersectionObserverOptio
///
/// ## See also
///
-/// * [`use_intersection_observer`]
+/// * [`fn@crate::use_intersection_observer`]
pub fn use_element_visibility(target: El) -> Signal
where
El: Into>,
diff --git a/src/use_event_source.rs b/src/use_event_source.rs
index e158324..c3fd25d 100644
--- a/src/use_event_source.rs
+++ b/src/use_event_source.rs
@@ -19,7 +19,7 @@ use thiserror::Error;
/// ## Usage
///
/// 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
/// available and what feature flags they require.
@@ -47,10 +47,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
///
/// You can define named events when using `use_event_source_with_options`.
diff --git a/src/use_intersection_observer.rs b/src/use_intersection_observer.rs
index 6cc3849..cca3343 100644
--- a/src/use_intersection_observer.rs
+++ b/src/use_intersection_observer.rs
@@ -52,7 +52,7 @@ cfg_if! { if #[cfg(not(feature = "ssr"))] {
///
/// ## See also
///
-/// * [`use_element_visibility`]
+/// * [`fn@crate::use_element_visibility`]
pub fn use_intersection_observer(
target: El,
callback: F,
diff --git a/src/use_intl_number_format.rs b/src/use_intl_number_format.rs
index d7ad291..694ba76 100644
--- a/src/use_intl_number_format.rs
+++ b/src/use_intl_number_format.rs
@@ -484,7 +484,7 @@ pub struct UseIntlNumberFormatOptions {
/// 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,
- /// 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.
#[builder(into)]
currency: Option,
diff --git a/src/use_media_query.rs b/src/use_media_query.rs
index b9c5be8..61e423c 100644
--- a/src/use_media_query.rs
+++ b/src/use_media_query.rs
@@ -36,8 +36,8 @@ use std::rc::Rc;
///
/// ## See also
///
-/// * [`use_preferred_dark`]
-/// * [`use_preferred_contrast`]
+/// * [`fn@crate::use_preferred_dark`]
+/// * [`fn@crate::use_preferred_contrast`]
pub fn use_media_query(query: impl Into>) -> Signal {
let query = query.into();
diff --git a/src/use_preferred_contrast.rs b/src/use_preferred_contrast.rs
index 86c3ebe..85fc679 100644
--- a/src/use_preferred_contrast.rs
+++ b/src/use_preferred_contrast.rs
@@ -25,8 +25,8 @@ use std::fmt::Display;
///
/// ## See also
///
-/// * [`use_media_query`]
-/// * [`use_preferred_dark`]
+/// * [`fn@crate::use_media_query`]
+/// * [`fn@crate::use_preferred_dark`]
pub fn use_preferred_contrast() -> Signal {
let is_more = use_media_query("(prefers-contrast: more)");
let is_less = use_media_query("(prefers-contrast: less)");
diff --git a/src/use_preferred_dark.rs b/src/use_preferred_dark.rs
index 0f44831..18d8043 100644
--- a/src/use_preferred_dark.rs
+++ b/src/use_preferred_dark.rs
@@ -24,8 +24,8 @@ use leptos::*;
///
/// ## See also
///
-/// * [`use_media_query`]
-/// * [`use_preferred_contrast`]
+/// * [`fn@crate::use_media_query`]
+/// * [`fn@crate::use_preferred_contrast`]
pub fn use_preferred_dark() -> Signal {
use_media_query("(prefers-color-scheme: dark)")
}
diff --git a/src/use_raf_fn.rs b/src/use_raf_fn.rs
index d390cd1..eb61261 100644
--- a/src/use_raf_fn.rs
+++ b/src/use_raf_fn.rs
@@ -165,6 +165,6 @@ pub struct UseRafFnCallbackArgs {
/// Time elapsed between this and the last frame.
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,
}
diff --git a/src/use_resize_observer.rs b/src/use_resize_observer.rs
index 11aafe7..3a631ca 100644
--- a/src/use_resize_observer.rs
+++ b/src/use_resize_observer.rs
@@ -50,7 +50,7 @@ cfg_if! { if #[cfg(not(feature = "ssr"))] {
///
/// ## See also
///
-/// - [`use_element_size`]
+/// * [`fn@crate::use_element_size`]
pub fn use_resize_observer(
target: El, // TODO : multiple elements?
callback: F,
diff --git a/src/use_timestamp.rs b/src/use_timestamp.rs
index d09ec01..9cbcdae 100644
--- a/src/use_timestamp.rs
+++ b/src/use_timestamp.rs
@@ -155,10 +155,10 @@ pub struct UseTimestampOptions {
/// Interval type for [`UseTimestampOptions`].
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum TimestampInterval {
- /// use [`use_raf_fn`] for updating the timestamp
+ /// use [`fn@crate::use_raf_fn`] for updating the timestamp
RequestAnimationFrame,
- /// use [`use_interval_fn`] for updating the timestamp
+ /// use [`fn@crate::use_interval_fn`] for updating the timestamp
Interval(u64),
}
diff --git a/src/use_websocket.rs b/src/use_websocket.rs
index d7c41e4..8654832 100644
--- a/src/use_websocket.rs
+++ b/src/use_websocket.rs
@@ -16,6 +16,7 @@ use js_sys::Array;
use wasm_bindgen::prelude::*;
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.
///
/// ## Demo
diff --git a/src/use_window.rs b/src/use_window.rs
index b0185f8..542b1f9 100644
--- a/src/use_window.rs
+++ b/src/use_window.rs
@@ -54,7 +54,7 @@ impl UseWindow {
navigator(&self) -> Option
);
- /// Returns the same as [`use_document`].
+ /// Returns the same as [`fn@use_document`].
#[inline(always)]
pub fn document(&self) -> UseDocument {
use_document()
diff --git a/src/utils/use_derive_signal.rs b/src/utils/use_derive_signal.rs
index 1e7e9c2..6e7f7fc 100644
--- a/src/utils/use_derive_signal.rs
+++ b/src/utils/use_derive_signal.rs
@@ -1,6 +1,6 @@
/// 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_rules! use_derive_signal {
(
diff --git a/src/watch_debounced.rs b/src/watch_debounced.rs
index b52d2eb..2dbe3ef 100644
--- a/src/watch_debounced.rs
+++ b/src/watch_debounced.rs
@@ -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.
///
-/// 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::*;
@@ -70,8 +70,8 @@ use leptos::*;
///
/// ## See also
///
-/// * [`watch`]
-/// * [`watch_throttled`]
+/// * `leptos::watch`
+/// * [`fn@crate::watch_throttled`]
pub fn watch_debounced(deps: DFn, callback: CFn, ms: f64) -> impl Fn() + Clone
where
DFn: Fn() -> W + 'static,
@@ -82,7 +82,8 @@ where
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(
deps: DFn,
callback: CFn,
diff --git a/src/watch_pausable.rs b/src/watch_pausable.rs
index 62099e7..1d7d924 100644
--- a/src/watch_pausable.rs
+++ b/src/watch_pausable.rs
@@ -52,7 +52,7 @@ use leptos::*;
///
/// ## See also
///
-/// * [`watch`]
+/// * `leptos::watch`
pub fn watch_pausable(
deps: DFn,
callback: CFn,
diff --git a/src/watch_throttled.rs b/src/watch_throttled.rs
index 00497a3..5fd585f 100644
--- a/src/watch_throttled.rs
+++ b/src/watch_throttled.rs
@@ -1,7 +1,7 @@
use crate::{watch_with_options, ThrottleOptions, WatchOptions};
use default_struct_builder::DefaultBuilder;
-/// A throttled version of [`watch`].
+/// A throttled version of `leptos::watch`.
///
/// ## Demo
///
@@ -69,8 +69,8 @@ use default_struct_builder::DefaultBuilder;
///
/// ## See also
///
-/// * [`watch`]
-/// * [`watch_debounced`]
+/// * `leptos::watch`
+/// * [`fn@crate::watch_debounced`]
pub fn watch_throttled(deps: DFn, callback: CFn, ms: f64) -> impl Fn() + Clone
where
DFn: Fn() -> W + 'static,
@@ -81,7 +81,7 @@ where
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(
deps: DFn,
callback: CFn,
diff --git a/src/watch_with_options.rs b/src/watch_with_options.rs
index b01c255..85747fd 100644
--- a/src/watch_with_options.rs
+++ b/src/watch_with_options.rs
@@ -38,7 +38,8 @@ use std::rc::Rc;
///
/// ## 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::*;
@@ -86,8 +87,8 @@ use std::rc::Rc;
///
/// ## See also
///
-/// * [`watch_throttled`]
-/// * [`watch_debounced`]
+/// * [`fn@crate::watch_throttled`]
+/// * [`fn@crate::watch_debounced`]
/// Version of `watch` that accepts `WatchOptions`. See [`watch`] for how to use.
pub fn watch_with_options(
diff --git a/src/whenever.rs b/src/whenever.rs
index b8f4c3c..260e944 100644
--- a/src/whenever.rs
+++ b/src/whenever.rs
@@ -20,7 +20,7 @@ use crate::{watch_with_options, WatchOptions};
///
/// ### 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::*;
@@ -39,7 +39,7 @@ use crate::{watch_with_options, WatchOptions};
///
/// ### 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::*;
@@ -59,7 +59,7 @@ use crate::{watch_with_options, WatchOptions};
///
/// ### Options
///
-/// Options and defaults are same as [`watch_with_options`].
+/// Options and defaults are same as [`fn@watch_with_options`].
///
/// ```
/// # use leptos::*;
From 60d43f63175089d4330d3224b05ae7cf12419f08 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?=
Date: Sat, 27 Jul 2024 18:23:28 +0200
Subject: [PATCH 07/26] Run `cargo fmt`
---
src/lib.rs | 4 ++--
src/use_clipboard.rs | 2 +-
src/use_cookie.rs | 2 +-
src/utils/use_derive_signal.rs | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/lib.rs b/src/lib.rs
index 41112af..efcf708 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -25,7 +25,6 @@ mod is_none;
mod is_ok;
mod is_some;
mod on_click_outside;
-mod use_user_media;
mod signal_debounced;
mod signal_throttled;
mod sync_signal;
@@ -75,6 +74,7 @@ mod use_throttle_fn;
mod use_timeout_fn;
mod use_timestamp;
mod use_to_string;
+mod use_user_media;
mod use_web_notification;
mod use_websocket;
mod use_window;
@@ -91,7 +91,6 @@ pub use is_none::*;
pub use is_ok::*;
pub use is_some::*;
pub use on_click_outside::*;
-pub use use_user_media::*;
pub use signal_debounced::*;
pub use signal_throttled::*;
pub use sync_signal::*;
@@ -141,6 +140,7 @@ pub use use_throttle_fn::*;
pub use use_timeout_fn::*;
pub use use_timestamp::*;
pub use use_to_string::*;
+pub use use_user_media::*;
pub use use_web_notification::*;
pub use use_websocket::*;
pub use use_window::*;
diff --git a/src/use_clipboard.rs b/src/use_clipboard.rs
index 2d4ab26..ecdc42f 100644
--- a/src/use_clipboard.rs
+++ b/src/use_clipboard.rs
@@ -127,7 +127,7 @@ pub fn use_clipboard_with_options(
pub struct UseClipboardOptions {
/// When `true` event handlers are added so that the returned signal `text` is updated whenever the clipboard changes.
/// Defaults to `false`.
- ///
+ ///
/// > Please note that clipboard changes are only detected when copying or cutting text inside the same document.
read: bool,
diff --git a/src/use_cookie.rs b/src/use_cookie.rs
index 4ac3811..aabfe2d 100644
--- a/src/use_cookie.rs
+++ b/src/use_cookie.rs
@@ -92,7 +92,7 @@ use std::rc::Rc;
/// 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 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.
/// > In case it's `actix-web` enable the feature `"actix"`, for `spin` enable `"spin"`.
diff --git a/src/utils/use_derive_signal.rs b/src/utils/use_derive_signal.rs
index 6e7f7fc..639d100 100644
--- a/src/utils/use_derive_signal.rs
+++ b/src/utils/use_derive_signal.rs
@@ -1,5 +1,5 @@
/// Macro to easily create helper functions that derive a signal using a piece of code.
-///
+///
/// See [`fn@crate::is_ok`] or [`fn@crate::use_to_string`] as examples.
#[macro_export]
macro_rules! use_derive_signal {
From 6001a93142f49011e378a2b64caf5b3f4fc818da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?=
Date: Sat, 27 Jul 2024 18:35:59 +0200
Subject: [PATCH 08/26] Run `cargo clippy`
---
src/core/element_maybe_signal.rs | 2 ++
src/core/elements_maybe_signal.rs | 2 ++
src/on_click_outside.rs | 6 +++---
src/storage/use_storage.rs | 2 +-
src/use_broadcast_channel.rs | 2 +-
src/use_color_mode.rs | 2 +-
src/use_cookie.rs | 2 +-
src/use_event_source.rs | 2 +-
src/use_websocket.rs | 3 ++-
src/watch_with_options.rs | 2 --
10 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/src/core/element_maybe_signal.rs b/src/core/element_maybe_signal.rs
index 6d25d41..6b81824 100644
--- a/src/core/element_maybe_signal.rs
+++ b/src/core/element_maybe_signal.rs
@@ -6,11 +6,13 @@ use std::marker::PhantomData;
use std::ops::Deref;
/// 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`),
/// * an `Option` where `T` is the web_sys element,
/// * a `Signal` where `T` is the web_sys element,
/// * a `Signal>` where `T` is the web_sys element,
/// * a `NodeRef`
+///
/// into a function. Used for example in [`fn@crate::use_event_listener`].
pub enum ElementMaybeSignal
where
diff --git a/src/core/elements_maybe_signal.rs b/src/core/elements_maybe_signal.rs
index c8446d9..cbc761a 100644
--- a/src/core/elements_maybe_signal.rs
+++ b/src/core/elements_maybe_signal.rs
@@ -7,11 +7,13 @@ use std::marker::PhantomData;
use std::ops::Deref;
/// 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`),
/// * an `Option` where `T` is the web_sys element,
/// * a `Signal` where `T` is the web_sys element,
/// * a `Signal>` where `T` is the web_sys element,
/// * a `NodeRef`
+///
/// into a function. Used for example in [`fn@crate::use_event_listener`].
pub enum ElementsMaybeSignal
where
diff --git a/src/on_click_outside.rs b/src/on_click_outside.rs
index def8aa8..403a005 100644
--- a/src/on_click_outside.rs
+++ b/src/on_click_outside.rs
@@ -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)
-/// which is **not** supported by IE 11, Edge 18 and below.
-/// If you are targeting these browsers, we recommend you to include
-/// [this code snippet](https://gist.github.com/sibbng/13e83b1dd1b733317ce0130ef07d4efd) on your project.
+/// > which is **not** supported by IE 11, Edge 18 and below.
+/// > If you are targeting these browsers, we recommend you to include
+/// > [this code snippet](https://gist.github.com/sibbng/13e83b1dd1b733317ce0130ef07d4efd) on your project.
///
/// ## Excluding Elements
///
diff --git a/src/storage/use_storage.rs b/src/storage/use_storage.rs
index 4f9c2af..0d8f903 100644
--- a/src/storage/use_storage.rs
+++ b/src/storage/use_storage.rs
@@ -31,7 +31,7 @@ const INTERNAL_STORAGE_EVENT: &str = "leptos-use-storage";
/// binary codec wrapped in `Base64`.
///
/// > 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
///
diff --git a/src/use_broadcast_channel.rs b/src/use_broadcast_channel.rs
index 37cc0c5..6355356 100644
--- a/src/use_broadcast_channel.rs
+++ b/src/use_broadcast_channel.rs
@@ -48,7 +48,7 @@ use wasm_bindgen::JsValue;
/// binary codec wrapped in `Base64`.
///
/// > 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::*;
diff --git a/src/use_color_mode.rs b/src/use_color_mode.rs
index 66cdd39..1df636b 100644
--- a/src/use_color_mode.rs
+++ b/src/use_color_mode.rs
@@ -426,7 +426,7 @@ where
/// To get the default behaviour back you can call the provided `default_handler` function.
/// It takes two parameters:
/// - `mode: ColorMode`: The color mode to change to.
- /// -`default_handler: Rc`: The default handler that would have been called if the `on_changed` handler had not been specified.
+ /// - `default_handler: Rc`: The default handler that would have been called if the `on_changed` handler had not been specified.
on_changed: OnChangedFn,
/// When provided, `useStorage` will be skipped.
diff --git a/src/use_cookie.rs b/src/use_cookie.rs
index aabfe2d..1af6615 100644
--- a/src/use_cookie.rs
+++ b/src/use_cookie.rs
@@ -60,7 +60,7 @@ use std::rc::Rc;
/// binary codec wrapped in `Base64`.
///
/// > 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
///
diff --git a/src/use_event_source.rs b/src/use_event_source.rs
index c3fd25d..30edbfb 100644
--- a/src/use_event_source.rs
+++ b/src/use_event_source.rs
@@ -22,7 +22,7 @@ use thiserror::Error;
/// binary codec wrapped in `Base64`.
///
/// > 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.
///
///
/// ```
diff --git a/src/use_websocket.rs b/src/use_websocket.rs
index 8654832..48a9596 100644
--- a/src/use_websocket.rs
+++ b/src/use_websocket.rs
@@ -28,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.
///
/// > 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::*;
@@ -248,6 +248,7 @@ where
}
/// Version of [`use_websocket`] that takes `UseWebSocketOptions`. See [`use_websocket`] for how to use.
+#[allow(clippy::type_complexity)]
pub fn use_websocket_with_options(
url: &str,
options: UseWebSocketOptions<
diff --git a/src/watch_with_options.rs b/src/watch_with_options.rs
index 85747fd..4e0f4ad 100644
--- a/src/watch_with_options.rs
+++ b/src/watch_with_options.rs
@@ -89,8 +89,6 @@ use std::rc::Rc;
///
/// * [`fn@crate::watch_throttled`]
/// * [`fn@crate::watch_debounced`]
-
-/// Version of `watch` that accepts `WatchOptions`. See [`watch`] for how to use.
pub fn watch_with_options(
deps: DFn,
callback: CFn,
From a3015625e4f698918e2e64ed3a2a3afdfb2d6829 Mon Sep 17 00:00:00 2001
From: Esteban Borai
Date: Sat, 27 Jul 2024 12:36:08 -0400
Subject: [PATCH 09/26] chore: integrity checks for nightly/stable
---
.github/workflows/cd.yml | 82 +++++++++++++++++++++++++++++
.github/workflows/ci.yml | 110 ++++++++++++++-------------------------
2 files changed, 120 insertions(+), 72 deletions(-)
create mode 100644 .github/workflows/cd.yml
diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
new file mode 100644
index 0000000..b1e6e05
--- /dev/null
+++ b/.github/workflows/cd.yml
@@ -0,0 +1,82 @@
+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)
+ 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/*/}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 95f75d3..07bd401 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,82 +1,48 @@
+name: Continuous Integration
+
on:
- push:
- # Pattern matched against refs/tags
- tags:
- - '*' # Push events to every tag not containing /
- workflow_dispatch:
+ pull_request:
+ branches:
+ - main
+ paths:
+ - "**"
+ - "!/*.md"
+ - "!/**.md"
-name: CI
-
-permissions: write-all
+concurrency:
+ group: "${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}"
+ cancel-in-progress: true
jobs:
- publish:
- name: Publish
+ integrity:
+ name: Integrity Checks on Rust ${{ matrix.toolchain }}
runs-on: ubuntu-latest
+ timeout-minutes: 15
+ strategy:
+ matrix:
+ toolchain:
+ - stable
+ - nightly
+
steps:
- - uses: actions/checkout@v3
- - uses: actions-rs/toolchain@v1
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup Rust
+ uses: dtolnay/rust-toolchain
with:
- toolchain: nightly
- profile: minimal
- override: true
- components: rustfmt, clippy, rust-src
- - name: Cache
+ toolchain: ${{ matrix.toolchain }}
+ targets: wasm32-unknown-unknown
+ components: clippy, rustfmt
+
+ - name: Setup Rust 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
+
+ - name: Build
+ run: cargo build
+
+ - name: Format
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)
- 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/*/}
+ run: cargo clippy -- -D warnings
From 90399ee313056f253e6bd169df5823f5575d95cd Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Sat, 27 Jul 2024 18:07:00 +0100
Subject: [PATCH 10/26] updated changelog
---
CHANGELOG.md | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d9734c5..91aad70 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -65,7 +65,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
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.
+- `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 🍕
@@ -73,6 +75,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- 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
### Change 🔥
From 1e0a87909c9b8cdaa3b242010e804f4769eb890a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?=
Date: Sat, 27 Jul 2024 19:34:01 +0200
Subject: [PATCH 11/26] Fix Rust toolchain step on ci.yml
---
.github/workflows/ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 07bd401..b44b27e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,7 +29,7 @@ jobs:
uses: actions/checkout@v4
- name: Setup Rust
- uses: dtolnay/rust-toolchain
+ uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.toolchain }}
targets: wasm32-unknown-unknown
From b28f1b3e113c008529693b2698da9a2307091079 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Sat, 27 Jul 2024 18:35:19 +0100
Subject: [PATCH 12/26] fixed examples
---
docs/book/post_build.py | 10 +++++++---
examples/use_broadcast_channel/Cargo.toml | 1 +
examples/use_broadcast_channel/src/main.rs | 6 +++---
examples/use_cookie/Cargo.toml | 1 +
examples/use_cookie/src/main.rs | 2 +-
examples/use_storage/Cargo.toml | 8 ++++----
examples/use_storage/src/main.rs | 6 +++---
examples/use_websocket/Cargo.toml | 2 +-
src/use_event_source.rs | 1 -
9 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/docs/book/post_build.py b/docs/book/post_build.py
index fc9fc3a..20691a8 100644
--- a/docs/book/post_build.py
+++ b/docs/book/post_build.py
@@ -13,8 +13,8 @@ def main():
if os.path.isdir(category_dir):
for file in os.listdir(category_dir):
if file.endswith(".md") and (len(sys.argv) == 1 or (sys.argv[1] in file)):
- build_and_copy_demo(category, file)
- rewrite_links(category, file)
+ if build_and_copy_demo(category, file):
+ rewrite_links(category, file)
def build_and_copy_demo(category, md_name):
@@ -51,7 +51,7 @@ def build_and_copy_demo(category, md_name):
with open(book_html_path, "w") as f:
f.write(
- f"""{head_split[0]}
+ f"""{head_split[0]}
{demo_head}
{target_head}
@@ -62,6 +62,10 @@ def build_and_copy_demo(category, md_name):
{body_split[1]}""")
+ return True
+
+ return False
+
def rewrite_links(category, md_name):
"""Rewrite links in generated documentation to make them
diff --git a/examples/use_broadcast_channel/Cargo.toml b/examples/use_broadcast_channel/Cargo.toml
index 6a95089..a7bf756 100644
--- a/examples/use_broadcast_channel/Cargo.toml
+++ b/examples/use_broadcast_channel/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
leptos = { version = "0.6", features = ["nightly", "csr"] }
+codee = "0.1"
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
diff --git a/examples/use_broadcast_channel/src/main.rs b/examples/use_broadcast_channel/src/main.rs
index 749ae88..3890bdc 100644
--- a/examples/use_broadcast_channel/src/main.rs
+++ b/examples/use_broadcast_channel/src/main.rs
@@ -1,6 +1,6 @@
+use codee::string::FromToStringCodec;
use leptos::*;
use leptos_use::docs::demo_or_body;
-use leptos_use::utils::FromToStringCodec;
use leptos_use::{use_broadcast_channel, UseBroadcastChannelReturn};
#[component]
@@ -46,8 +46,8 @@ fn Demo() -> impl IntoView {
"Received message: " {move || message().as_ref().unwrap().to_string()}
-
- "Error: " {move || format!("{:?}", error().as_ref().unwrap())}
+
+ "Error: " {move || error.with(|e| format!("{:?}", e.as_ref().unwrap()))}
}
diff --git a/examples/use_cookie/Cargo.toml b/examples/use_cookie/Cargo.toml
index 280824f..c645550 100644
--- a/examples/use_cookie/Cargo.toml
+++ b/examples/use_cookie/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
leptos = { version = "0.6", features = ["nightly", "csr"] }
+codee = "0.1"
console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
diff --git a/examples/use_cookie/src/main.rs b/examples/use_cookie/src/main.rs
index 0429b28..4954248 100644
--- a/examples/use_cookie/src/main.rs
+++ b/examples/use_cookie/src/main.rs
@@ -1,7 +1,7 @@
use leptos::*;
use leptos_use::docs::demo_or_body;
use leptos_use::use_cookie;
-use leptos_use::utils::FromToStringCodec;
+use codee::string::FromToStringCodec;
use rand::prelude::*;
#[component]
diff --git a/examples/use_storage/Cargo.toml b/examples/use_storage/Cargo.toml
index 4a53065..5174789 100644
--- a/examples/use_storage/Cargo.toml
+++ b/examples/use_storage/Cargo.toml
@@ -4,14 +4,14 @@ version = "0.1.0"
edition = "2021"
[dependencies]
-codee = { path = "../../../codee", features = ["json_serde"] }
-leptos = { version = "0.6", features = ["nightly", "csr"] }
+codee = { version = "0.1", features = ["json_serde"] }
console_error_panic_hook = "0.1"
console_log = "1"
-log = "0.4"
+leptos = { version = "0.6", features = ["nightly", "csr"] }
leptos-use = { path = "../..", features = ["docs"] }
-web-sys = "0.3"
+log = "0.4"
serde = "1.0.163"
+web-sys = "0.3"
[dev-dependencies]
wasm-bindgen = "0.2"
diff --git a/examples/use_storage/src/main.rs b/examples/use_storage/src/main.rs
index 0d38d7b..524facd 100644
--- a/examples/use_storage/src/main.rs
+++ b/examples/use_storage/src/main.rs
@@ -1,7 +1,7 @@
use leptos::*;
use leptos_use::docs::{demo_or_body, Note};
use leptos_use::storage::use_local_storage;
-use leptos_use::utils::JsonCodec;
+use codee::string::JsonSerdeCodec;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
@@ -25,8 +25,8 @@ impl Default for BananaState {
#[component]
fn Demo() -> impl IntoView {
- let (state, set_state, reset) = use_local_storage::("banana-state");
- let (state2, _, _) = use_local_storage::("banana-state");
+ let (state, set_state, reset) = use_local_storage::("banana-state");
+ let (state2, _, _) = use_local_storage::("banana-state");
view! {
Please check [the codec chapter](https://leptos-use.rs/codecs.html) to see what codecs are
/// > available and what feature flags they require.
///
-///
/// ```
/// # use leptos::*;
/// # use leptos_use::{use_event_source, UseEventSourceReturn};
From d648eaa2ad6cf5890cb090faa0e3301e8f5cb6fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?=
Date: Sat, 27 Jul 2024 19:41:48 +0200
Subject: [PATCH 13/26] Fix `web_sys_unstable_apis` not passed to rustdoc
---
.cargo/config.toml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.cargo/config.toml b/.cargo/config.toml
index b891103..eac64d8 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -1,3 +1,3 @@
-[unstable]
+[build]
rustflags = ["--cfg=web_sys_unstable_apis"]
-rustdocflags = ["--cfg=web_sys_unstable_apis"]
\ No newline at end of file
+rustdocflags = ["--cfg=web_sys_unstable_apis"]
From 0a9dbc40477351a8281b22a1d89d5d1bfff9746f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?=
Date: Sat, 27 Jul 2024 19:46:02 +0200
Subject: [PATCH 14/26] Run `clippy`
---
src/use_clipboard.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/use_clipboard.rs b/src/use_clipboard.rs
index ecdc42f..74a7ff9 100644
--- a/src/use_clipboard.rs
+++ b/src/use_clipboard.rs
@@ -11,7 +11,7 @@ use leptos::*;
/// Without user permission, reading or altering the clipboard contents is not permitted.
///
/// > 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
///
@@ -89,7 +89,7 @@ pub fn use_clipboard_with_options(
};
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);
}
From 0103524d276c6227729b8850bdd951d8216ce613 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Sat, 27 Jul 2024 19:13:54 +0100
Subject: [PATCH 15/26] Release 0.11.0
---
CHANGELOG.md | 2 +-
Cargo.toml | 2 +-
README.md | 4 ++--
docs/book/src/introduction.md | 2 +-
examples/ssr/Cargo.toml | 1 +
examples/ssr/src/app.rs | 4 ++--
src/use_cookie.rs | 37 ++++++++++++++++++++++-------------
7 files changed, 31 insertions(+), 21 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 91aad70..c2d7794 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,7 @@
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).
-## [Unreleased]
+## [0.11.0] - 2024-07-27
### New Functions 🚀
diff --git a/Cargo.toml b/Cargo.toml
index aa60808..4aa163c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "leptos-use"
-version = "0.10.10"
+version = "0.11.0"
edition = "2021"
authors = ["Marc-Stefan Cassola"]
categories = ["gui", "web-programming"]
diff --git a/README.md b/README.md
index 57516cc..7711119 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
-
+
@@ -92,4 +92,4 @@ This will create the function file in the src directory, scaffold an example dir
| <= 0.3 | 0.3 |
| 0.4, 0.5, 0.6 | 0.4 |
| 0.7, 0.8, 0.9 | 0.5 |
-| 0.10 | 0.6 |
\ No newline at end of file
+| 0.10, 0.11 | 0.6 |
diff --git a/docs/book/src/introduction.md b/docs/book/src/introduction.md
index f12ec1b..cf0098a 100644
--- a/docs/book/src/introduction.md
+++ b/docs/book/src/introduction.md
@@ -12,6 +12,6 @@
-
+
\ No newline at end of file
diff --git a/examples/ssr/Cargo.toml b/examples/ssr/Cargo.toml
index d0b6e6a..5d71626 100644
--- a/examples/ssr/Cargo.toml
+++ b/examples/ssr/Cargo.toml
@@ -8,6 +8,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
axum = { version = "0.7", optional = true }
+codee = "0.1"
console_error_panic_hook = "0.1"
console_log = "1"
cfg-if = "1"
diff --git a/examples/ssr/src/app.rs b/examples/ssr/src/app.rs
index 80b8695..7db0793 100644
--- a/examples/ssr/src/app.rs
+++ b/examples/ssr/src/app.rs
@@ -4,7 +4,7 @@ use leptos::*;
use leptos_meta::*;
use leptos_router::*;
use leptos_use::storage::{use_local_storage, use_local_storage_with_options, UseStorageOptions};
-use leptos_use::utils::FromToStringCodec;
+use codee::string::FromToStringCodec;
use leptos_use::{
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,
@@ -78,7 +78,7 @@ fn HomePage() -> impl IntoView {
let (test_cookie, _) = use_cookie_with_options::(
"test-cookie",
- UseCookieOptions::::default()
+ UseCookieOptions::::default()
.max_age(3000)
.default_value(Some("Bogus string".to_owned())),
);
diff --git a/src/use_cookie.rs b/src/use_cookie.rs
index 1af6615..d212b18 100644
--- a/src/use_cookie.rs
+++ b/src/use_cookie.rs
@@ -359,6 +359,8 @@ where
#[cfg(feature = "ssr")]
{
if !readonly {
+ let cookie_name = cookie_name.to_owned();
+
create_isomorphic_effect(move |_| {
let value = cookie
.with(|cookie| {
@@ -369,20 +371,27 @@ where
})
})
.flatten();
- jar.update_value(|jar| {
- write_server_cookie(
- cookie_name,
- value,
- jar,
- max_age,
- expires,
- domain,
- path,
- same_site,
- secure,
- http_only,
- ssr_set_cookie,
- )
+
+ jar.update_value({
+ let domain = domain.clone();
+ let path = path.clone();
+ let ssr_set_cookie = Rc::clone(&ssr_set_cookie);
+
+ |jar| {
+ write_server_cookie(
+ &cookie_name,
+ value,
+ jar,
+ max_age,
+ expires,
+ domain,
+ path,
+ same_site,
+ secure,
+ http_only,
+ ssr_set_cookie,
+ )
+ }
});
});
}
From 2fe13f954015b5ab60f5f871ae8d05bf452d35dd Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Sat, 27 Jul 2024 19:17:37 +0100
Subject: [PATCH 16/26] chore: rustfmt
---
src/use_cookie.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/use_cookie.rs b/src/use_cookie.rs
index d212b18..b7773a8 100644
--- a/src/use_cookie.rs
+++ b/src/use_cookie.rs
@@ -360,7 +360,7 @@ where
{
if !readonly {
let cookie_name = cookie_name.to_owned();
-
+
create_isomorphic_effect(move |_| {
let value = cookie
.with(|cookie| {
From c674b45635ddc998b824404c847521fc12b63e67 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Sat, 27 Jul 2024 19:25:31 +0100
Subject: [PATCH 17/26] fixed tests
---
src/use_clipboard.rs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/use_clipboard.rs b/src/use_clipboard.rs
index 74a7ff9..c6f1efe 100644
--- a/src/use_clipboard.rs
+++ b/src/use_clipboard.rs
@@ -29,14 +29,14 @@ use leptos::*;
///
/// view! {
/// Your browser does not support Clipboard API }
/// >
///
-///
+///
/// "Copied!"
///
///
From c64fb046f8e2ba46e89118453cdb2775f1dc17b1 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Sat, 27 Jul 2024 19:45:42 +0100
Subject: [PATCH 18/26] updated readme build batch
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 7711119..052d738 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@
[![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)
-[![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)
```rust
From 4ec66ecbc85bbb14b485f9c7aa8955cfe720c7cc Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Sun, 28 Jul 2024 17:41:16 +0100
Subject: [PATCH 19/26] added function header and made use_cookie use it
---
CHANGELOG.md | 10 +++-
docs/book/src/SUMMARY.md | 1 +
docs/book/src/utilities/header.md | 3 ++
src/use_cookie.rs | 74 +-----------------------------
src/utils/header.rs | 76 +++++++++++++++++++++++++++++++
src/utils/header_macro.rs | 36 +++++++++++++++
src/utils/mod.rs | 12 +++++
7 files changed, 138 insertions(+), 74 deletions(-)
create mode 100644 docs/book/src/utilities/header.md
create mode 100644 src/utils/header.rs
create mode 100644 src/utils/header_macro.rs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c2d7794..6516447 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,12 @@
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).
+## [Unreleased]
+
+### New Functions 🚀
+
+- `header` – Standard implementations for reading a header on the server.
+
## [0.11.0] - 2024-07-27
### New Functions 🚀
@@ -31,7 +37,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
option to `true`.
- `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
- The macro `use_derive_signal!` is now exported (thanks to @mscofield0).
@@ -66,7 +72,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- 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.
-- Renamed `BreakpointsSematic` to `BreakpointsSemantic` and `breakpoints_sematic` to `breakpoints_semantic`
+- Renamed `BreakpointsSematic` to `BreakpointsSemantic` and `breakpoints_sematic` to `breakpoints_semantic`
(note the `n`) (thanks to @mondeja).
### Fixes 🍕
diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md
index 502a1a6..c70b480 100644
--- a/docs/book/src/SUMMARY.md
+++ b/docs/book/src/SUMMARY.md
@@ -99,6 +99,7 @@
# Utilities
+- [header](utilities/header.md)
- [is_err](utilities/is_err.md)
- [is_none](utilities/is_none.md)
- [is_ok](utilities/is_ok.md)
diff --git a/docs/book/src/utilities/header.md b/docs/book/src/utilities/header.md
new file mode 100644
index 0000000..2bd2d1f
--- /dev/null
+++ b/docs/book/src/utilities/header.md
@@ -0,0 +1,3 @@
+# header
+
+
diff --git a/src/use_cookie.rs b/src/use_cookie.rs
index b7773a8..2e6c894 100644
--- a/src/use_cookie.rs
+++ b/src/use_cookie.rs
@@ -1,6 +1,7 @@
#![allow(clippy::too_many_arguments)]
use crate::core::now;
+use crate::utils::get_header;
use codee::{CodecError, Decoder, Encoder};
use cookie::time::{Duration, OffsetDateTime};
pub use cookie::SameSite;
@@ -496,78 +497,7 @@ impl Default for UseCookieOptions {
path: None,
same_site: None,
ssr_cookies_header_getter: Rc::new(move || {
- #[cfg(feature = "ssr")]
- {
- #[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::()
- .map(|req| req.headers().clone());
- }
- #[cfg(feature = "axum")]
- {
- headers = use_context::().map(|parts| parts.headers);
- }
- #[cfg(feature = "spin")]
- {
- headers = use_context::()
- .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
+ get_header!(COOKIE, use_cookie, ssr_cookies_header_getter)
}),
ssr_set_cookie: Rc::new(|cookie: &Cookie| {
#[cfg(feature = "ssr")]
diff --git a/src/utils/header.rs b/src/utils/header.rs
new file mode 100644
index 0000000..0e9d6cd
--- /dev/null
+++ b/src/utils/header.rs
@@ -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(name: N) -> Option
+where
+ N: Into,
+{
+ 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::().map(|req| req.headers().clone());
+ }
+ #[cfg(feature = "axum")]
+ {
+ headers = use_context::().map(|parts| parts.headers);
+ }
+ #[cfg(feature = "spin")]
+ {
+ headers = use_context::().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())
+ })
+ }
+}
diff --git a/src/utils/header_macro.rs b/src/utils/header_macro.rs
new file mode 100644
index 0000000..2cb0b52
--- /dev/null
+++ b/src/utils/header_macro.rs
@@ -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;
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index 906f4e1..32d43b0 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -1,4 +1,10 @@
mod filters;
+#[cfg(all(
+ feature = "ssr",
+ any(feature = "axum", feature = "actix", feature = "spin")
+))]
+mod header;
+mod header_macro;
mod is;
mod js;
mod js_value_from_to_string;
@@ -7,6 +13,12 @@ mod signal_filtered;
mod use_derive_signal;
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(crate) use js_value_from_to_string::*;
pub use pausable::*;
From 49bb88768c6bae8a6e2415330ae9ceee28c6b3da Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Sun, 28 Jul 2024 20:02:12 +0100
Subject: [PATCH 20/26] added use_locales
---
.github/workflows/cd.yml | 15 +-
.github/workflows/tests.yml | 27 +-
.idea/leptos-use.iml | 1 +
CHANGELOG.md | 1 +
docs/book/src/SUMMARY.md | 1 +
docs/book/src/intl/use_locales.md | 3 +
examples/Cargo.toml | 1 +
examples/ssr/src/app.rs | 14 +-
examples/use_locales/Cargo.toml | 16 +
examples/use_locales/README.md | 23 ++
examples/use_locales/Trunk.toml | 2 +
examples/use_locales/index.html | 7 +
examples/use_locales/input.css | 3 +
examples/use_locales/rust-toolchain.toml | 2 +
examples/use_locales/src/main.rs | 21 ++
examples/use_locales/style/output.css | 289 ++++++++++++++++++
examples/use_locales/tailwind.config.js | 15 +
src/lib.rs | 2 +
src/use_cookie.rs | 2 +-
src/use_locales.rs | 114 +++++++
.../{{ function_name }}.ffizer.hbs.rs | 12 +-
21 files changed, 549 insertions(+), 22 deletions(-)
create mode 100644 docs/book/src/intl/use_locales.md
create mode 100644 examples/use_locales/Cargo.toml
create mode 100644 examples/use_locales/README.md
create mode 100644 examples/use_locales/Trunk.toml
create mode 100644 examples/use_locales/index.html
create mode 100644 examples/use_locales/input.css
create mode 100644 examples/use_locales/rust-toolchain.toml
create mode 100644 examples/use_locales/src/main.rs
create mode 100644 examples/use_locales/style/output.css
create mode 100644 examples/use_locales/tailwind.config.js
create mode 100644 src/use_locales.rs
diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
index b1e6e05..e8f15e6 100644
--- a/.github/workflows/cd.yml
+++ b/.github/workflows/cd.yml
@@ -23,20 +23,27 @@ jobs:
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)
- 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
+ - name: Run tests (axum) use_cookie
+ run: cargo test --features math,docs,ssr,axum --doc use_cookie
+ - name: Run tests (axum) use_locales
+ run: cargo test --features math,docs,ssr,axum --doc use_locales
+ - name: Run tests (actix) use_cookie
+ run: cargo test --features math,docs,ssr,actix --doc use_cookie
+ - name: Run tests (actix) use_locales
+ run: cargo test --features math,docs,ssr,actix --doc use_locales
#### mdbook
- name: Install mdbook I
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 68ee5cf..6de613d 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -1,5 +1,11 @@
on:
pull_request:
+ branches:
+ - main
+ paths:
+ - "**"
+ - "!/*.md"
+ - "!/**.md"
workflow_dispatch:
name: Tests
@@ -20,13 +26,18 @@ jobs:
components: rustfmt, clippy, rust-src
- name: Cache
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)
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
+
+ - name: Run tests (axum) use_cookie
+ run: cargo test --features math,docs,ssr,axum --doc use_cookie
+
+ - name: Run tests (axum) use_locales
+ run: cargo test --features math,docs,ssr,axum --doc use_locales
+
+ - name: Run tests (actix) use_cookie
+ run: cargo test --features math,docs,ssr,actix --doc use_cookie
+
+ - name: Run tests (actix) use_locales
+ run: cargo test --features math,docs,ssr,actix --doc use_locales
diff --git a/.idea/leptos-use.iml b/.idea/leptos-use.iml
index b65a8a2..bc52064 100644
--- a/.idea/leptos-use.iml
+++ b/.idea/leptos-use.iml
@@ -78,6 +78,7 @@
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6516447..bfc939a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### New Functions 🚀
+- `use_locale`
- `header` – Standard implementations for reading a header on the server.
## [0.11.0] - 2024-07-27
diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md
index c70b480..75aad32 100644
--- a/docs/book/src/SUMMARY.md
+++ b/docs/book/src/SUMMARY.md
@@ -114,6 +114,7 @@
# Intl
- [use_intl_number_format](intl/use_intl_number_format.md)
+- [use_locales](intl/use_locales.md)
# @Math
diff --git a/docs/book/src/intl/use_locales.md b/docs/book/src/intl/use_locales.md
new file mode 100644
index 0000000..084b0fd
--- /dev/null
+++ b/docs/book/src/intl/use_locales.md
@@ -0,0 +1,3 @@
+# use_locales
+
+
diff --git a/examples/Cargo.toml b/examples/Cargo.toml
index f428959..12466ce 100644
--- a/examples/Cargo.toml
+++ b/examples/Cargo.toml
@@ -38,6 +38,7 @@ members = [
"use_interval",
"use_interval_fn",
"use_intl_number_format",
+ "use_locales",
"use_media_query",
"use_mouse",
"use_mouse_in_element",
diff --git a/examples/ssr/src/app.rs b/examples/ssr/src/app.rs
index 7db0793..9ffe5d0 100644
--- a/examples/ssr/src/app.rs
+++ b/examples/ssr/src/app.rs
@@ -1,15 +1,15 @@
use crate::error_template::{AppError, ErrorTemplate};
+use codee::string::FromToStringCodec;
use leptos::ev::{keypress, KeyboardEvent};
use leptos::*;
use leptos_meta::*;
use leptos_router::*;
use leptos_use::storage::{use_local_storage, use_local_storage_with_options, UseStorageOptions};
-use codee::string::FromToStringCodec;
use leptos_use::{
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,
- UseColorModeOptions, UseColorModeReturn, UseCookieOptions, UseIntervalReturn,
- UseIntlNumberFormatOptions,
+ use_interval, use_intl_number_format, use_locales, use_preferred_dark, use_timestamp,
+ use_window, ColorMode, UseColorModeOptions, UseColorModeReturn, UseCookieOptions,
+ UseIntervalReturn, UseIntlNumberFormatOptions,
};
#[component]
@@ -83,12 +83,13 @@ fn HomePage() -> impl IntoView {
.default_value(Some("Bogus string".to_owned())),
);
+ let locales = use_locales();
+
view! {
Leptos-Use SSR Example
Click Me: {count}
- Locale zh-Hans-CN-u-nu-hanidec: {zh_count}
Press any key: {key}
Debounced called: {debounce_value}
Color mode: {move || format!("{:?}", mode.get())}
@@ -99,7 +100,10 @@ fn HomePage() -> impl IntoView {
Dark preferred: {is_dark_preferred}
Test cookie: {move || test_cookie().unwrap_or("".to_string())}
+ {move || format!("Locales:\n {}", locales().join("\n "))}
+ Locale zh-Hans-CN-u-nu-hanidec: {zh_count}
+
0 }>
Greater than 0
diff --git a/examples/use_locales/Cargo.toml b/examples/use_locales/Cargo.toml
new file mode 100644
index 0000000..05b5bc9
--- /dev/null
+++ b/examples/use_locales/Cargo.toml
@@ -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"
diff --git a/examples/use_locales/README.md b/examples/use_locales/README.md
new file mode 100644
index 0000000..f1827be
--- /dev/null
+++ b/examples/use_locales/README.md
@@ -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
+```
\ No newline at end of file
diff --git a/examples/use_locales/Trunk.toml b/examples/use_locales/Trunk.toml
new file mode 100644
index 0000000..3e4be08
--- /dev/null
+++ b/examples/use_locales/Trunk.toml
@@ -0,0 +1,2 @@
+[build]
+public_url = "/demo/"
\ No newline at end of file
diff --git a/examples/use_locales/index.html b/examples/use_locales/index.html
new file mode 100644
index 0000000..ae249a6
--- /dev/null
+++ b/examples/use_locales/index.html
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/examples/use_locales/input.css b/examples/use_locales/input.css
new file mode 100644
index 0000000..bd6213e
--- /dev/null
+++ b/examples/use_locales/input.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
\ No newline at end of file
diff --git a/examples/use_locales/rust-toolchain.toml b/examples/use_locales/rust-toolchain.toml
new file mode 100644
index 0000000..271800c
--- /dev/null
+++ b/examples/use_locales/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "nightly"
\ No newline at end of file
diff --git a/examples/use_locales/src/main.rs b/examples/use_locales/src/main.rs
new file mode 100644
index 0000000..dfa206b
--- /dev/null
+++ b/examples/use_locales/src/main.rs
@@ -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! {
+ {move || format!("Locales:\n {}", locales().join("\n "))}
+ }
+}
+
+fn main() {
+ _ = console_log::init_with_level(log::Level::Debug);
+ console_error_panic_hook::set_once();
+
+ mount_to(demo_or_body(), || {
+ view! { }
+ })
+}
diff --git a/examples/use_locales/style/output.css b/examples/use_locales/style/output.css
new file mode 100644
index 0000000..ab5191f
--- /dev/null
+++ b/examples/use_locales/style/output.css
@@ -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));
+ }
+}
\ No newline at end of file
diff --git a/examples/use_locales/tailwind.config.js b/examples/use_locales/tailwind.config.js
new file mode 100644
index 0000000..bc09f5e
--- /dev/null
+++ b/examples/use_locales/tailwind.config.js
@@ -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'),
+ ],
+}
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index efcf708..45a0e14 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -57,6 +57,7 @@ mod use_intersection_observer;
mod use_interval;
mod use_interval_fn;
mod use_intl_number_format;
+mod use_locales;
mod use_media_query;
mod use_mouse;
mod use_mouse_in_element;
@@ -123,6 +124,7 @@ pub use use_intersection_observer::*;
pub use use_interval::*;
pub use use_interval_fn::*;
pub use use_intl_number_format::*;
+pub use use_locales::*;
pub use use_media_query::*;
pub use use_mouse::*;
pub use use_mouse_in_element::*;
diff --git a/src/use_cookie.rs b/src/use_cookie.rs
index 2e6c894..13f36fe 100644
--- a/src/use_cookie.rs
+++ b/src/use_cookie.rs
@@ -100,7 +100,7 @@ use std::rc::Rc;
///
/// ### 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.
///
/// ```
diff --git a/src/use_locales.rs b/src/use_locales.rs
new file mode 100644
index 0000000..e6d6cc4
--- /dev/null
+++ b/src/use_locales.rs
@@ -0,0 +1,114 @@
+use crate::utils::get_header;
+use default_struct_builder::DefaultBuilder;
+use leptos::*;
+use std::rc::Rc;
+
+/// Reactive accepted 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> {
+ 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> {
+ #[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::>()
+ };
+
+ 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::>();
+
+ 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 Option>,
+}
+
+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)
+ }),
+ }
+ }
+}
diff --git a/template/src/{{ module }}/{{ function_name }}.ffizer.hbs.rs b/template/src/{{ module }}/{{ function_name }}.ffizer.hbs.rs
index 0edb6ba..ef81b03 100644
--- a/template/src/{{ module }}/{{ function_name }}.ffizer.hbs.rs
+++ b/template/src/{{ module }}/{{ function_name }}.ffizer.hbs.rs
@@ -22,19 +22,23 @@ use leptos::*;
/// #
/// # view! { }
/// # }
-/// ```{{#if feature}}
+/// ```
+///
+/// ## Server-Side Rendering
+/// {{#if feature}}
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
+
pub fn {{ function_name }}() -> {{ to_pascal_case function_name }}Return {
{{ 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}}
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 {}
}
-/// Options for [`{{ function_name }}_with_options`].{{#if feature}}
+/// Options for [`fn@crate::{{ function_name }}_with_options`].{{#if feature}}
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
#[derive(DefaultBuilder)]
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}}
pub struct {{ to_pascal_case function_name }}Return {}
\ No newline at end of file
From 7aa580ace4808be8053993f143be4d34b89a4bb6 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Sun, 28 Jul 2024 20:34:38 +0100
Subject: [PATCH 21/26] added use_locale
---
.github/workflows/cd.yml | 14 +-
.github/workflows/tests.yml | 8 +-
.idea/leptos-use.iml | 1 +
CHANGELOG.md | 1 +
docs/book/src/SUMMARY.md | 1 +
docs/book/src/intl/use_locale.md | 3 +
examples/Cargo.toml | 1 +
examples/use_locale/Cargo.toml | 16 ++
examples/use_locale/README.md | 23 ++
examples/use_locale/Trunk.toml | 2 +
examples/use_locale/index.html | 7 +
examples/use_locale/input.css | 3 +
examples/use_locale/rust-toolchain.toml | 2 +
examples/use_locale/src/main.rs | 21 ++
examples/use_locale/style/output.css | 330 ++++++++++++++++++++++++
examples/use_locale/tailwind.config.js | 15 ++
src/lib.rs | 2 +
src/use_locale.rs | 74 ++++++
src/use_locales.rs | 4 +-
19 files changed, 515 insertions(+), 13 deletions(-)
create mode 100644 docs/book/src/intl/use_locale.md
create mode 100644 examples/use_locale/Cargo.toml
create mode 100644 examples/use_locale/README.md
create mode 100644 examples/use_locale/Trunk.toml
create mode 100644 examples/use_locale/index.html
create mode 100644 examples/use_locale/input.css
create mode 100644 examples/use_locale/rust-toolchain.toml
create mode 100644 examples/use_locale/src/main.rs
create mode 100644 examples/use_locale/style/output.css
create mode 100644 examples/use_locale/tailwind.config.js
create mode 100644 src/use_locale.rs
diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
index e8f15e6..cb67468 100644
--- a/.github/workflows/cd.yml
+++ b/.github/workflows/cd.yml
@@ -23,27 +23,27 @@ jobs:
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_locales
- run: cargo test --features math,docs,ssr,axum --doc use_locales
+ - 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_locales
- run: cargo test --features math,docs,ssr,actix --doc use_locales
+ - name: Run tests (actix) use_locale
+ run: cargo test --features math,docs,ssr,actix --doc use_locale
#### mdbook
- name: Install mdbook I
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 6de613d..1ae502a 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -33,11 +33,11 @@ jobs:
- name: Run tests (axum) use_cookie
run: cargo test --features math,docs,ssr,axum --doc use_cookie
- - name: Run tests (axum) use_locales
- run: cargo test --features math,docs,ssr,axum --doc use_locales
+ - 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_locales
- run: cargo test --features math,docs,ssr,actix --doc use_locales
+ - name: Run tests (actix) use_locale
+ run: cargo test --features math,docs,ssr,actix --doc use_locale
diff --git a/.idea/leptos-use.iml b/.idea/leptos-use.iml
index bc52064..a9c24d6 100644
--- a/.idea/leptos-use.iml
+++ b/.idea/leptos-use.iml
@@ -78,6 +78,7 @@
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bfc939a..5deaa0e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### New Functions 🚀
+- `use_locale`
- `use_locale`
- `header` – Standard implementations for reading a header on the server.
diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md
index 75aad32..cd07431 100644
--- a/docs/book/src/SUMMARY.md
+++ b/docs/book/src/SUMMARY.md
@@ -114,6 +114,7 @@
# Intl
- [use_intl_number_format](intl/use_intl_number_format.md)
+- [use_locale](intl/use_locale.md)
- [use_locales](intl/use_locales.md)
# @Math
diff --git a/docs/book/src/intl/use_locale.md b/docs/book/src/intl/use_locale.md
new file mode 100644
index 0000000..56b32d7
--- /dev/null
+++ b/docs/book/src/intl/use_locale.md
@@ -0,0 +1,3 @@
+# use_locale
+
+
diff --git a/examples/Cargo.toml b/examples/Cargo.toml
index 12466ce..debad03 100644
--- a/examples/Cargo.toml
+++ b/examples/Cargo.toml
@@ -38,6 +38,7 @@ members = [
"use_interval",
"use_interval_fn",
"use_intl_number_format",
+ "use_locale",
"use_locales",
"use_media_query",
"use_mouse",
diff --git a/examples/use_locale/Cargo.toml b/examples/use_locale/Cargo.toml
new file mode 100644
index 0000000..eb1cdfd
--- /dev/null
+++ b/examples/use_locale/Cargo.toml
@@ -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"
diff --git a/examples/use_locale/README.md b/examples/use_locale/README.md
new file mode 100644
index 0000000..2398484
--- /dev/null
+++ b/examples/use_locale/README.md
@@ -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
+```
\ No newline at end of file
diff --git a/examples/use_locale/Trunk.toml b/examples/use_locale/Trunk.toml
new file mode 100644
index 0000000..3e4be08
--- /dev/null
+++ b/examples/use_locale/Trunk.toml
@@ -0,0 +1,2 @@
+[build]
+public_url = "/demo/"
\ No newline at end of file
diff --git a/examples/use_locale/index.html b/examples/use_locale/index.html
new file mode 100644
index 0000000..ae249a6
--- /dev/null
+++ b/examples/use_locale/index.html
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/examples/use_locale/input.css b/examples/use_locale/input.css
new file mode 100644
index 0000000..bd6213e
--- /dev/null
+++ b/examples/use_locale/input.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
\ No newline at end of file
diff --git a/examples/use_locale/rust-toolchain.toml b/examples/use_locale/rust-toolchain.toml
new file mode 100644
index 0000000..271800c
--- /dev/null
+++ b/examples/use_locale/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+channel = "nightly"
\ No newline at end of file
diff --git a/examples/use_locale/src/main.rs b/examples/use_locale/src/main.rs
new file mode 100644
index 0000000..36ed437
--- /dev/null
+++ b/examples/use_locale/src/main.rs
@@ -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();
+
+ view! {
+ Locale: {locale}
+ }
+}
+
+fn main() {
+ _ = console_log::init_with_level(log::Level::Debug);
+ console_error_panic_hook::set_once();
+
+ mount_to(demo_or_body(), || {
+ view! { }
+ })
+}
diff --git a/examples/use_locale/style/output.css b/examples/use_locale/style/output.css
new file mode 100644
index 0000000..6063b89
--- /dev/null
+++ b/examples/use_locale/style/output.css
@@ -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));
+ }
+}
\ No newline at end of file
diff --git a/examples/use_locale/tailwind.config.js b/examples/use_locale/tailwind.config.js
new file mode 100644
index 0000000..bc09f5e
--- /dev/null
+++ b/examples/use_locale/tailwind.config.js
@@ -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'),
+ ],
+}
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index 45a0e14..4c63f30 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -25,6 +25,7 @@ mod is_none;
mod is_ok;
mod is_some;
mod on_click_outside;
+mod use_locale;
mod signal_debounced;
mod signal_throttled;
mod sync_signal;
@@ -92,6 +93,7 @@ pub use is_none::*;
pub use is_ok::*;
pub use is_some::*;
pub use on_click_outside::*;
+pub use use_locale::*;
pub use signal_debounced::*;
pub use signal_throttled::*;
pub use sync_signal::*;
diff --git a/src/use_locale.rs b/src/use_locale.rs
new file mode 100644
index 0000000..6e55a37
--- /dev/null
+++ b/src/use_locale.rs
@@ -0,0 +1,74 @@
+use crate::utils::get_header;
+use crate::{use_locales_with_options, UseLocalesOptions};
+use default_struct_builder::DefaultBuilder;
+use leptos::*;
+use std::rc::Rc;
+
+/// Reactive locale.
+///
+/// This is basically the same as [`fn@crate::use_locales`] but takes the first entry of the list.
+/// If no locale is found then [`crate::UseLocaleOptions::fallback`] is returned which defaults
+/// to `"en"`.
+///
+/// ## 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();
+/// #
+/// # view! { }
+/// # }
+/// ```
+///
+/// ## Server-Side Rendering
+///
+/// See [`fn@crate::use_locales`]
+
+pub fn use_locale() -> Signal {
+ use_locale_with_options(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(options: UseLocaleOptions) -> Signal {
+ let UseLocaleOptions {
+ fallback,
+ ssr_lang_header_getter,
+ } = options;
+
+ let locales = use_locales_with_options(UseLocalesOptions {
+ ssr_lang_header_getter,
+ });
+
+ Signal::derive(move || locales.get().first().cloned().unwrap_or(fallback.clone()))
+}
+
+/// Options for [`fn@crate::use_locale_with_options`].
+#[derive(DefaultBuilder)]
+pub struct UseLocaleOptions {
+ /// Fallback value in case no locale is found. Defaults to `"en"`.
+ fallback: String,
+
+ /// 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 Option>,
+}
+
+impl Default for UseLocaleOptions {
+ fn default() -> Self {
+ Self {
+ fallback: "en".to_string(),
+ ssr_lang_header_getter: Rc::new(move || {
+ get_header!(ACCEPT_LANGUAGE, use_locale, ssr_lang_header_getter)
+ }),
+ }
+ }
+}
diff --git a/src/use_locales.rs b/src/use_locales.rs
index e6d6cc4..98f7e73 100644
--- a/src/use_locales.rs
+++ b/src/use_locales.rs
@@ -3,7 +3,7 @@ use default_struct_builder::DefaultBuilder;
use leptos::*;
use std::rc::Rc;
-/// Reactive accepted locales.
+/// 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)
@@ -100,7 +100,7 @@ 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 Option>,
+ pub(crate) ssr_lang_header_getter: Rc Option>,
}
impl Default for UseLocalesOptions {
From 1945e94da17a959a96c4f312db84997acb13a845 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Sun, 28 Jul 2024 20:46:28 +0100
Subject: [PATCH 22/26] release 0.11.1
---
CHANGELOG.md | 6 +++---
Cargo.toml | 4 ++--
README.md | 2 +-
docs/book/src/introduction.md | 2 +-
src/lib.rs | 4 ++--
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5deaa0e..33a9f73 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,12 +3,12 @@
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).
-## [Unreleased]
+## [0.11.1] - 2024-07-28
### New Functions 🚀
-- `use_locale`
-- `use_locale`
+- `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
diff --git a/Cargo.toml b/Cargo.toml
index 4aa163c..7ac4ef7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,10 +1,10 @@
[package]
name = "leptos-use"
-version = "0.11.0"
+version = "0.11.1"
edition = "2021"
authors = ["Marc-Stefan Cassola"]
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/"]
keywords = ["leptos", "utilities"]
license = "MIT OR Apache-2.0"
diff --git a/README.md b/README.md
index 052d738..eb58418 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
-
+
diff --git a/docs/book/src/introduction.md b/docs/book/src/introduction.md
index cf0098a..8bcc1c1 100644
--- a/docs/book/src/introduction.md
+++ b/docs/book/src/introduction.md
@@ -12,6 +12,6 @@
-
+
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index 4c63f30..9ad5b9b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -25,7 +25,6 @@ mod is_none;
mod is_ok;
mod is_some;
mod on_click_outside;
-mod use_locale;
mod signal_debounced;
mod signal_throttled;
mod sync_signal;
@@ -58,6 +57,7 @@ mod use_intersection_observer;
mod use_interval;
mod use_interval_fn;
mod use_intl_number_format;
+mod use_locale;
mod use_locales;
mod use_media_query;
mod use_mouse;
@@ -93,7 +93,6 @@ pub use is_none::*;
pub use is_ok::*;
pub use is_some::*;
pub use on_click_outside::*;
-pub use use_locale::*;
pub use signal_debounced::*;
pub use signal_throttled::*;
pub use sync_signal::*;
@@ -126,6 +125,7 @@ pub use use_intersection_observer::*;
pub use use_interval::*;
pub use use_interval_fn::*;
pub use use_intl_number_format::*;
+pub use use_locale::*;
pub use use_locales::*;
pub use use_media_query::*;
pub use use_mouse::*;
From 709757996ebc7dff23544e4872e87a3a19b85bbd Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Mon, 29 Jul 2024 01:06:00 +0100
Subject: [PATCH 23/26] locale now does matching against supported
---
examples/use_locale/src/main.rs | 2 +-
src/use_locale.rs | 87 +++++++++++++++++----------------
src/use_locales.rs | 2 +-
3 files changed, 47 insertions(+), 44 deletions(-)
diff --git a/examples/use_locale/src/main.rs b/examples/use_locale/src/main.rs
index 36ed437..36e132c 100644
--- a/examples/use_locale/src/main.rs
+++ b/examples/use_locale/src/main.rs
@@ -4,7 +4,7 @@ use leptos_use::use_locale;
#[component]
fn Demo() -> impl IntoView {
- let locale = use_locale();
+ let locale = use_locale(["en", "de", "fr"]);
view! {
Locale: {locale}
diff --git a/src/use_locale.rs b/src/use_locale.rs
index 6e55a37..ebf5423 100644
--- a/src/use_locale.rs
+++ b/src/use_locale.rs
@@ -1,14 +1,14 @@
-use crate::utils::get_header;
use crate::{use_locales_with_options, UseLocalesOptions};
-use default_struct_builder::DefaultBuilder;
use leptos::*;
-use std::rc::Rc;
-/// Reactive locale.
+/// Reactive locale matching.
///
-/// This is basically the same as [`fn@crate::use_locales`] but takes the first entry of the list.
-/// If no locale is found then [`crate::UseLocaleOptions::fallback`] is returned which defaults
-/// to `"en"`.
+/// 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
///
@@ -22,7 +22,7 @@ use std::rc::Rc;
/// #
/// # #[component]
/// # fn Demo() -> impl IntoView {
-/// let locale = use_locale();
+/// let locale = use_locale(&["en".to_string(), "de".to_string(), "fr".to_string()]);
/// #
/// # view! { }
/// # }
@@ -31,44 +31,47 @@ use std::rc::Rc;
/// ## Server-Side Rendering
///
/// See [`fn@crate::use_locales`]
-
-pub fn use_locale() -> Signal {
- use_locale_with_options(UseLocaleOptions::default())
+pub fn use_locale(supported: S) -> Signal
+where
+ S: IntoIterator,
+ S::Item: Into + 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(options: UseLocaleOptions) -> Signal {
- let UseLocaleOptions {
- fallback,
- ssr_lang_header_getter,
- } = options;
+pub fn use_locale_with_options(supported: S, options: UseLocaleOptions) -> Signal
+where
+ S: IntoIterator,
+ S::Item: Into + Clone + 'static,
+{
+ let locales = use_locales_with_options(options);
- let locales = use_locales_with_options(UseLocalesOptions {
- ssr_lang_header_getter,
- });
+ let supported = supported.into_iter().collect::>();
- Signal::derive(move || locales.get().first().cloned().unwrap_or(fallback.clone()))
+ 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())
+ })
+ })
}
-/// Options for [`fn@crate::use_locale_with_options`].
-#[derive(DefaultBuilder)]
-pub struct UseLocaleOptions {
- /// Fallback value in case no locale is found. Defaults to `"en"`.
- fallback: String,
-
- /// 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 Option>,
-}
-
-impl Default for UseLocaleOptions {
- fn default() -> Self {
- Self {
- fallback: "en".to_string(),
- ssr_lang_header_getter: Rc::new(move || {
- get_header!(ACCEPT_LANGUAGE, use_locale, ssr_lang_header_getter)
- }),
- }
- }
-}
+pub type UseLocaleOptions = UseLocalesOptions;
diff --git a/src/use_locales.rs b/src/use_locales.rs
index 98f7e73..4e4f567 100644
--- a/src/use_locales.rs
+++ b/src/use_locales.rs
@@ -100,7 +100,7 @@ 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)]
- pub(crate) ssr_lang_header_getter: Rc Option>,
+ ssr_lang_header_getter: Rc Option>,
}
impl Default for UseLocalesOptions {
From 5b8cfd4449a0af092d43ed04b666b041d3aa60f0 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Mon, 29 Jul 2024 01:09:24 +0100
Subject: [PATCH 24/26] fixed tests
---
src/use_locale.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/use_locale.rs b/src/use_locale.rs
index ebf5423..7b31825 100644
--- a/src/use_locale.rs
+++ b/src/use_locale.rs
@@ -22,7 +22,7 @@ use leptos::*;
/// #
/// # #[component]
/// # fn Demo() -> impl IntoView {
-/// let locale = use_locale(&["en".to_string(), "de".to_string(), "fr".to_string()]);
+/// let locale = use_locale(["en", "de", "fr"]);
/// #
/// # view! { }
/// # }
From f0d60e5d49c89087ece080197f5f90a5db646a98 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Tue, 30 Jul 2024 12:49:24 +0100
Subject: [PATCH 25/26] release 0.11.2
---
CHANGELOG.md | 8 +++++++-
Cargo.toml | 2 +-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 33a9f73..43a5e4c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,13 @@
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).
-## [0.11.1] - 2024-07-28
+## [0.11.2] - 2024-07-30
+
+### Change 🔥
+
+- `use_locale` has now a supported locale list.
+
+## (yanked) [0.11.1] - 2024-07-28
### New Functions 🚀
diff --git a/Cargo.toml b/Cargo.toml
index 7ac4ef7..1201482 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "leptos-use"
-version = "0.11.1"
+version = "0.11.2"
edition = "2021"
authors = ["Marc-Stefan Cassola"]
categories = ["gui", "web-programming"]
From da56771900a2362e266243d81478c7fa5c158b14 Mon Sep 17 00:00:00 2001
From: Maccesch
Date: Wed, 31 Jul 2024 01:15:20 +0100
Subject: [PATCH 26/26] fixed use_timeout_fn to be SSR safe
---
CHANGELOG.md | 6 +++
Cargo.toml | 2 +-
src/use_timeout_fn.rs | 116 +++++++++++++++++++++++++-----------------
3 files changed, 76 insertions(+), 48 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 43a5e4c..20fe0dc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,12 @@
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).
+## [0.11.3] - 2024-07-31
+
+### Fix 🍕
+
+- Made `use_timeout_fn` SSR-safe
+
## [0.11.2] - 2024-07-30
### Change 🔥
diff --git a/Cargo.toml b/Cargo.toml
index 1201482..24e568a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "leptos-use"
-version = "0.11.2"
+version = "0.11.3"
edition = "2021"
authors = ["Marc-Stefan Cassola"]
categories = ["gui", "web-programming"]
diff --git a/src/use_timeout_fn.rs b/src/use_timeout_fn.rs
index 7ae644b..2e3d27f 100644
--- a/src/use_timeout_fn.rs
+++ b/src/use_timeout_fn.rs
@@ -1,9 +1,5 @@
-use leptos::leptos_dom::helpers::TimeoutHandle;
use leptos::*;
-use std::cell::Cell;
use std::marker::PhantomData;
-use std::rc::Rc;
-use std::time::Duration;
/// Wrapper for `setTimeout` with controls.
///
@@ -31,6 +27,11 @@ use std::time::Duration;
/// # 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(
callback: CbFn,
delay: D,
@@ -40,65 +41,86 @@ where
Arg: 'static,
D: Into>,
{
- let delay = delay.into();
-
let (is_pending, set_pending) = create_signal(false);
- let timer = Rc::new(Cell::new(None::));
+ let start;
+ let stop;
- let clear = {
- let timer = Rc::clone(&timer);
+ #[cfg(not(feature = "ssr"))]
+ {
+ use leptos::leptos_dom::helpers::TimeoutHandle;
+ use std::cell::Cell;
+ use std::rc::Rc;
+ use std::time::Duration;
- move || {
- if let Some(timer) = timer.take() {
- timer.clear();
+ let delay = delay.into();
+
+ let timer = Rc::new(Cell::new(None::));
+
+ let clear = {
+ let timer = Rc::clone(&timer);
+
+ move || {
+ if let Some(timer) = timer.take() {
+ timer.clear();
+ }
}
- }
- };
+ };
- let stop = {
- let clear = clear.clone();
+ stop = {
+ let clear = clear.clone();
- move || {
- set_pending.set(false);
- clear();
- }
- };
+ move || {
+ set_pending.set(false);
+ clear();
+ }
+ };
- let start = {
- let timer = Rc::clone(&timer);
- let callback = callback.clone();
+ start = {
+ let timer = Rc::clone(&timer);
+ let callback = callback.clone();
- move |arg: Arg| {
- set_pending.set(true);
+ move |arg: Arg| {
+ set_pending.set(true);
- let handle = set_timeout_with_handle(
- {
- let timer = Rc::clone(&timer);
- let callback = callback.clone();
+ let handle = set_timeout_with_handle(
+ {
+ let timer = Rc::clone(&timer);
+ let callback = callback.clone();
- move || {
- set_pending.set(false);
- timer.set(None);
+ move || {
+ set_pending.set(false);
+ timer.set(None);
- #[cfg(debug_assertions)]
- let prev = SpecialNonReactiveZone::enter();
+ #[cfg(debug_assertions)]
+ let prev = SpecialNonReactiveZone::enter();
- callback(arg);
+ callback(arg);
- #[cfg(debug_assertions)]
- SpecialNonReactiveZone::exit(prev);
- }
- },
- Duration::from_millis(delay.get_untracked() as u64),
- )
- .ok();
+ #[cfg(debug_assertions)]
+ SpecialNonReactiveZone::exit(prev);
+ }
+ },
+ Duration::from_millis(delay.get_untracked() as u64),
+ )
+ .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 {
is_pending: is_pending.into(),