diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2553308..933a3ce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,11 +3,15 @@
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]
+## [Unreleased] -
-### Removed 🗑
+### Breaking Changes ðŸ›
+
+- Updated to web_sys 0.3.70 which unfortunately is breaking some things.
+- `use_clipboard` doesn't need the unstable flags anymore.
+- `use_locale` now uses `unic_langid::LanguageIdentifier` and proper locale matching (thanks to @mondeja).
+- Removed `UseMouseEventExtractorDefault` and reworked `UseMouseCoordType` (thanks to @carloskiki)
-- Removed `UseMouseEventExtractorDefault`
## [0.11.4] - 2024-08-12
diff --git a/Cargo.toml b/Cargo.toml
index 870af1a..cf8fd6e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "leptos-use"
-version = "0.11.4"
+version = "0.11.5"
edition = "2021"
authors = ["Marc-Stefan Cassola"]
categories = ["gui", "web-programming"]
@@ -33,11 +33,12 @@ leptos-spin = { version = "0.1", optional = true }
num = { version = "0.4", optional = true }
paste = "1"
thiserror = "1"
-wasm-bindgen = "0.2.92"
+unic-langid = "0.9"
+wasm-bindgen = ">=0.2.93"
wasm-bindgen-futures = "0.4"
[dependencies.web-sys]
-version = "0.3"
+version = ">=0.3.70"
features = [
"AddEventListenerOptions",
"BinaryType",
@@ -129,11 +130,12 @@ features = [
]
[dev-dependencies]
+codee = { version = "0.1", features = ["json_serde", "msgpack_serde", "base64", "prost"] }
getrandom = { version = "0.2", features = ["js"] }
leptos_meta = "0.6"
rand = "0.8"
-codee = { version = "0.1", features = ["json_serde", "msgpack_serde", "base64", "prost"] }
serde = { version = "1", features = ["derive"] }
+unic-langid = { version = "0.9", features = ["macros"] }
[features]
actix = ["dep:actix-web", "dep:leptos_actix", "dep:http0_2"]
diff --git a/examples/use_clipboard/.cargo/config.toml b/examples/use_clipboard/.cargo/config.toml
deleted file mode 100644
index 8467175..0000000
--- a/examples/use_clipboard/.cargo/config.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[build]
-rustflags = ["--cfg=web_sys_unstable_apis"]
diff --git a/examples/use_locale/Cargo.toml b/examples/use_locale/Cargo.toml
index eb1cdfd..1a2555a 100644
--- a/examples/use_locale/Cargo.toml
+++ b/examples/use_locale/Cargo.toml
@@ -9,6 +9,7 @@ console_error_panic_hook = "0.1"
console_log = "1"
log = "0.4"
leptos-use = { path = "../..", features = ["docs"] }
+unic-langid = { version = "0.9", features = ["macros"] }
web-sys = "0.3"
[dev-dependencies]
diff --git a/examples/use_locale/src/main.rs b/examples/use_locale/src/main.rs
index 36e132c..a0fe2a6 100644
--- a/examples/use_locale/src/main.rs
+++ b/examples/use_locale/src/main.rs
@@ -1,13 +1,14 @@
use leptos::*;
use leptos_use::docs::demo_or_body;
use leptos_use::use_locale;
+use unic_langid::langid_slice;
#[component]
fn Demo() -> impl IntoView {
- let locale = use_locale(["en", "de", "fr"]);
+ let locale = use_locale(langid_slice!["en", "de", "fr"]);
view! {
-
Locale: {locale}
+ Locale: {move || locale.get().to_string()}
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 9ad5b9b..efe5187 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -15,11 +15,6 @@ pub mod utils;
// #[cfg(web_sys_unstable_apis)]
// pub use use_webtransport::*;
-#[cfg(web_sys_unstable_apis)]
-mod use_clipboard;
-#[cfg(web_sys_unstable_apis)]
-pub use use_clipboard::*;
-
mod is_err;
mod is_none;
mod is_ok;
@@ -31,6 +26,7 @@ mod sync_signal;
mod use_active_element;
mod use_breakpoints;
mod use_broadcast_channel;
+mod use_clipboard;
mod use_color_mode;
mod use_cookie;
mod use_css_var;
@@ -99,6 +95,7 @@ pub use sync_signal::*;
pub use use_active_element::*;
pub use use_breakpoints::*;
pub use use_broadcast_channel::*;
+pub use use_clipboard::*;
pub use use_color_mode::*;
pub use use_cookie::*;
pub use use_css_var::*;
diff --git a/src/storage/use_storage.rs b/src/storage/use_storage.rs
index 0d8f903..91b56c0 100644
--- a/src/storage/use_storage.rs
+++ b/src/storage/use_storage.rs
@@ -215,8 +215,8 @@ where
queue_microtask(move || {
// TODO : better to use a BroadcastChannel (use_broadcast_channel)?
// Note: we cannot construct a full StorageEvent so we _must_ rely on a custom event
- let mut custom = web_sys::CustomEventInit::new();
- custom.detail(&JsValue::from_str(&key));
+ let custom = web_sys::CustomEventInit::new();
+ custom.set_detail(&JsValue::from_str(&key));
let result = window()
.dispatch_event(
&web_sys::CustomEvent::new_with_event_init_dict(
diff --git a/src/use_clipboard.rs b/src/use_clipboard.rs
index c6f1efe..0bd0e03 100644
--- a/src/use_clipboard.rs
+++ b/src/use_clipboard.rs
@@ -10,9 +10,6 @@ use leptos::*;
/// [Permissions API](https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API).
/// 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).
-///
/// ## Demo
///
/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_clipboard)
@@ -79,10 +76,9 @@ pub fn use_clipboard_with_options(
let update_text = move |_| {
if is_supported.get() {
spawn_local(async move {
- if let Some(clipboard) = window().navigator().clipboard() {
- if let Ok(text) = js_fut!(clipboard.read_text()).await {
- set_text.set(text.as_string());
- }
+ let clipboard = window().navigator().clipboard();
+ if let Ok(text) = js_fut!(clipboard.read_text()).await {
+ set_text.set(text.as_string());
}
})
}
@@ -102,12 +98,11 @@ pub fn use_clipboard_with_options(
let value = value.to_owned();
spawn_local(async move {
- if let Some(clipboard) = window().navigator().clipboard() {
- if js_fut!(clipboard.write_text(&value)).await.is_ok() {
- set_text.set(Some(value));
- set_copied.set(true);
- start(());
- }
+ let clipboard = window().navigator().clipboard();
+ if js_fut!(clipboard.write_text(&value)).await.is_ok() {
+ set_text.set(Some(value));
+ set_copied.set(true);
+ start(());
}
});
}
diff --git a/src/use_display_media.rs b/src/use_display_media.rs
index 8174fba..a89d9c2 100644
--- a/src/use_display_media.rs
+++ b/src/use_display_media.rs
@@ -131,9 +131,9 @@ async fn create_media(audio: bool) -> Result {
.ok_or_else(|| JsValue::from_str("Failed to access window.navigator"))
.and_then(|n| n.media_devices())?;
- let mut constraints = web_sys::DisplayMediaStreamConstraints::new();
+ let constraints = web_sys::DisplayMediaStreamConstraints::new();
if audio {
- constraints.audio(&JsValue::from(true));
+ constraints.set_audio(&JsValue::from(true));
}
let promise = media.get_display_media_with_constraints(&constraints)?;
diff --git a/src/use_event_listener.rs b/src/use_event_listener.rs
index 68ff33d..8f35a51 100644
--- a/src/use_event_listener.rs
+++ b/src/use_event_listener.rs
@@ -235,11 +235,11 @@ impl UseEventListenerOptions {
passive,
} = self;
- let mut options = web_sys::AddEventListenerOptions::new();
- options.capture(*capture);
- options.once(*once);
+ let options = web_sys::AddEventListenerOptions::new();
+ options.set_capture(*capture);
+ options.set_once(*once);
if let Some(passive) = passive {
- options.passive(*passive);
+ options.set_passive(*passive);
}
options
diff --git a/src/use_event_source.rs b/src/use_event_source.rs
index 7cf049b..09539e7 100644
--- a/src/use_event_source.rs
+++ b/src/use_event_source.rs
@@ -183,8 +183,8 @@ where
return;
}
- let mut event_src_opts = web_sys::EventSourceInit::new();
- event_src_opts.with_credentials(with_credentials);
+ let event_src_opts = web_sys::EventSourceInit::new();
+ event_src_opts.set_with_credentials(with_credentials);
let es = web_sys::EventSource::new_with_event_source_init_dict(&url, &event_src_opts)
.unwrap_throw();
diff --git a/src/use_geolocation.rs b/src/use_geolocation.rs
index 2aeda83..7494ef3 100644
--- a/src/use_geolocation.rs
+++ b/src/use_geolocation.rs
@@ -186,10 +186,10 @@ impl UseGeolocationOptions {
..
} = self;
- let mut options = web_sys::PositionOptions::new();
- options.enable_high_accuracy(*enable_high_accuracy);
- options.maximum_age(*maximum_age);
- options.timeout(*timeout);
+ let options = web_sys::PositionOptions::new();
+ options.set_enable_high_accuracy(*enable_high_accuracy);
+ options.set_maximum_age(*maximum_age);
+ options.set_timeout(*timeout);
options
}
diff --git a/src/use_intersection_observer.rs b/src/use_intersection_observer.rs
index cca3343..f17f1f3 100644
--- a/src/use_intersection_observer.rs
+++ b/src/use_intersection_observer.rs
@@ -154,8 +154,9 @@ where
return;
}
- let mut options = web_sys::IntersectionObserverInit::new();
- options.root_margin(&root_margin).threshold(
+ let options = web_sys::IntersectionObserverInit::new();
+ options.set_root_margin(&root_margin);
+ options.set_threshold(
&thresholds
.iter()
.copied()
@@ -165,7 +166,7 @@ where
if let Some(Some(root)) = root {
let root: web_sys::Element = root.clone().into();
- options.root(Some(&root));
+ options.set_root(Some(&root));
}
let obs = web_sys::IntersectionObserver::new_with_options(
diff --git a/src/use_locale.rs b/src/use_locale.rs
index 7b31825..be781a4 100644
--- a/src/use_locale.rs
+++ b/src/use_locale.rs
@@ -1,14 +1,16 @@
use crate::{use_locales_with_options, UseLocalesOptions};
use leptos::*;
+use unic_langid::LanguageIdentifier;
/// Reactive locale matching.
///
/// Returns the first matching locale given by [`fn@crate::use_locales`] that is also found in
/// the `supported` list. In case there is no match, then the first locale in `supported` will be
-/// returned. If `supported` is empty, the empty string is returned.
+/// 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.
+/// > If `supported` is empty, this function will panic!
+///
+/// Matching is done by using the [`fn@unic_langid::LanguageIdentifier::matches`] method.
///
/// ## Demo
///
@@ -19,10 +21,11 @@ use leptos::*;
/// ```
/// # use leptos::*;
/// # use leptos_use::use_locale;
+/// use unic_langid::langid_slice;
/// #
/// # #[component]
/// # fn Demo() -> impl IntoView {
-/// let locale = use_locale(["en", "de", "fr"]);
+/// let locale = use_locale(langid_slice!["en", "de", "fr"]);
/// #
/// # view! { }
/// # }
@@ -31,45 +34,55 @@ use leptos::*;
/// ## Server-Side Rendering
///
/// See [`fn@crate::use_locales`]
-pub fn use_locale(supported: S) -> Signal
+pub fn use_locale(supported: S) -> Signal
where
S: IntoIterator,
- S::Item: Into + Clone + 'static,
+ S::Item: AsRef,
{
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(supported: S, options: UseLocaleOptions) -> Signal
+pub fn use_locale_with_options(
+ supported: S,
+ options: UseLocaleOptions,
+) -> Signal
where
S: IntoIterator,
- S::Item: Into + Clone + 'static,
+ S::Item: AsRef,
{
- let locales = use_locales_with_options(options);
+ let client_locales = use_locales_with_options(options);
- let supported = supported.into_iter().collect::>();
+ let supported = supported
+ .into_iter()
+ .map(|l| l.as_ref().clone())
+ .collect::>();
+
+ const EMPTY_ERR_MSG: &'static str = "Empty supported list. You have to provide at least one locale in the `supported` parameter";
+ assert!(supported.len() > 0, "{}", EMPTY_ERR_MSG);
Signal::derive(move || {
let supported = supported.clone();
- locales.with(|locales| {
+ client_locales.with(|clienht_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) {
+ for client_locale in clienht_locales {
+ let client_locale: LanguageIdentifier = client_locale
+ .parse()
+ .expect("Client should provide a list of valid unicode locales");
+ if client_locale.matches(&s, true, true) {
return s;
}
}
}
- first_supported.unwrap_or_else(|| "".to_string())
+ unreachable!("{}", EMPTY_ERR_MSG);
})
})
}
diff --git a/src/use_mutation_observer.rs b/src/use_mutation_observer.rs
index c165c09..813ce4f 100644
--- a/src/use_mutation_observer.rs
+++ b/src/use_mutation_observer.rs
@@ -214,20 +214,20 @@ impl From for web_sys::MutationObserverInit {
character_data_old_value,
} = val;
- let mut init = Self::new();
+ let init = Self::new();
- init.subtree(subtree)
- .child_list(child_list)
- .attributes(attributes)
- .attribute_old_value(attribute_old_value)
- .character_data_old_value(character_data_old_value);
+ init.set_subtree(subtree);
+ init.set_child_list(child_list);
+ init.set_attributes(attributes);
+ init.set_attribute_old_value(attribute_old_value);
+ init.set_character_data_old_value(character_data_old_value);
if let Some(attribute_filter) = attribute_filter {
let array = js_sys::Array::from_iter(attribute_filter.into_iter().map(JsValue::from));
- init.attribute_filter(array.unchecked_ref());
+ init.set_attribute_filter(array.unchecked_ref());
}
if let Some(character_data) = character_data {
- init.character_data(character_data);
+ init.set_character_data(character_data);
}
init
diff --git a/src/use_resize_observer.rs b/src/use_resize_observer.rs
index 3a631ca..154f3c2 100644
--- a/src/use_resize_observer.rs
+++ b/src/use_resize_observer.rs
@@ -171,8 +171,8 @@ pub struct UseResizeObserverOptions {
impl From for web_sys::ResizeObserverOptions {
fn from(val: UseResizeObserverOptions) -> Self {
- let mut options = web_sys::ResizeObserverOptions::new();
- options.box_(
+ let options = web_sys::ResizeObserverOptions::new();
+ options.set_box(
val.box_
.unwrap_or(web_sys::ResizeObserverBoxOptions::ContentBox),
);
diff --git a/src/use_scroll.rs b/src/use_scroll.rs
index 9db4ab1..8c0fc80 100644
--- a/src/use_scroll.rs
+++ b/src/use_scroll.rs
@@ -231,14 +231,14 @@ where
if let Some(element) = element {
let element = element.into();
- let mut scroll_options = web_sys::ScrollToOptions::new();
- scroll_options.behavior(behavior.get_untracked().into());
+ let scroll_options = web_sys::ScrollToOptions::new();
+ scroll_options.set_behavior(behavior.get_untracked().into());
if let Some(x) = x {
- scroll_options.left(x);
+ scroll_options.set_left(x);
}
if let Some(y) = y {
- scroll_options.top(y);
+ scroll_options.set_top(y);
}
element.scroll_to_with_scroll_to_options(&scroll_options);
diff --git a/src/use_user_media.rs b/src/use_user_media.rs
index 2336f38..76b1eed 100644
--- a/src/use_user_media.rs
+++ b/src/use_user_media.rs
@@ -136,12 +136,12 @@ async fn create_media(video: bool, audio: bool) -> Result for web_sys::NotificationOptions {
fn from(options: &UseWebNotificationOptions) -> Self {
- let mut web_sys_options = Self::new();
+ let web_sys_options = Self::new();
- web_sys_options
- .dir(options.direction.into())
- .require_interaction(options.require_interaction)
- .renotify(options.renotify)
- .silent(options.silent);
+ web_sys_options.set_dir(options.direction.into());
+ web_sys_options.set_require_interaction(options.require_interaction);
+ web_sys_options.set_renotify(options.renotify);
+ web_sys_options.set_silent(options.silent);
if let Some(body) = &options.body {
- web_sys_options.body(body);
+ web_sys_options.set_body(body);
}
if let Some(icon) = &options.icon {
- web_sys_options.icon(icon);
+ web_sys_options.set_icon(icon);
}
if let Some(image) = &options.image {
- web_sys_options.image(image);
+ web_sys_options.set_image(image);
}
if let Some(language) = &options.language {
- web_sys_options.lang(language);
+ web_sys_options.set_lang(language);
}
if let Some(tag) = &options.tag {
- web_sys_options.tag(tag);
+ web_sys_options.set_tag(tag);
}
web_sys_options
@@ -415,39 +414,39 @@ pub struct ShowOptions {
impl ShowOptions {
fn override_notification_options(&self, options: &mut web_sys::NotificationOptions) {
if let Some(direction) = self.direction {
- options.dir(direction.into());
+ options.set_dir(direction.into());
}
if let Some(require_interaction) = self.require_interaction {
- options.require_interaction(require_interaction);
+ options.set_require_interaction(require_interaction);
}
if let Some(body) = &self.body {
- options.body(body);
+ options.set_body(body);
}
if let Some(icon) = &self.icon {
- options.icon(icon);
+ options.set_icon(icon);
}
if let Some(image) = &self.image {
- options.image(image);
+ options.set_image(image);
}
if let Some(language) = &self.language {
- options.lang(language);
+ options.set_lang(language);
}
if let Some(tag) = &self.tag {
- options.tag(tag);
+ options.set_tag(tag);
}
if let Some(renotify) = self.renotify {
- options.renotify(renotify);
+ options.set_renotify(renotify);
}
if let Some(silent) = self.silent {
- options.silent(Some(silent));
+ options.set_silent(Some(silent));
}
}
}
@@ -481,7 +480,7 @@ impl From for NotificationPermission {
web_sys::NotificationPermission::Default => Self::Default,
web_sys::NotificationPermission::Granted => Self::Granted,
web_sys::NotificationPermission::Denied => Self::Denied,
- web_sys::NotificationPermission::__Nonexhaustive => Self::Default,
+ _ => Self::Default,
}
}
}