use gloo_utils::document;
use std::rc::Rc;
use wasm_bindgen::JsValue;
use yew::prelude::*;
#[derive(Clone, Debug)]
pub struct Backdrop {
pub content: Html,
}
impl Backdrop {
pub fn new(content: Html) -> Self {
Self { content }
}
}
impl Default for Backdrop {
fn default() -> Self {
Self { content: html!() }
}
}
impl From<Html> for Backdrop {
fn from(content: Html) -> Self {
Self { content }
}
}
#[derive(Clone, PartialEq)]
pub struct Backdropper {
callback: Callback<Msg>,
}
impl Backdropper {
pub fn open<B>(&self, backdrop: B)
where
B: Into<Backdrop>,
{
self.callback.emit(Msg::Open(Rc::new(backdrop.into())));
}
pub fn close(&self) {
self.callback.emit(Msg::Close);
}
}
#[derive(Clone, PartialEq, Properties)]
pub struct BackdropProperties {
pub children: Html,
}
#[doc(hidden)]
enum Msg {
Open(Rc<Backdrop>),
Close,
}
#[function_component(BackdropViewer)]
pub fn backdrop_viewer(props: &BackdropProperties) -> Html {
let open = use_state::<Option<Rc<Backdrop>>, _>(|| None);
let ctx = {
let open = open.clone();
use_memo((), |()| Backdropper {
callback: Callback::from(move |msg| match msg {
Msg::Open(backdrop) => open.set(Some(backdrop)),
Msg::Close => open.set(None),
}),
})
};
use_effect_with(open.is_some(), |open| {
match open {
true => body_open(),
false => body_close(),
}
body_close
});
html!(
<ContextProvider<Backdropper> context={(*ctx).clone()}>
if let Some(open) = &*open {
<div class="pf-v6-c-backdrop">{ open.content.clone() }</div>
}
{ props.children.clone() }
</ContextProvider<Backdropper>>
)
}
fn body_open() {
if let Some(body) = document().body() {
let classes = js_sys::Array::of1(&JsValue::from_str("pf-v6-c-backdrop__open"));
body.class_list().add(&classes).ok();
}
}
fn body_close() {
if let Some(body) = document().body() {
let classes = js_sys::Array::of1(&JsValue::from_str("pf-v6-c-backdrop__open"));
body.class_list().remove(&classes).ok();
}
}
#[hook]
pub fn use_backdrop() -> Option<Backdropper> {
use_context::<Backdropper>()
}