use dioxus_html::input_data::keyboard_types::Key;
use dioxus_native_core::{
custom_element::CustomElement,
real_dom::{NodeImmutable, RealDom},
NodeId,
};
use crate::EventData;
use super::{text_like::TextLike, RinkWidget};
#[derive(Debug, Default)]
pub(crate) struct Number {
text: TextLike,
}
impl Number {
fn increase(&mut self, rdom: &mut RealDom, id: NodeId) {
let num = self.text.text().parse::<f64>().unwrap_or(0.0);
self.text.set_text((num + 1.0).to_string(), rdom, id);
}
fn decrease(&mut self, rdom: &mut RealDom, id: NodeId) {
let num = self.text.text().parse::<f64>().unwrap_or(0.0);
self.text.set_text((num - 1.0).to_string(), rdom, id);
}
}
impl CustomElement for Number {
const NAME: &'static str = "input";
fn roots(&self) -> Vec<NodeId> {
self.text.roots()
}
fn create(mut root: dioxus_native_core::real_dom::NodeMut) -> Self {
Number {
text: TextLike::create(root.reborrow()),
}
}
fn attributes_changed(
&mut self,
root: dioxus_native_core::real_dom::NodeMut,
attributes: &dioxus_native_core::node_ref::AttributeMask,
) {
self.text.attributes_changed(root, attributes)
}
}
impl RinkWidget for Number {
fn handle_event(
&mut self,
event: &crate::Event,
mut node: dioxus_native_core::real_dom::NodeMut,
) {
if event.name == "keydown" {
if let EventData::Keyboard(data) = &event.data {
let key = data.key();
let is_num_like = match key.clone() {
Key::ArrowLeft | Key::ArrowRight | Key::Backspace => true,
Key::Character(c)
if c == "." || c == "-" || c.chars().all(|c| c.is_numeric()) =>
{
true
}
_ => false,
};
if is_num_like {
self.text.handle_event(event, node)
} else {
let id = node.id();
let rdom = node.real_dom_mut();
match key {
Key::ArrowUp => {
self.increase(rdom, id);
}
Key::ArrowDown => {
self.decrease(rdom, id);
}
_ => (),
}
}
return;
}
}
self.text.handle_event(event, node)
}
}