mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-01-23 00:59:22 -05:00
finished new functions and release
This commit is contained in:
parent
fadfcab1c1
commit
4999313f32
15 changed files with 116 additions and 242 deletions
|
@ -1,3 +1,3 @@
|
||||||
[build]
|
[unstable]
|
||||||
rustflags = ["--cfg=web_sys_unstable_apis"]
|
rustflags = ["--cfg=web_sys_unstable_apis"]
|
||||||
rustdocflags = ["--cfg=web_sys_unstable_apis"]
|
rustdocflags = ["--cfg=web_sys_unstable_apis"]
|
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -3,6 +3,19 @@
|
||||||
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).
|
||||||
|
|
||||||
|
## [0.3.3] - 2023-06-24
|
||||||
|
|
||||||
|
### New Functions 🚀
|
||||||
|
|
||||||
|
- `use_color_mode`
|
||||||
|
- `use_cycle_list`
|
||||||
|
- `use_active_element`
|
||||||
|
|
||||||
|
### Changes 🔥
|
||||||
|
|
||||||
|
- You can now use this crate with the `stable` toolchain (thanks @lpotthast)
|
||||||
|
- Set leptos dependency to `default-features = false` in order to enable SSR.
|
||||||
|
|
||||||
## [0.3.2] - 2023-06-17
|
## [0.3.2] - 2023-06-17
|
||||||
|
|
||||||
### New Functions 🚀
|
### New Functions 🚀
|
||||||
|
|
11
Cargo.toml
11
Cargo.toml
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "leptos-use"
|
name = "leptos-use"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Marc-Stefan Cassola"]
|
authors = ["Marc-Stefan Cassola"]
|
||||||
categories = ["gui", "web-programming"]
|
categories = ["gui", "web-programming"]
|
||||||
|
@ -16,7 +16,7 @@ homepage = "https://leptos-use.rs"
|
||||||
leptos = { version = "0.3", default-features = false }
|
leptos = { version = "0.3", default-features = false }
|
||||||
wasm-bindgen = "0.2"
|
wasm-bindgen = "0.2"
|
||||||
js-sys = "0.3"
|
js-sys = "0.3"
|
||||||
default-struct-builder = { path = "../default-struct-builder" }
|
default-struct-builder = "0.3"
|
||||||
num = { version = "0.4", optional = true }
|
num = { version = "0.4", optional = true }
|
||||||
serde = { version = "1", optional = true }
|
serde = { version = "1", optional = true }
|
||||||
serde_json = { version = "1", optional = true }
|
serde_json = { version = "1", optional = true }
|
||||||
|
@ -64,7 +64,10 @@ math = ["num"]
|
||||||
storage = ["serde", "serde_json", "web-sys/StorageEvent"]
|
storage = ["serde", "serde_json", "web-sys/StorageEvent"]
|
||||||
stable = ["leptos/stable"]
|
stable = ["leptos/stable"]
|
||||||
|
|
||||||
[package.metadata."docs.rs"]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg=web_sys_unstable_apis"]
|
rustdoc-args = ["--cfg=web_sys_unstable_apis"]
|
||||||
rustc-args = ["--cfg=web_sys_unstable_apis"]
|
rustc-args = ["--cfg=web_sys_unstable_apis"]
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
leptos = "0.3"
|
|
@ -12,7 +12,7 @@
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
|
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
|
||||||
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
|
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
|
||||||
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-35%20functions-%23EF3939" alt="35 Functions" /></a>
|
<a href="https://leptos-use.rs"><img src="https://img.shields.io/badge/-38%20functions-%23EF3939" alt="38 Functions" /></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
|
@ -64,6 +64,9 @@ def main():
|
||||||
|
|
||||||
print(line)
|
print(line)
|
||||||
|
|
||||||
|
elif re.match(r"^//\s?#\[doc\(cfg\(.+?\)\)]", stripped_line):
|
||||||
|
pass
|
||||||
|
|
||||||
elif doc_comment_started:
|
elif doc_comment_started:
|
||||||
initial_doc_finished = True
|
initial_doc_finished = True
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,6 @@
|
||||||
<p>
|
<p>
|
||||||
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
|
<a href="https://crates.io/crates/leptos-use"><img src="https://img.shields.io/crates/v/leptos-use.svg?label=&color=%232C1275" alt="Crates.io"/></a>
|
||||||
<a href="./get_started.html"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
|
<a href="./get_started.html"><img src="https://img.shields.io/badge/-docs%20%26%20demos-%239A233F" alt="Docs & Demos"></a>
|
||||||
<a href="./functions.html"><img src="https://img.shields.io/badge/-35%20functions-%23EF3939" alt="35 Functions" /></a>
|
<a href="./functions.html"><img src="https://img.shields.io/badge/-38%20functions-%23EF3939" alt="38 Functions" /></a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
|
@ -1,17 +1,26 @@
|
||||||
use leptos::html::Col;
|
use leptos::html::html;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_use::docs::demo_or_body;
|
use leptos_use::docs::{demo_or_body, Note};
|
||||||
use leptos_use::{
|
use leptos_use::{
|
||||||
use_color_mode_with_options, use_cycle_list, ColorMode, UseColorModeOptions,
|
use_color_mode_with_options, use_cycle_list_with_options, ColorMode, UseColorModeOptions,
|
||||||
UseColorModeReturn, UseCycleListReturn,
|
UseColorModeReturn, UseCycleListOptions, UseCycleListReturn,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn Demo(cx: Scope) -> impl IntoView {
|
fn Demo(cx: Scope) -> impl IntoView {
|
||||||
let UseColorModeReturn { mode, set_mode, .. } =
|
let UseColorModeReturn { mode, set_mode, .. } = use_color_mode_with_options(
|
||||||
use_color_mode_with_options(cx, UseColorModeOptions::default());
|
cx,
|
||||||
|
UseColorModeOptions::default()
|
||||||
|
.custom_modes(vec![
|
||||||
|
"rust".into(),
|
||||||
|
"coal".into(),
|
||||||
|
"navy".into(),
|
||||||
|
"ayu".into(),
|
||||||
|
])
|
||||||
|
.initial_value(ColorMode::from(html(cx).class_name())),
|
||||||
|
);
|
||||||
|
|
||||||
let UseCycleListReturn { state, next, .. } = use_cycle_list(
|
let UseCycleListReturn { state, next, .. } = use_cycle_list_with_options(
|
||||||
cx,
|
cx,
|
||||||
vec![
|
vec![
|
||||||
ColorMode::Light,
|
ColorMode::Light,
|
||||||
|
@ -20,9 +29,14 @@ fn Demo(cx: Scope) -> impl IntoView {
|
||||||
ColorMode::Custom("navy".into()),
|
ColorMode::Custom("navy".into()),
|
||||||
ColorMode::Custom("ayu".into()),
|
ColorMode::Custom("ayu".into()),
|
||||||
],
|
],
|
||||||
|
UseCycleListOptions::default().initial_value(Some((mode, set_mode).into())),
|
||||||
);
|
);
|
||||||
|
|
||||||
view! { cx,
|
view! { cx,
|
||||||
|
<button on:click=move |_| next()>
|
||||||
|
{ move || format!("{}", state.get()) }
|
||||||
|
</button>
|
||||||
|
<Note>"Click to change the color mode"</Note>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -264,8 +264,8 @@ select {
|
||||||
--tw-backdrop-sepia: ;
|
--tw-backdrop-sepia: ;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block {
|
.static {
|
||||||
display: block;
|
position: static;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-\[--brand-color\] {
|
.text-\[--brand-color\] {
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[toolchain]
|
|
||||||
channel = "stable"
|
|
|
@ -1,12 +1,11 @@
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use std::pin::Pin;
|
|
||||||
|
|
||||||
pub enum MaybeRwSignal<T>
|
pub enum MaybeRwSignal<T>
|
||||||
where
|
where
|
||||||
T: 'static,
|
T: 'static,
|
||||||
{
|
{
|
||||||
Static(T),
|
Static(T),
|
||||||
DynamicRw(ReadSignal<T>, WriteSignal<T>),
|
DynamicRw(Signal<T>, WriteSignal<T>),
|
||||||
DynamicRead(Signal<T>),
|
DynamicRead(Signal<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,8 +13,8 @@ impl<T: Clone> Clone for MaybeRwSignal<T> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
match self {
|
match self {
|
||||||
Self::Static(t) => Self::Static(t.clone()),
|
Self::Static(t) => Self::Static(t.clone()),
|
||||||
Self::DynamicRw(r, w) => Self::DynamicRw(r, w),
|
Self::DynamicRw(r, w) => Self::DynamicRw(*r, *w),
|
||||||
Self::DynamicRead(s) => Self::DynamicRead(s),
|
Self::DynamicRead(s) => Self::DynamicRead(*s),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,12 +54,18 @@ impl<T> From<Memo<T>> for MaybeRwSignal<T> {
|
||||||
impl<T> From<RwSignal<T>> for MaybeRwSignal<T> {
|
impl<T> From<RwSignal<T>> for MaybeRwSignal<T> {
|
||||||
fn from(s: RwSignal<T>) -> Self {
|
fn from(s: RwSignal<T>) -> Self {
|
||||||
let (r, w) = s.split();
|
let (r, w) = s.split();
|
||||||
Self::DynamicRw(r, w)
|
Self::DynamicRw(r.into(), w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<(ReadSignal<T>, WriteSignal<T>)> for MaybeRwSignal<T> {
|
impl<T> From<(ReadSignal<T>, WriteSignal<T>)> for MaybeRwSignal<T> {
|
||||||
fn from(s: (ReadSignal<T>, WriteSignal<T>)) -> Self {
|
fn from(s: (ReadSignal<T>, WriteSignal<T>)) -> Self {
|
||||||
|
Self::DynamicRw(s.0.into(), s.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<(Signal<T>, WriteSignal<T>)> for MaybeRwSignal<T> {
|
||||||
|
fn from(s: (Signal<T>, WriteSignal<T>)) -> Self {
|
||||||
Self::DynamicRw(s.0, s.1)
|
Self::DynamicRw(s.0, s.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,187 +76,18 @@ impl From<&str> for MaybeRwSignal<String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone> SignalGet<T> for MaybeRwSignal<T> {
|
impl<T: Clone> MaybeRwSignal<T> {
|
||||||
fn get(&self) -> T {
|
pub fn to_signal(&self, cx: Scope) -> (Signal<T>, WriteSignal<T>) {
|
||||||
match self {
|
match self {
|
||||||
Self::Static(t) => t.clone(),
|
Self::DynamicRead(s) => {
|
||||||
Self::DynamicRw(r, _) => r.get(),
|
// TODO : this feels hacky
|
||||||
Self::DynamicRead(s) => s.get(),
|
let (_, w) = create_signal(cx, s.get_untracked());
|
||||||
}
|
(*s, w)
|
||||||
}
|
|
||||||
|
|
||||||
fn try_get(&self) -> Option<T> {
|
|
||||||
match self {
|
|
||||||
Self::Static(t) => Some(t.clone()),
|
|
||||||
Self::DynamicRw(r, _) => r.try_get(),
|
|
||||||
Self::DynamicRead(s) => s.try_get(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> SignalWith<T> for MaybeRwSignal<T> {
|
|
||||||
fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O {
|
|
||||||
match self {
|
|
||||||
Self::Static(t) => f(t),
|
|
||||||
Self::DynamicRw(r, w) => r.with(f),
|
|
||||||
Self::DynamicRead(s) => s.with(f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_with<O>(&self, f: impl FnOnce(&T) -> O) -> Option<O> {
|
|
||||||
match self {
|
|
||||||
Self::Static(t) => Some(f(t)),
|
|
||||||
Self::DynamicRw(r, _) => r.try_with(f),
|
|
||||||
Self::DynamicRead(s) => s.try_with(f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> SignalWithUntracked<T> for MaybeRwSignal<T> {
|
|
||||||
fn with_untracked<O>(&self, f: impl FnOnce(&T) -> O) -> O {
|
|
||||||
match self {
|
|
||||||
Self::Static(t) => f(t),
|
|
||||||
Self::DynamicRw(r, _) => r.with_untracked(f),
|
|
||||||
Self::DynamicRead(s) => s.with_untracked(f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_with_untracked<O>(&self, f: impl FnOnce(&T) -> O) -> Option<O> {
|
|
||||||
match self {
|
|
||||||
Self::Static(t) => Some(f(t)),
|
|
||||||
Self::DynamicRw(r, _) => r.try_with_untracked(f),
|
|
||||||
Self::DynamicRead(s) => s.try_with_untracked(f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone> SignalGetUntracked<T> for MaybeRwSignal<T> {
|
|
||||||
fn get_untracked(&self) -> T {
|
|
||||||
match self {
|
|
||||||
Self::Static(t) => t.clone(),
|
|
||||||
Self::DynamicRw(r, _) => r.get_untracked(),
|
|
||||||
Self::DynamicRead(s) => s.get_untracked(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_get_untracked(&self) -> Option<T> {
|
|
||||||
match self {
|
|
||||||
Self::Static(t) => Some(t.clone()),
|
|
||||||
Self::DynamicRw(r, _) => r.try_get_untracked(),
|
|
||||||
Self::DynamicRead(s) => s.try_get_untracked(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone> SignalStream<T> for MaybeRwSignal<T> {
|
|
||||||
fn to_stream(&self, cx: Scope) -> Pin<Box<dyn futures::stream::Stream<Item = T>>> {
|
|
||||||
match self {
|
|
||||||
Self::Static(t) => {
|
|
||||||
let t = t.clone();
|
|
||||||
|
|
||||||
let stream = futures::stream::once(async move { t });
|
|
||||||
|
|
||||||
Box::bin(stream)
|
|
||||||
}
|
}
|
||||||
Self::DynamicRw(r, _) => r.to_stream(cx),
|
Self::DynamicRw(r, w) => (*r, *w),
|
||||||
Self::DynamicRead(s) => s.to_stream(cx),
|
Self::Static(v) => {
|
||||||
}
|
let (r, w) = create_signal(cx, v.clone());
|
||||||
}
|
(Signal::from(r), w)
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> MaybeRwSignal<T> {
|
|
||||||
pub fn derive(cx: Scope, derived_signal: impl Fn() -> T + 'static) -> Self {
|
|
||||||
Self::DynamicRead(Signal::derive(cx, derived_signal))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> SignalSetUntracked<T> for MaybeRwSignal<T> {
|
|
||||||
fn set_untracked(&self, new_value: T) {
|
|
||||||
match self {
|
|
||||||
Self::DynamicRw(_, w) => w.set_untracked(new_value),
|
|
||||||
_ => {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_set_untracked(&self, new_value: T) -> Option<T> {
|
|
||||||
match self {
|
|
||||||
Self::DynamicRw(_, w) => w.try_set_untracked(new_value),
|
|
||||||
_ => Some(new_value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> SignalUpdateUntracked<T> for MaybeRwSignal<T> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn update_untracked(&self, f: impl FnOnce(&mut T)) {
|
|
||||||
match self {
|
|
||||||
Self::DynamicRw(_, w) => w.update_untracked(f),
|
|
||||||
_ => {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn try_update_untracked<O>(&self, f: impl FnOnce(&mut T) -> O) -> Option<O> {
|
|
||||||
match self {
|
|
||||||
Self::DynamicRw(_, w) => w.try_update_untracked(f),
|
|
||||||
_ => Some(f()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> SignalUpdate<T> for MaybeRwSignal<T> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn update(&self, f: impl FnOnce(&mut T)) {
|
|
||||||
match self {
|
|
||||||
Self::DynamicRw(_, w) => w.update(f),
|
|
||||||
_ => {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn try_update<O>(&self, f: impl FnOnce(&mut T) -> O) -> Option<O> {
|
|
||||||
match self {
|
|
||||||
Self::DynamicRw(_, w) => w.try_update(f),
|
|
||||||
_ => Some(f()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> SignalSet<T> for MaybeRwSignal<T> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn set(&self, new_value: T) {
|
|
||||||
match self {
|
|
||||||
Self::DynamicRw(_, w) => w.set(new_value),
|
|
||||||
_ => {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_set(&self, new_value: T) -> Option<T> {
|
|
||||||
match self {
|
|
||||||
Self::DynamicRw(_, w) => w.try_set(new_value),
|
|
||||||
_ => Some(new_value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> SignalDispose for MaybeRwSignal<T> {
|
|
||||||
fn dispose(self) {
|
|
||||||
match self {
|
|
||||||
Self::DynamicRw(r, w) => {
|
|
||||||
r.dispose();
|
|
||||||
w.dispose();
|
|
||||||
}
|
|
||||||
Self::DynamicRead(s) => s.dispose(),
|
|
||||||
_ => {
|
|
||||||
// do nothing
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use leptos::window;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
|
|
||||||
/// Local or session storage or a custom store that is a `web_sys::Storage`.
|
/// Local or session storage or a custom store that is a `web_sys::Storage`.
|
||||||
#[doc(cfg(feature = "storage"))]
|
// #[doc(cfg(feature = "storage"))]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub enum StorageType {
|
pub enum StorageType {
|
||||||
#[default]
|
#[default]
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::core::ElementMaybeSignal;
|
||||||
use crate::storage::{use_storage_with_options, UseStorageOptions};
|
use crate::storage::{use_storage_with_options, UseStorageOptions};
|
||||||
#[cfg(feature = "storage")]
|
#[cfg(feature = "storage")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
use crate::core::StorageType;
|
use crate::core::StorageType;
|
||||||
use crate::use_preferred_dark;
|
use crate::use_preferred_dark;
|
||||||
|
@ -54,11 +55,11 @@ use wasm_bindgen::JsCast;
|
||||||
/// # fn Demo(cx: Scope) -> impl IntoView {
|
/// # fn Demo(cx: Scope) -> impl IntoView {
|
||||||
/// # let UseColorModeReturn { mode, set_mode, .. } = use_color_mode(cx);
|
/// # let UseColorModeReturn { mode, set_mode, .. } = use_color_mode(cx);
|
||||||
/// #
|
/// #
|
||||||
/// mode(); // ColorMode::Dark or ColorMode::Light
|
/// mode.get(); // ColorMode::Dark or ColorMode::Light
|
||||||
///
|
///
|
||||||
/// set_mode(ColorMode::Dark); // change to dark mode and persist (with feature `storage`)
|
/// set_mode.set(ColorMode::Dark); // change to dark mode and persist (with feature `storage`)
|
||||||
///
|
///
|
||||||
/// set_mode(ColorMode::Auto); // change to auto mode
|
/// set_mode.set(ColorMode::Auto); // change to auto mode
|
||||||
/// #
|
/// #
|
||||||
/// # view! { cx, }
|
/// # view! { cx, }
|
||||||
/// # }
|
/// # }
|
||||||
|
@ -182,7 +183,7 @@ where
|
||||||
|
|
||||||
if attribute == "class" {
|
if attribute == "class" {
|
||||||
for mode in &modes {
|
for mode in &modes {
|
||||||
if value == ColorMode::from_string(mode) {
|
if &value.to_string() == mode {
|
||||||
let _ = el.class_list().add_1(mode);
|
let _ = el.class_list().add_1(mode);
|
||||||
} else {
|
} else {
|
||||||
let _ = el.class_list().remove_1(mode);
|
let _ = el.class_list().remove_1(mode);
|
||||||
|
@ -231,7 +232,10 @@ where
|
||||||
on_changed(state.get());
|
on_changed(state.get());
|
||||||
});
|
});
|
||||||
|
|
||||||
let mode = Signal::derive(cx, move || if emit_auto { store.get() } else { state() });
|
let mode = Signal::derive(
|
||||||
|
cx,
|
||||||
|
move || if emit_auto { store.get() } else { state.get() },
|
||||||
|
);
|
||||||
|
|
||||||
UseColorModeReturn {
|
UseColorModeReturn {
|
||||||
mode,
|
mode,
|
||||||
|
@ -259,10 +263,10 @@ fn get_store_signal(
|
||||||
cx: Scope,
|
cx: Scope,
|
||||||
initial_value: MaybeSignal<ColorMode>,
|
initial_value: MaybeSignal<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>) {
|
) -> (ReadSignal<ColorMode>, WriteSignal<ColorMode>) {
|
||||||
if let Some(storage_signal) = storage_signal {
|
if let Some(storage_signal) = storage_signal {
|
||||||
storage_signal.split()
|
storage_signal.split()
|
||||||
|
@ -273,7 +277,7 @@ fn get_store_signal(
|
||||||
|
|
||||||
#[cfg(feature = "storage")]
|
#[cfg(feature = "storage")]
|
||||||
/// Color modes
|
/// Color modes
|
||||||
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq, Hash, Debug)]
|
||||||
pub enum ColorMode {
|
pub enum ColorMode {
|
||||||
#[default]
|
#[default]
|
||||||
Auto,
|
Auto,
|
||||||
|
@ -310,21 +314,21 @@ fn get_store_signal(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for ColorMode {
|
impl Display for ColorMode {
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
use ColorMode::*;
|
use ColorMode::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Auto => "".to_string(),
|
Auto => write!(f, "auto"),
|
||||||
Light => "light".to_string(),
|
Light => write!(f, "light"),
|
||||||
Dark => "dark".to_string(),
|
Dark => write!(f, "dark"),
|
||||||
Custom(v) => v.clone(),
|
Custom(v) => write!(f, "{}", v),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ColorMode {
|
impl From<&str> for ColorMode {
|
||||||
pub fn from_string(s: &str) -> ColorMode {
|
fn from(s: &str) -> Self {
|
||||||
match s {
|
match s {
|
||||||
"auto" => ColorMode::Auto,
|
"auto" => ColorMode::Auto,
|
||||||
"" => ColorMode::Auto,
|
"" => ColorMode::Auto,
|
||||||
|
@ -335,6 +339,12 @@ impl ColorMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<String> for ColorMode {
|
||||||
|
fn from(s: String) -> Self {
|
||||||
|
ColorMode::from(s.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Arguments to [`UseColorModeOptions::on_changed`]
|
/// Arguments to [`UseColorModeOptions::on_changed`]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct UseColorModeOnChangeArgs {
|
pub struct UseColorModeOnChangeArgs {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::core::MaybeRwSignal;
|
||||||
use crate::watch;
|
use crate::watch;
|
||||||
use default_struct_builder::DefaultBuilder;
|
use default_struct_builder::DefaultBuilder;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
|
@ -21,11 +22,11 @@ use leptos::*;
|
||||||
/// vec!["Dog", "Cat", "Lizard", "Shark", "Whale", "Dolphin", "Octopus", "Seal"]
|
/// vec!["Dog", "Cat", "Lizard", "Shark", "Whale", "Dolphin", "Octopus", "Seal"]
|
||||||
/// );
|
/// );
|
||||||
///
|
///
|
||||||
/// log!("{}", state()); // "Dog"
|
/// log!("{}", state.get()); // "Dog"
|
||||||
///
|
///
|
||||||
/// prev();
|
/// prev();
|
||||||
///
|
///
|
||||||
/// log!("{}", state()); // "Seal"
|
/// log!("{}", state.get()); // "Seal"
|
||||||
/// #
|
/// #
|
||||||
/// # view! { cx, }
|
/// # view! { cx, }
|
||||||
/// # }
|
/// # }
|
||||||
|
@ -77,14 +78,14 @@ where
|
||||||
|
|
||||||
move || {
|
move || {
|
||||||
if let Some(initial_value) = initial_value {
|
if let Some(initial_value) = initial_value {
|
||||||
initial_value.get()
|
initial_value
|
||||||
} else {
|
} else {
|
||||||
first.expect("The provided list shouldn't be empty")
|
MaybeRwSignal::from(first.expect("The provided list shouldn't be empty"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (state, set_state) = create_signal(cx, get_initial_value());
|
let (state, set_state) = get_initial_value().to_signal(cx);
|
||||||
|
|
||||||
let index = {
|
let index = {
|
||||||
let list = list.clone();
|
let list = list.clone();
|
||||||
|
@ -162,7 +163,7 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
UseCycleListReturn {
|
UseCycleListReturn {
|
||||||
state: state.into(),
|
state,
|
||||||
set_state,
|
set_state,
|
||||||
index: index.into(),
|
index: index.into(),
|
||||||
set_index: set,
|
set_index: set,
|
||||||
|
@ -181,7 +182,7 @@ where
|
||||||
/// The initial value of the state. Can be a Signal. If none is provided the first entry
|
/// The initial value of the state. Can be a Signal. If none is provided the first entry
|
||||||
/// of the list will be used.
|
/// of the list will be used.
|
||||||
#[builder(keep_type)]
|
#[builder(keep_type)]
|
||||||
initial_value: Option<MaybeSignal<T>>,
|
initial_value: Option<MaybeRwSignal<T>>,
|
||||||
|
|
||||||
/// The default index when the current value is not found in the list.
|
/// The default index when the current value is not found in the list.
|
||||||
/// For example when `get_index_of` returns `None`.
|
/// For example when `get_index_of` returns `None`.
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::use_event_listener;
|
||||||
use crate::utils::CloneableFnMutWithArg;
|
use crate::utils::CloneableFnMutWithArg;
|
||||||
use leptos::ev::change;
|
use leptos::ev::change;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use std::cell::{OnceCell, RefCell};
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// Reactive [Media Query](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Testing_media_queries).
|
/// Reactive [Media Query](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Testing_media_queries).
|
||||||
|
@ -40,8 +40,8 @@ pub fn use_media_query(cx: Scope, query: impl Into<MaybeSignal<String>>) -> Sign
|
||||||
let media_query: Rc<RefCell<Option<web_sys::MediaQueryList>>> = Rc::new(RefCell::new(None));
|
let media_query: Rc<RefCell<Option<web_sys::MediaQueryList>>> = Rc::new(RefCell::new(None));
|
||||||
let remove_listener: RemoveListener = Rc::new(RefCell::new(None));
|
let remove_listener: RemoveListener = Rc::new(RefCell::new(None));
|
||||||
|
|
||||||
let listener: Rc<OnceCell<Box<dyn CloneableFnMutWithArg<web_sys::Event>>>> =
|
let listener: Rc<RefCell<Box<dyn CloneableFnMutWithArg<web_sys::Event>>>> =
|
||||||
Rc::new(OnceCell::new());
|
Rc::new(RefCell::new(Box::new(|_| {})));
|
||||||
|
|
||||||
let cleanup = {
|
let cleanup = {
|
||||||
let remove_listener = Rc::clone(&remove_listener);
|
let remove_listener = Rc::clone(&remove_listener);
|
||||||
|
@ -70,10 +70,7 @@ pub fn use_media_query(cx: Scope, query: impl Into<MaybeSignal<String>>) -> Sign
|
||||||
cx,
|
cx,
|
||||||
media_query.clone(),
|
media_query.clone(),
|
||||||
change,
|
change,
|
||||||
listener
|
listener.borrow().clone(),
|
||||||
.get()
|
|
||||||
.expect("cell should be initialized by now")
|
|
||||||
.clone(),
|
|
||||||
))));
|
))));
|
||||||
} else {
|
} else {
|
||||||
set_matches.set(false);
|
set_matches.set(false);
|
||||||
|
@ -84,8 +81,7 @@ pub fn use_media_query(cx: Scope, query: impl Into<MaybeSignal<String>>) -> Sign
|
||||||
{
|
{
|
||||||
let update = update.clone();
|
let update = update.clone();
|
||||||
listener
|
listener
|
||||||
.set(Box::new(move |_| update()) as Box<dyn CloneableFnMutWithArg<web_sys::Event>>)
|
.replace(Box::new(move |_| update()) as Box<dyn CloneableFnMutWithArg<web_sys::Event>>);
|
||||||
.expect("cell is empty");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
create_effect(cx, move |_| update());
|
create_effect(cx, move |_| update());
|
||||||
|
|
|
@ -20,19 +20,19 @@ use leptos::*;
|
||||||
/// # view! { cx, }
|
/// # view! { cx, }
|
||||||
/// # }
|
/// # }
|
||||||
/// ```{{#if feature}}
|
/// ```{{#if feature}}
|
||||||
#[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
||||||
pub fn {{ function_name }}({{#if scope }}cx: Scope{{/if}}) -> {{ to_pascal_case function_name }}Return {
|
pub fn {{ function_name }}({{#if scope }}cx: Scope{{/if}}) -> {{ to_pascal_case function_name }}Return {
|
||||||
{{ function_name }}_with_options({{#if scope }}cx, {{/if}}{{ to_pascal_case function_name }}Options::default())
|
{{ function_name }}_with_options({{#if scope }}cx, {{/if}}{{ 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 [`{{ function_name }}`] that takes a `{{ to_pascal_case function_name }}Options`. See [`{{ function_name }}`] for how to use.{{#if feature}}
|
||||||
#[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
||||||
pub fn {{ function_name }}_with_options({{#if scope }}cx: Scope, {{/if}}options: {{ to_pascal_case function_name }}Options) -> {{ to_pascal_case function_name }}Return {
|
pub fn {{ function_name }}_with_options({{#if scope }}cx: Scope, {{/if}}options: {{ to_pascal_case function_name }}Options) -> {{ to_pascal_case function_name }}Return {
|
||||||
{{ to_pascal_case function_name }}Return {}
|
{{ to_pascal_case function_name }}Return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Options for [`{{ function_name }}_with_options`].{{#if feature}}
|
/// Options for [`{{ function_name }}_with_options`].{{#if feature}}
|
||||||
#[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
||||||
#[derive(DefaultBuilder)]
|
#[derive(DefaultBuilder)]
|
||||||
pub struct {{ to_pascal_case function_name }}Options {}
|
pub struct {{ to_pascal_case function_name }}Options {}
|
||||||
|
|
||||||
|
@ -42,6 +42,6 @@ impl Default for {{ to_pascal_case function_name }}Options {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return type of [`{{ function_name }}`].
|
/// Return type of [`{{ function_name }}`].{{#if feature}}
|
||||||
{{#if feature}}#[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
// #[doc(cfg(feature = "{{feature}}"))]{{/if}}
|
||||||
pub struct {{ to_pascal_case function_name }}Return {}
|
pub struct {{ to_pascal_case function_name }}Return {}
|
Loading…
Add table
Reference in a new issue