leptos_use/
use_cycle_list.rsuse crate::core::MaybeRwSignal;
use default_struct_builder::DefaultBuilder;
use leptos::prelude::*;
pub fn use_cycle_list<T, L>(
list: L,
) -> UseCycleListReturn<
T,
impl Fn(usize) -> T + Clone + Send + Sync,
impl Fn() + Clone + Send + Sync,
impl Fn() + Clone + Send + Sync,
impl Fn(i64) -> T + Clone + Send + Sync,
>
where
T: Clone + PartialEq + Send + Sync + 'static,
L: Into<Signal<Vec<T>>>,
{
use_cycle_list_with_options(list, UseCycleListOptions::default())
}
pub fn use_cycle_list_with_options<T, L>(
list: L,
options: UseCycleListOptions<T>,
) -> UseCycleListReturn<
T,
impl Fn(usize) -> T + Clone,
impl Fn() + Clone,
impl Fn() + Clone,
impl Fn(i64) -> T + Clone,
>
where
T: Clone + PartialEq + Send + Sync + 'static,
L: Into<Signal<Vec<T>>>,
{
let UseCycleListOptions {
initial_value,
fallback_index,
get_position,
} = options;
let list = list.into();
let get_initial_value = {
let list = list.get_untracked();
let first = list.first().cloned();
move || {
if let Some(initial_value) = initial_value {
initial_value
} else {
MaybeRwSignal::from(first.expect("The provided list shouldn't be empty"))
}
}
};
let (state, set_state) = get_initial_value().into_signal();
let index = Signal::derive(move || {
let index = get_position(&state.get(), &list.read());
if let Some(index) = index {
index
} else {
fallback_index
}
});
let set = move |i: usize| {
let length = list.read().len();
let index = i % length;
let value = list.read()[index].clone();
set_state.update({
let value = value.clone();
move |v| *v = value
});
value
};
let shift = move |delta: i64| {
let length = list.read().len() as i64;
let i = index.get_untracked() as i64 + delta;
let index = (i % length) + length;
set(index as usize)
};
let next = move || {
shift(1);
};
let prev = move || {
shift(-1);
};
let _ = Effect::watch(move || list.get(), move |_, _, _| set(index.get()), false);
UseCycleListReturn {
state,
set_state,
index,
set_index: set,
next,
prev,
shift,
}
}
#[derive(DefaultBuilder)]
pub struct UseCycleListOptions<T>
where
T: Clone + PartialEq + Send + Sync + 'static,
{
#[builder(keep_type)]
initial_value: Option<MaybeRwSignal<T>>,
fallback_index: usize,
#[builder(keep_type)]
get_position: fn(&T, &Vec<T>) -> Option<usize>,
}
impl<T> Default for UseCycleListOptions<T>
where
T: Clone + PartialEq + Send + Sync + 'static,
{
fn default() -> Self {
Self {
initial_value: None,
fallback_index: 0,
get_position: |value: &T, list: &Vec<T>| list.iter().position(|v| v == value),
}
}
}
pub struct UseCycleListReturn<T, SetFn, NextFn, PrevFn, ShiftFn>
where
T: Clone + PartialEq + Send + Sync + 'static,
SetFn: Fn(usize) -> T + Clone,
NextFn: Fn() + Clone,
PrevFn: Fn() + Clone,
ShiftFn: Fn(i64) -> T + Clone,
{
pub state: Signal<T>,
pub set_state: WriteSignal<T>,
pub index: Signal<usize>,
pub set_index: SetFn,
pub next: NextFn,
pub prev: PrevFn,
pub shift: ShiftFn,
}