leptos_use/utils/filters/
mod.rs

1mod debounce;
2mod throttle;
3
4pub use debounce::*;
5pub use throttle::*;
6
7use crate::sendwrap_fn;
8use leptos::prelude::Signal;
9use std::sync::{Arc, Mutex};
10
11macro_rules! ArcFilterFn {
12    ($R:ident) => {
13        Arc<dyn Fn(Arc<dyn Fn() -> $R>) -> Arc<Mutex<Option<$R>>>>
14    }
15}
16
17pub fn create_filter_wrapper<F, R>(
18    filter: ArcFilterFn!(R),
19    func: F,
20) -> impl Fn() -> Arc<Mutex<Option<R>>> + Clone + Send + Sync
21where
22    F: Fn() -> R + Clone + 'static,
23    R: 'static,
24{
25    sendwrap_fn!(move || Arc::clone(&filter)(Arc::new(func.clone())))
26}
27
28pub fn create_filter_wrapper_with_arg<F, Arg, R>(
29    filter: ArcFilterFn!(R),
30    func: F,
31) -> impl Fn(Arg) -> Arc<Mutex<Option<R>>> + Clone + Send + Sync
32where
33    F: Fn(Arg) -> R + Clone + 'static,
34    R: 'static,
35    Arg: Clone + 'static,
36{
37    sendwrap_fn!(move |arg: Arg| {
38        let func = func.clone();
39        Arc::clone(&filter)(Arc::new(move || func(arg.clone())))
40    })
41}
42
43/// Specify a debounce or throttle filter with their respective options or no filter
44#[derive(Default)]
45pub enum FilterOptions {
46    #[default]
47    None,
48    Debounce {
49        ms: Signal<f64>,
50        options: DebounceOptions,
51    },
52    Throttle {
53        ms: Signal<f64>,
54        options: ThrottleOptions,
55    },
56}
57
58impl FilterOptions {
59    pub fn debounce(ms: impl Into<Signal<f64>>) -> Self {
60        Self::Debounce {
61            ms: ms.into(),
62            options: DebounceOptions::default(),
63        }
64    }
65
66    pub fn throttle(ms: impl Into<Signal<f64>>) -> Self {
67        Self::Throttle {
68            ms: ms.into(),
69            options: ThrottleOptions::default(),
70        }
71    }
72
73    pub fn filter_fn<R>(&self) -> ArcFilterFn!(R)
74    where
75        R: 'static,
76    {
77        match self {
78            FilterOptions::Debounce { ms, options } => Arc::new(debounce_filter(*ms, *options)),
79            FilterOptions::Throttle { ms, options } => Arc::new(throttle_filter(*ms, *options)),
80            FilterOptions::None => {
81                Arc::new(|invoke: Arc<dyn Fn() -> R>| Arc::new(Mutex::new(Some(invoke()))))
82            }
83        }
84    }
85}
86
87/// Defines builder methods to define filter options without having to use nested methods
88#[macro_export]
89macro_rules! filter_builder_methods {
90    (
91        #[$filter_docs:meta]
92        $filter_field_name:ident
93    ) => {
94        /// Debounce
95        #[$filter_docs]
96        /// by `ms` milliseconds.
97        pub fn debounce(self, ms: impl Into<Signal<f64>>) -> Self {
98            self.debounce_with_options(ms, DebounceOptions::default())
99        }
100
101        /// Debounce
102        #[$filter_docs]
103        /// by `ms` milliseconds with additional options.
104        pub fn debounce_with_options(
105            self,
106            ms: impl Into<Signal<f64>>,
107            options: DebounceOptions,
108        ) -> Self {
109            Self {
110                $filter_field_name: FilterOptions::Debounce {
111                    ms: ms.into(),
112                    options,
113                },
114                ..self
115            }
116        }
117
118        /// Throttle
119        #[$filter_docs]
120        /// by `ms` milliseconds.
121        pub fn throttle(self, ms: impl Into<Signal<f64>>) -> Self {
122            self.throttle_with_options(ms, ThrottleOptions::default())
123        }
124
125        /// Throttle
126        #[$filter_docs]
127        /// by `ms` milliseconds with additional options.
128        pub fn throttle_with_options(
129            self,
130            ms: impl Into<Signal<f64>>,
131            options: ThrottleOptions,
132        ) -> Self {
133            Self {
134                $filter_field_name: FilterOptions::Throttle {
135                    ms: ms.into(),
136                    options,
137                },
138                ..self
139            }
140        }
141    };
142}