Skip to main content

euv_ui/hook/debounced_value/
struct.rs

1use super::*;
2
3/// A value that only emits after a quiet period of
4/// `delay` since its most recent `set`.
5///
6/// Constructed via `DebouncedValue::new(delay_ms)`
7/// (Lombok `New`); the emitted value starts at
8/// `T::default()` and the throttle state starts at
9/// `Idle`. Use [`DebouncedValue::set`] (or
10/// [`DebouncedValue::tick`] with a backdated `Instant`)
11/// to seed the emitted value.
12///
13/// Typical use: pair with `App::use_interval` — the
14/// interval callback calls `tick(Instant::now())` every
15/// N milliseconds. After `delay_ms` without a fresh
16/// `set`, the pending value is committed.
17///
18/// This shape keeps the hook free of any browser /
19/// timer dependency so the same code runs in
20/// `cargo test` and in `wasm32-unknown-unknown` — the
21/// caller supplies the time source.
22#[derive(Clone, Data, Debug, New)]
23pub struct DebouncedValue<T: Clone + PartialEq + Default + 'static> {
24    /// The emitted value signal. Defaults to
25    /// `Signal::create(T::default())` via
26    /// `#[new(skip)]`.
27    #[new(skip)]
28    #[get(type(copy))]
29    pub(crate) value: Signal<T>,
30    /// The internal pending/empty state. Defaults to
31    /// `Signal::create(DebounceState::Idle)` via
32    /// `#[new(skip)]`.
33    #[new(skip)]
34    pub(crate) state: Signal<DebounceState<T>>,
35    /// The quiet period in milliseconds.
36    pub(crate) delay_ms: u32,
37}
38
39/// `DebouncedValue<T>` is `Copy` when `T` is — every field
40/// (`Signal<T>`, `Signal<DebounceState<T>>`, `u32`) is itself
41/// `Copy`, so the blanket impl is sound.
42impl<T> Copy for DebouncedValue<T> where T: Clone + PartialEq + Default + 'static {}