use ratatui_kit::{Hooks, UseEffect, UseState};
use std::{hash::Hash, time::Duration};
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct DebounceOptions {
pub wait: Duration,
pub leading: bool,
pub trailing: bool,
}
impl Default for DebounceOptions {
fn default() -> Self {
Self {
wait: Duration::from_millis(500),
leading: false,
trailing: true,
}
}
}
impl DebounceOptions {
pub fn trailing(mut self) -> Self {
self.trailing = true;
self
}
pub fn leading(mut self) -> Self {
self.leading = true;
self
}
pub fn wait(mut self, wait: Duration) -> Self {
self.wait = wait;
self
}
}
pub trait UseDebounceEffect {
fn use_debounce_effect<F, D>(&mut self, callback: F, deps: D, options: DebounceOptions)
where
F: FnMut() + Send + 'static,
D: Hash;
}
impl UseDebounceEffect for Hooks<'_, '_> {
fn use_debounce_effect<F, D>(&mut self, mut callback: F, deps: D, options: DebounceOptions)
where
F: FnMut() + Send + 'static,
D: Hash,
{
let mut has_leading = self.use_state(|| false);
self.use_async_effect(
async move {
if options.leading && !has_leading.get() {
has_leading.set(true);
callback();
}
tokio::time::sleep(options.wait).await;
if options.trailing {
callback();
}
has_leading.set(false);
},
(deps, options),
);
}
}