#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ScrollTriggerOptions {
pub threshold: f64,
pub hysteresis: f64,
}
impl Default for ScrollTriggerOptions {
fn default() -> Self {
Self {
threshold: 48.0,
hysteresis: 8.0,
}
}
}
pub fn resolve_scroll_trigger(
last_y: f64,
y: f64,
hidden: bool,
opts: ScrollTriggerOptions,
) -> bool {
let threshold = opts.threshold.max(0.0);
let hysteresis = opts.hysteresis.max(0.0);
if y < threshold {
return false;
}
let delta = y - last_y;
if delta >= hysteresis {
true
} else if delta <= -hysteresis {
false
} else {
hidden
}
}
#[cfg(test)]
mod tests {
use super::*;
fn opts() -> ScrollTriggerOptions {
ScrollTriggerOptions {
threshold: 48.0,
hysteresis: 8.0,
}
}
#[test]
fn resolve_hides_on_scroll_down_past_threshold() {
assert!(resolve_scroll_trigger(50.0, 80.0, false, opts()));
}
#[test]
fn resolve_shows_on_scroll_up() {
assert!(!resolve_scroll_trigger(200.0, 160.0, true, opts()));
}
#[test]
fn resolve_stays_visible_below_threshold() {
assert!(!resolve_scroll_trigger(10.0, 20.0, true, opts()));
assert!(!resolve_scroll_trigger(40.0, 47.0, true, opts()));
}
#[test]
fn resolve_hysteresis_ignores_small_delta() {
assert!(!resolve_scroll_trigger(100.0, 104.0, false, opts()));
assert!(resolve_scroll_trigger(100.0, 96.0, true, opts()));
}
}