use std::cell::RefCell;
use std::collections::HashMap;
use web_sys::Element;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LifecycleState {
Mount,
Hydrate,
Active,
Replay,
Suspend,
Destroy,
}
impl LifecycleState {
pub fn as_str(&self) -> &'static str {
match self {
Self::Mount => "mount",
Self::Hydrate => "hydrate",
Self::Active => "active",
Self::Replay => "replay",
Self::Suspend => "suspend",
Self::Destroy => "destroy",
}
}
pub fn can_transition_to(&self, next: &LifecycleState) -> bool {
match (self, next) {
(Self::Mount, Self::Hydrate) => true,
(Self::Mount, Self::Active) => true,
(Self::Hydrate, Self::Active) => true,
(Self::Active, Self::Replay) => true,
(Self::Active, Self::Suspend) => true,
(Self::Active, Self::Destroy) => true,
(Self::Replay, Self::Active) => true,
(Self::Replay, Self::Destroy) => true,
(Self::Suspend, Self::Active) => true,
(Self::Suspend, Self::Destroy) => true,
_ => false,
}
}
}
thread_local! {
static STATES: RefCell<HashMap<String, LifecycleState>> = RefCell::new(HashMap::new());
}
pub fn state(uid: &str) -> Option<LifecycleState> {
STATES.with(|s| s.borrow().get(uid).copied())
}
pub fn transition(uid: &str, next: LifecycleState) -> bool {
STATES.with(|s| {
let mut states = s.borrow_mut();
let current = states.get(uid).copied().unwrap_or(LifecycleState::Mount);
if !current.can_transition_to(&next) { return false; }
states.insert(uid.to_string(), next);
true
})
}
pub fn set_state(uid: &str, state: LifecycleState) {
STATES.with(|s| { s.borrow_mut().insert(uid.to_string(), state); });
}
pub fn remove(uid: &str) {
STATES.with(|s| { s.borrow_mut().remove(uid); });
}
pub fn is_active(uid: &str) -> bool {
state(uid) == Some(LifecycleState::Active)
}
pub fn is_mounted(uid: &str) -> bool {
!matches!(state(uid), None | Some(LifecycleState::Destroy))
}
pub fn uid_of(el: &Element) -> Option<String> {
el.get_attribute("data-rs-uid")
}