mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-01-22 16:49:22 -05:00
use MaybeRwSignal
where applicable. Fixes #4
This commit is contained in:
parent
6b9a272b12
commit
e55f253e8d
12 changed files with 197 additions and 151 deletions
|
@ -3,7 +3,13 @@
|
|||
{
|
||||
"type": "cargo",
|
||||
"name": "Tests",
|
||||
"cargoArgs": ["test", "--all-features"],
|
||||
"cargoArgs": ["test", "--features", "math,storage,docs"],
|
||||
},
|
||||
{
|
||||
"type": "cargo",
|
||||
"name": "Clippy",
|
||||
"cargoArgs": ["+nightly", "clippy", "--features", "math,storage,docs", "--tests", "--", "-D", "warnings"],
|
||||
"workingDir": "./",
|
||||
},
|
||||
|
||||
]
|
||||
|
|
38
CHANGELOG.md
38
CHANGELOG.md
|
@ -3,7 +3,30 @@
|
|||
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.5.0] - 2023-07-15
|
||||
## [Unreleased] -
|
||||
|
||||
### Braking Changes 🛠
|
||||
|
||||
- The following functions now accept a `MaybeRwSignal` as their initial/default value which means
|
||||
you can use a synchronized `RwSignal` in those places.
|
||||
- `use_color_mode`
|
||||
- `use_cycle_list`
|
||||
- `use_favicon`
|
||||
- `use_storage`
|
||||
- `use_local_storage`
|
||||
- `use_session_storage`
|
||||
- Instead of returning `ReadSignal`, the following functions now return `Signal`.
|
||||
- `use_color_mode`
|
||||
- `use_favicon`
|
||||
- `use_storage`
|
||||
- `use_local_storage`
|
||||
- `use_session_storage`
|
||||
|
||||
### Fixes 🍕
|
||||
|
||||
- `use_drop_zone` now uses `.get_untracked()` in event handlers
|
||||
|
||||
## [0.5.0] - 2023-07-15
|
||||
|
||||
### New Functions 🚀
|
||||
|
||||
|
@ -26,8 +49,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
## [0.4.0] - 2023-07-03
|
||||
|
||||
### Braking Changes 🛠
|
||||
|
||||
- Required `leptos` version is now 0.4
|
||||
- Following the changes in `leptos` there is no longer a `stable` crate feature required in order to use this library with a stable toolchain.
|
||||
- Following the changes in `leptos` there is no longer a `stable` crate feature required in order to use this library
|
||||
with a stable toolchain.
|
||||
If you want to use it with a nightly toolchain you have to enable the `nightly` feature only on `leptos` directly.
|
||||
No change is required for `leptos-use` itself.
|
||||
|
||||
|
@ -61,17 +86,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
## [0.3.0] - 2023-06-13
|
||||
|
||||
### Braking Changes 🛠
|
||||
|
||||
- `use_event_listener` no longer returns a `Box<dyn Fn()>` but a `impl Fn() + Clone`
|
||||
|
||||
### Changes 🔥
|
||||
|
||||
- You can now specify a `&str` or `Signal<String>` with CSS selectors wherever a node ref is accepted
|
||||
- Callbacks of the following functions no longer require `Clone`
|
||||
- `use_resize_observer`
|
||||
- `use_intersection_observer`
|
||||
- `use_resize_observer`
|
||||
- `use_intersection_observer`
|
||||
- These functions now also accept multiple target elements in addition to a single one:
|
||||
- `use_resize_observer`
|
||||
- `use_intersection_observer`
|
||||
- `use_resize_observer`
|
||||
- `use_intersection_observer`
|
||||
|
||||
### New Functions 🚀
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ To run all tests run
|
|||
cargo test --all-features
|
||||
```
|
||||
|
||||
## Book
|
||||
### Book
|
||||
|
||||
First you need to install
|
||||
|
||||
|
|
|
@ -77,14 +77,20 @@ impl From<&str> for MaybeRwSignal<String> {
|
|||
}
|
||||
|
||||
impl<T: Clone> MaybeRwSignal<T> {
|
||||
pub fn to_signal(&self, cx: Scope) -> (Signal<T>, WriteSignal<T>) {
|
||||
pub fn into_signal(self, cx: Scope) -> (Signal<T>, WriteSignal<T>) {
|
||||
match self {
|
||||
Self::DynamicRead(s) => {
|
||||
// TODO : this feels hacky
|
||||
let (_, w) = create_signal(cx, s.get_untracked());
|
||||
(*s, w)
|
||||
let (r, w) = create_signal(cx, s.get_untracked());
|
||||
|
||||
create_effect(cx, move |_| {
|
||||
w.update(move |w| {
|
||||
*w = s.get();
|
||||
});
|
||||
});
|
||||
|
||||
(r.into(), w)
|
||||
}
|
||||
Self::DynamicRw(r, w) => (*r, *w),
|
||||
Self::DynamicRw(r, w) => (r, w),
|
||||
Self::Static(v) => {
|
||||
let (r, w) = create_signal(cx, v.clone());
|
||||
(Signal::from(r), w)
|
||||
|
|
|
@ -15,10 +15,10 @@ macro_rules! use_specific_storage {
|
|||
cx: Scope,
|
||||
key: &str,
|
||||
defaults: D,
|
||||
) -> (ReadSignal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||
where
|
||||
for<'de> T: Serialize + Deserialize<'de> + Clone + 'static,
|
||||
D: Into<MaybeSignal<T>>,
|
||||
D: Into<MaybeRwSignal<T>>,
|
||||
T: Clone,
|
||||
{
|
||||
[<use_ $storage_name _storage_with_options>](cx, key, defaults, UseSpecificStorageOptions::default())
|
||||
|
@ -34,10 +34,10 @@ macro_rules! use_specific_storage {
|
|||
key: &str,
|
||||
defaults: D,
|
||||
options: UseSpecificStorageOptions<T>,
|
||||
) -> (ReadSignal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||
where
|
||||
for<'de> T: Serialize + Deserialize<'de> + Clone + 'static,
|
||||
D: Into<MaybeSignal<T>>,
|
||||
D: Into<MaybeRwSignal<T>>,
|
||||
T: Clone,
|
||||
{
|
||||
use_storage_with_options(cx, key, defaults, options.into_storage_options(StorageType::[<$storage_name:camel>]))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::core::MaybeRwSignal;
|
||||
use crate::storage::shared::{use_specific_storage, UseSpecificStorageOptions};
|
||||
use crate::storage::{use_storage_with_options, StorageType};
|
||||
use leptos::*;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::core::MaybeRwSignal;
|
||||
use crate::storage::shared::{use_specific_storage, UseSpecificStorageOptions};
|
||||
use crate::storage::{use_storage_with_options, StorageType};
|
||||
use leptos::*;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![cfg_attr(feature = "ssr", allow(unused_variables, unused_imports, dead_code))]
|
||||
|
||||
use crate::core::MaybeRwSignal;
|
||||
use crate::utils::{CloneableFn, CloneableFnWithArg, FilterOptions};
|
||||
use crate::{
|
||||
filter_builder_methods, use_event_listener, watch_pausable_with_options, DebounceOptions,
|
||||
|
@ -160,10 +161,10 @@ pub fn use_storage<T, D>(
|
|||
cx: Scope,
|
||||
key: &str,
|
||||
defaults: D,
|
||||
) -> (ReadSignal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||
where
|
||||
for<'de> T: Serialize + Deserialize<'de> + Clone + 'static,
|
||||
D: Into<MaybeSignal<T>>,
|
||||
D: Into<MaybeRwSignal<T>>,
|
||||
T: Clone,
|
||||
{
|
||||
use_storage_with_options(cx, key, defaults, UseStorageOptions::default())
|
||||
|
@ -176,10 +177,10 @@ pub fn use_storage_with_options<T, D>(
|
|||
key: &str,
|
||||
defaults: D,
|
||||
options: UseStorageOptions<T>,
|
||||
) -> (ReadSignal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||
) -> (Signal<T>, WriteSignal<T>, impl Fn() + Clone)
|
||||
where
|
||||
for<'de> T: Serialize + Deserialize<'de> + Clone + 'static,
|
||||
D: Into<MaybeSignal<T>>,
|
||||
D: Into<MaybeRwSignal<T>>,
|
||||
T: Clone,
|
||||
{
|
||||
let defaults = defaults.into();
|
||||
|
@ -193,7 +194,9 @@ where
|
|||
filter,
|
||||
} = options;
|
||||
|
||||
let (data, set_data) = create_signal(cx, defaults.get_untracked());
|
||||
let (data, set_data) = defaults.into_signal(cx);
|
||||
|
||||
let raw_init = data.get();
|
||||
|
||||
cfg_if! { if #[cfg(feature = "ssr")] {
|
||||
let remove: Box<dyn CloneableFn> = Box::new(|| {});
|
||||
|
@ -202,101 +205,102 @@ where
|
|||
|
||||
let remove: Box<dyn CloneableFn> = match storage {
|
||||
Ok(Some(storage)) => {
|
||||
let on_err = on_error.clone();
|
||||
let write = {
|
||||
let on_error = on_error.clone();
|
||||
let storage = storage.clone();
|
||||
let key = key.to_string();
|
||||
|
||||
let store = storage.clone();
|
||||
let k = key.to_string();
|
||||
move |v: &T| {
|
||||
match serde_json::to_string(&v) {
|
||||
Ok(ref serialized) => match storage.get_item(&key) {
|
||||
Ok(old_value) => {
|
||||
if old_value.as_ref() != Some(serialized) {
|
||||
if let Err(e) = storage.set_item(&key, serialized) {
|
||||
on_error(UseStorageError::StorageAccessError(e));
|
||||
} else {
|
||||
let mut event_init = web_sys::CustomEventInit::new();
|
||||
event_init.detail(
|
||||
&StorageEventDetail {
|
||||
key: Some(key.clone()),
|
||||
old_value,
|
||||
new_value: Some(serialized.clone()),
|
||||
storage_area: Some(storage.clone()),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
|
||||
let write = move |v: &T| {
|
||||
match serde_json::to_string(&v) {
|
||||
Ok(ref serialized) => match store.get_item(&k) {
|
||||
Ok(old_value) => {
|
||||
if old_value.as_ref() != Some(serialized) {
|
||||
if let Err(e) = store.set_item(&k, serialized) {
|
||||
on_err(UseStorageError::StorageAccessError(e));
|
||||
} else {
|
||||
let mut event_init = web_sys::CustomEventInit::new();
|
||||
event_init.detail(
|
||||
&StorageEventDetail {
|
||||
key: Some(k.clone()),
|
||||
old_value,
|
||||
new_value: Some(serialized.clone()),
|
||||
storage_area: Some(store.clone()),
|
||||
}
|
||||
.into(),
|
||||
);
|
||||
|
||||
// importantly this should _not_ be a StorageEvent since those cannot
|
||||
// be constructed with a non-built-in storage area
|
||||
let _ = window().dispatch_event(
|
||||
&web_sys::CustomEvent::new_with_event_init_dict(
|
||||
CUSTOM_STORAGE_EVENT_NAME,
|
||||
&event_init,
|
||||
)
|
||||
.expect("Failed to create CustomEvent"),
|
||||
);
|
||||
// importantly this should _not_ be a StorageEvent since those cannot
|
||||
// be constructed with a non-built-in storage area
|
||||
let _ = window().dispatch_event(
|
||||
&web_sys::CustomEvent::new_with_event_init_dict(
|
||||
CUSTOM_STORAGE_EVENT_NAME,
|
||||
&event_init,
|
||||
)
|
||||
.expect("Failed to create CustomEvent"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
on_error.clone()(UseStorageError::StorageAccessError(e));
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
on_err.clone()(UseStorageError::StorageAccessError(e));
|
||||
on_error.clone()(UseStorageError::SerializationError(e));
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
on_err.clone()(UseStorageError::SerializationError(e));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let store = storage.clone();
|
||||
let on_err = on_error.clone();
|
||||
let k = key.to_string();
|
||||
let def = defaults.clone();
|
||||
let read = {
|
||||
let storage = storage.clone();
|
||||
let on_error = on_error.clone();
|
||||
let key = key.to_string();
|
||||
let raw_init = raw_init.clone();
|
||||
|
||||
let read = move |event_detail: Option<StorageEventDetail>| -> Option<T> {
|
||||
let raw_init = match serde_json::to_string(&def.get_untracked()) {
|
||||
Ok(serialized) => Some(serialized),
|
||||
Err(e) => {
|
||||
on_err.clone()(UseStorageError::DefaultSerializationError(e));
|
||||
None
|
||||
}
|
||||
};
|
||||
move |event_detail: Option<StorageEventDetail>| -> Option<T> {
|
||||
let serialized_init = match serde_json::to_string(&raw_init) {
|
||||
Ok(serialized) => Some(serialized),
|
||||
Err(e) => {
|
||||
on_error.clone()(UseStorageError::DefaultSerializationError(e));
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let raw_value = if let Some(event_detail) = event_detail {
|
||||
event_detail.new_value
|
||||
} else {
|
||||
match store.get_item(&k) {
|
||||
Ok(raw_value) => match raw_value {
|
||||
Some(raw_value) => {
|
||||
Some(merge_defaults(&raw_value, &def.get_untracked()))
|
||||
let raw_value = if let Some(event_detail) = event_detail {
|
||||
event_detail.new_value
|
||||
} else {
|
||||
match storage.get_item(&key) {
|
||||
Ok(raw_value) => match raw_value {
|
||||
Some(raw_value) => Some(merge_defaults(&raw_value, &raw_init)),
|
||||
None => serialized_init.clone(),
|
||||
},
|
||||
Err(e) => {
|
||||
on_error.clone()(UseStorageError::StorageAccessError(e));
|
||||
None
|
||||
}
|
||||
None => raw_init.clone(),
|
||||
},
|
||||
Err(e) => {
|
||||
on_err.clone()(UseStorageError::StorageAccessError(e));
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
match raw_value {
|
||||
Some(raw_value) => match serde_json::from_str(&raw_value) {
|
||||
Ok(v) => Some(v),
|
||||
Err(e) => {
|
||||
on_err.clone()(UseStorageError::SerializationError(e));
|
||||
None
|
||||
}
|
||||
},
|
||||
None => {
|
||||
if let Some(raw_init) = &raw_init {
|
||||
if write_defaults {
|
||||
if let Err(e) = store.set_item(&k, raw_init) {
|
||||
on_err(UseStorageError::StorageAccessError(e));
|
||||
match raw_value {
|
||||
Some(raw_value) => match serde_json::from_str(&raw_value) {
|
||||
Ok(v) => Some(v),
|
||||
Err(e) => {
|
||||
on_error.clone()(UseStorageError::SerializationError(e));
|
||||
None
|
||||
}
|
||||
},
|
||||
None => {
|
||||
if let Some(serialized_init) = &serialized_init {
|
||||
if write_defaults {
|
||||
if let Err(e) = storage.set_item(&key, serialized_init) {
|
||||
on_error(UseStorageError::StorageAccessError(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(def.get_untracked())
|
||||
Some(raw_init)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -312,40 +316,43 @@ where
|
|||
WatchOptions::default().filter(filter),
|
||||
);
|
||||
|
||||
let k = key.to_string();
|
||||
let store = storage.clone();
|
||||
let update = {
|
||||
let key = key.to_string();
|
||||
let storage = storage.clone();
|
||||
let raw_init = raw_init.clone();
|
||||
|
||||
let update = move |event_detail: Option<StorageEventDetail>| {
|
||||
if let Some(event_detail) = &event_detail {
|
||||
if event_detail.storage_area != Some(store) {
|
||||
return;
|
||||
}
|
||||
|
||||
match &event_detail.key {
|
||||
None => {
|
||||
set_data.set(defaults.get_untracked());
|
||||
move |event_detail: Option<StorageEventDetail>| {
|
||||
if let Some(event_detail) = &event_detail {
|
||||
if event_detail.storage_area != Some(storage) {
|
||||
return;
|
||||
}
|
||||
Some(event_key) => {
|
||||
if event_key != &k {
|
||||
|
||||
match &event_detail.key {
|
||||
None => {
|
||||
set_data.set(raw_init);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
Some(event_key) => {
|
||||
if event_key != &key {
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pause_watch();
|
||||
pause_watch();
|
||||
|
||||
if let Some(value) = read(event_detail.clone()) {
|
||||
set_data.set(value);
|
||||
}
|
||||
if let Some(value) = read(event_detail.clone()) {
|
||||
set_data.set(value);
|
||||
}
|
||||
|
||||
if event_detail.is_some() {
|
||||
// use timeout to avoid inifinite loop
|
||||
let resume = resume_watch.clone();
|
||||
let _ = set_timeout_with_handle(resume, Duration::ZERO);
|
||||
} else {
|
||||
resume_watch();
|
||||
if event_detail.is_some() {
|
||||
// use timeout to avoid inifinite loop
|
||||
let resume = resume_watch.clone();
|
||||
let _ = set_timeout_with_handle(resume, Duration::ZERO);
|
||||
} else {
|
||||
resume_watch();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::core::ElementMaybeSignal;
|
||||
use crate::core::{ElementMaybeSignal, MaybeRwSignal};
|
||||
#[cfg(feature = "storage")]
|
||||
use crate::storage::{use_storage_with_options, UseStorageOptions};
|
||||
#[cfg(feature = "storage")]
|
||||
|
@ -248,7 +248,7 @@ where
|
|||
UseColorModeReturn {
|
||||
mode,
|
||||
set_mode: set_store,
|
||||
store: store.into(),
|
||||
store,
|
||||
set_store,
|
||||
system,
|
||||
state,
|
||||
|
@ -269,20 +269,21 @@ pub enum ColorMode {
|
|||
cfg_if! { if #[cfg(feature = "storage")] {
|
||||
fn get_store_signal(
|
||||
cx: Scope,
|
||||
initial_value: MaybeSignal<ColorMode>,
|
||||
initial_value: MaybeRwSignal<ColorMode>,
|
||||
storage_signal: Option<RwSignal<ColorMode>>,
|
||||
storage_key: &str,
|
||||
storage_enabled: bool,
|
||||
storage: StorageType,
|
||||
listen_to_storage_changes: bool,
|
||||
) -> (ReadSignal<ColorMode>, WriteSignal<ColorMode>) {
|
||||
) -> (Signal<ColorMode>, WriteSignal<ColorMode>) {
|
||||
if let Some(storage_signal) = storage_signal {
|
||||
storage_signal.split()
|
||||
let (store, set_store) = storage_signal.split();
|
||||
(store.into(), set_store)
|
||||
} else if storage_enabled {
|
||||
let (store, set_store, _) = use_storage_with_options(
|
||||
cx,
|
||||
storage_key,
|
||||
initial_value.get_untracked(),
|
||||
initial_value,
|
||||
UseStorageOptions::default()
|
||||
.listen_to_storage_changes(listen_to_storage_changes)
|
||||
.storage_type(storage),
|
||||
|
@ -290,23 +291,24 @@ cfg_if! { if #[cfg(feature = "storage")] {
|
|||
|
||||
(store, set_store)
|
||||
} else {
|
||||
create_signal(cx, initial_value.get_untracked())
|
||||
initial_value.into_signal(cx)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fn get_store_signal(
|
||||
cx: Scope,
|
||||
initial_value: MaybeSignal<ColorMode>,
|
||||
initial_value: MaybeRwSignal<ColorMode>,
|
||||
storage_signal: Option<RwSignal<ColorMode>>,
|
||||
_storage_key: &String,
|
||||
_storage_enabled: bool,
|
||||
_storage: StorageType,
|
||||
_listen_to_storage_changes: bool,
|
||||
) -> (ReadSignal<ColorMode>, WriteSignal<ColorMode>) {
|
||||
) -> (Signal<ColorMode>, WriteSignal<ColorMode>) {
|
||||
if let Some(storage_signal) = storage_signal {
|
||||
storage_signal.split()
|
||||
let (store, set_store) = storage_signal.split();
|
||||
(store.into(), set_store)
|
||||
} else {
|
||||
create_signal(cx, initial_value.get_untracked())
|
||||
initial_value.into_signal(cx)
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
@ -368,7 +370,7 @@ where
|
|||
|
||||
/// Initial value of the color mode. Defaults to `"Auto"`.
|
||||
#[builder(into)]
|
||||
initial_value: MaybeSignal<ColorMode>,
|
||||
initial_value: MaybeRwSignal<ColorMode>,
|
||||
|
||||
/// Custom modes that you plan to use as `ColorMode::Custom(x)`. Defaults to `vec![]`.
|
||||
custom_modes: Vec<String>,
|
||||
|
|
|
@ -84,7 +84,7 @@ where
|
|||
}
|
||||
};
|
||||
|
||||
let (state, set_state) = get_initial_value().to_signal(cx);
|
||||
let (state, set_state) = get_initial_value().into_signal(cx);
|
||||
|
||||
let index = {
|
||||
let list = list.clone();
|
||||
|
|
|
@ -100,7 +100,7 @@ where
|
|||
update_files(&event);
|
||||
|
||||
on_enter(UseDropZoneEvent {
|
||||
files: files.get(),
|
||||
files: files.get_untracked(),
|
||||
event,
|
||||
});
|
||||
});
|
||||
|
@ -109,7 +109,7 @@ where
|
|||
event.prevent_default();
|
||||
update_files(&event);
|
||||
on_over(UseDropZoneEvent {
|
||||
files: files.get(),
|
||||
files: files.get_untracked(),
|
||||
event,
|
||||
});
|
||||
});
|
||||
|
@ -124,7 +124,7 @@ where
|
|||
update_files(&event);
|
||||
|
||||
on_leave(UseDropZoneEvent {
|
||||
files: files.get(),
|
||||
files: files.get_untracked(),
|
||||
event,
|
||||
});
|
||||
});
|
||||
|
@ -137,7 +137,7 @@ where
|
|||
update_files(&event);
|
||||
|
||||
on_drop(UseDropZoneEvent {
|
||||
files: files.get(),
|
||||
files: files.get_untracked(),
|
||||
event,
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![cfg_attr(feature = "ssr", allow(unused_variables, unused_imports))]
|
||||
|
||||
use crate::core::MaybeRwSignal;
|
||||
use crate::watch;
|
||||
use cfg_if::cfg_if;
|
||||
use default_struct_builder::DefaultBuilder;
|
||||
|
@ -59,7 +60,7 @@ use wasm_bindgen::JsCast;
|
|||
/// ## Server-Side Rendering
|
||||
///
|
||||
/// On the server only the signals work but no favicon will be changed obviously.
|
||||
pub fn use_favicon(cx: Scope) -> (ReadSignal<Option<String>>, WriteSignal<Option<String>>) {
|
||||
pub fn use_favicon(cx: Scope) -> (Signal<Option<String>>, WriteSignal<Option<String>>) {
|
||||
use_favicon_with_options(cx, UseFaviconOptions::default())
|
||||
}
|
||||
|
||||
|
@ -67,18 +68,14 @@ pub fn use_favicon(cx: Scope) -> (ReadSignal<Option<String>>, WriteSignal<Option
|
|||
pub fn use_favicon_with_options(
|
||||
cx: Scope,
|
||||
options: UseFaviconOptions,
|
||||
) -> (ReadSignal<Option<String>>, WriteSignal<Option<String>>) {
|
||||
) -> (Signal<Option<String>>, WriteSignal<Option<String>>) {
|
||||
let UseFaviconOptions {
|
||||
new_icon,
|
||||
base_url,
|
||||
rel,
|
||||
} = options;
|
||||
|
||||
let (favicon, set_favicon) = create_signal(cx, new_icon.get_untracked());
|
||||
|
||||
if matches!(&new_icon, MaybeSignal::Dynamic(_)) {
|
||||
create_effect(cx, move |_| set_favicon.set(new_icon.get()));
|
||||
}
|
||||
let (favicon, set_favicon) = new_icon.into_signal(cx);
|
||||
|
||||
cfg_if! { if #[cfg(not(feature = "ssr"))] {
|
||||
let link_selector = format!("link[rel*=\"{rel}\"]");
|
||||
|
@ -116,9 +113,9 @@ pub fn use_favicon_with_options(
|
|||
/// Options for [`use_favicon_with_options`].
|
||||
#[derive(DefaultBuilder)]
|
||||
pub struct UseFaviconOptions {
|
||||
/// New input favicon. Can be a `Signal` in which case updates will change the favicon. Defaults to None.
|
||||
/// New input favicon. Can be a `RwSignal` in which case updates will change the favicon. Defaults to None.
|
||||
#[builder(into)]
|
||||
new_icon: MaybeSignal<Option<String>>,
|
||||
new_icon: MaybeRwSignal<Option<String>>,
|
||||
|
||||
/// Base URL of the favicon. Defaults to "".
|
||||
#[builder(into)]
|
||||
|
|
Loading…
Add table
Reference in a new issue