Skip to main content

a2ui_base/components/
slider.rs

1//! Slider component behavior — framework-agnostic `handle_event`.
2
3use crate::event::{EventResult, InputEvent, InputKey};
4use crate::model::component_context::ComponentContext;
5use crate::protocol::common_types::DynamicNumber;
6
7/// Handle a key-press for a Slider (steps the bound number Left/Right).
8pub fn handle_event(ctx: &ComponentContext, event: &InputEvent) -> Option<EventResult> {
9    let comp_model = ctx.components.get(&ctx.component_id)?;
10
11    let value_dn = comp_model.get_property::<DynamicNumber>("value")?;
12    let binding = match value_dn {
13        DynamicNumber::Binding(b) => b,
14        _ => return None,
15    };
16
17    let current =
18        ctx.data_context
19            .resolve_dynamic_number(&DynamicNumber::Binding(binding.clone()));
20    let min = comp_model
21        .get_property::<DynamicNumber>("min")
22        .map(|dn| ctx.data_context.resolve_dynamic_number(&dn))
23        .unwrap_or(0.0);
24    let max = comp_model
25        .get_property::<DynamicNumber>("max")
26        .map(|dn| ctx.data_context.resolve_dynamic_number(&dn))
27        .unwrap_or(100.0);
28
29    let steps = comp_model
30        .get_property::<DynamicNumber>("steps")
31        .map(|dn| ctx.data_context.resolve_dynamic_number(&dn) as usize)
32        .unwrap_or(10);
33    let step = if steps > 0 {
34        (max - min) / steps as f64
35    } else {
36        1.0
37    };
38
39    let delta = match event {
40        InputEvent::KeyPress {
41            key: InputKey::Right,
42        } => step,
43        InputEvent::KeyPress { key: InputKey::Left } => -step,
44        _ => return None,
45    };
46
47    let new_value = (current + delta).clamp(min, max);
48    Some(EventResult::DataUpdate {
49        path: binding.path.clone(),
50        value: serde_json::json!(new_value),
51    })
52}