yew-bulma 0.0.1

Yew components compatible with the Bulma CSS framework
Documentation
use crate::validations::{ValidationError, Validator};
use std::{cell::RefCell, rc::Rc};

#[derive(Debug, Default, Clone)]
pub struct FormStorage<T>
where
    T: std::fmt::Debug + Default + Clone,
{
    value: Rc<RefCell<FormStorageBacking<T>>>,
}

#[derive(Debug, Default, Clone)]
struct FormStorageBacking<T>
where
    T: std::fmt::Debug + Default + Clone,
{
    value: T,
    dirty: bool,
    invalid_value: bool,
}

impl<T> FormStorage<T>
where
    T: std::fmt::Debug + Default + Clone + PartialEq,
{
    pub fn new(value: T) -> Self {
        Self {
            value: Rc::new(RefCell::new(FormStorageBacking {
                value,
                dirty: false,
                invalid_value: false,
            })),
        }
    }

    pub fn update(&mut self, new_value: T) {
        let mut backing = self.value.borrow_mut();
        backing.dirty = backing.dirty || backing.value.eq(&new_value);
        backing.value = new_value;
    }

    pub fn update_with_invalid_hint(&mut self, new_value: T, invalid: bool) {
        self.update(new_value);
        self.value.borrow_mut().invalid_value = invalid;
    }

    pub fn update_invalid_hint(&mut self, invalid: bool) {
        self.value.borrow_mut().invalid_value = invalid;
    }

    pub fn value(&self) -> Result<T, ValidationError> {
        self.validate().map(|_| self.unchecked_value())
    }

    pub fn unchecked_value(&self) -> T {
        self.value.borrow().value.clone()
    }
}

impl<T> Validator for FormStorage<T>
where
    T: std::fmt::Debug + Default + Clone + PartialEq,
{
    fn validate(&self) -> Result<(), ValidationError> {
        let backing = self.value.borrow();

        if backing.invalid_value {
            return Err(ValidationError::InvalidValue);
        }
        Ok(())
    }
}