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