thaw 0.4.8

An easy to use leptos component library
Documentation
use leptos::{context::Provider, prelude::*};
use slotmap::{DefaultKey, SlotMap};

#[component]
pub fn FieldContextProvider(children: Children) -> impl IntoView {
    view! { <Provider value=FieldContextInjection::new()>{children()}</Provider> }
}

#[derive(Clone)]
pub struct FieldContextInjection(
    StoredValue<SlotMap<DefaultKey, (Signal<Option<String>>, Callback<(), bool>)>>,
);

impl FieldContextInjection {
    fn new() -> Self {
        Self(StoredValue::new(SlotMap::new()))
    }

    pub fn expect_context() -> Self {
        expect_context()
    }

    pub fn use_context() -> Option<Self> {
        use_context()
    }

    pub(crate) fn register_field(
        &self,
        name: Signal<Option<String>>,
        validate: impl Fn() -> bool + Send + Sync + 'static,
    ) {
        let mut key = None;
        let validate: Callback<(), bool> = Callback::from(move || validate());
        self.0.update_value(|map| {
            key = Some(map.insert((name, validate)));
            ()
        });

        let map = self.0.clone();
        Owner::on_cleanup(move || {
            map.update_value(|map| {
                map.remove(key.unwrap());
            });
        });
    }

    pub fn validate(&self) -> bool {
        self.0.with_value(|map| {
            let mut rt = true;
            for (_, (_, validate)) in map.iter() {
                if !validate.run(()) {
                    rt = false;
                }
            }
            rt
        })
    }

    pub fn validate_field(&self, name: String) -> bool {
        self.0.with_value(|map| {
            for (_, (n, validate)) in map.iter() {
                if n.get_untracked().as_ref() == Some(&name) && !validate.run(()) {
                    return false;
                }
            }
            true
        })
    }
}