use dioxus::prelude::*;
use super::registry::{RectRefresh, ZoneRegistry};
use super::state::{DndContext, DragState};
use super::types::{DragId, Point, ZoneId};
pub fn use_dnd_provider<T: Clone + 'static>() -> DndContext<T> {
let state = use_store(DragState::<T>::default);
let announcement = use_signal(String::new);
let registry = use_context_provider(|| ZoneRegistry::<T>::from_signal(Signal::new(Vec::new())));
let ctx = use_context_provider(move || DndContext::from_parts(state, announcement));
use_rect_refresh_provider();
use_rect_refresh_thunk(move |_| {
if ctx.dragging() {
registry.refresh_rects();
}
});
ctx
}
pub(crate) fn use_rect_refresh_provider() -> RectRefresh {
let bus = use_hook(|| {
try_consume_context::<RectRefresh>()
.unwrap_or_else(|| RectRefresh::from_signal(Signal::new(Vec::new())))
});
use_context_provider(|| bus);
bus
}
pub(crate) fn use_rect_refresh_thunk(thunk: impl FnMut(()) + 'static) {
let joined = use_hook(move || {
try_consume_context::<RectRefresh>().map(|mut bus| {
let key = DragId::auto().0;
bus.register(key, Callback::new(thunk));
(bus, key)
})
});
use_drop(move || {
if let Some((mut bus, key)) = joined {
bus.unregister(key);
}
});
}
pub fn use_rect_refresh() -> RectRefresh {
use_context()
}
pub fn use_dnd<T: Clone + 'static>() -> DndContext<T> {
use_context()
}
pub fn use_zone_registry<T: Clone + 'static>() -> ZoneRegistry<T> {
use_context()
}
pub fn use_zone_id() -> ZoneId {
use_hook(ZoneId::auto)
}
pub fn client_point(evt: &DragEvent) -> Point {
let c = evt.client_coordinates();
Point::new(c.x, c.y)
}
pub fn element_point(evt: &DragEvent) -> Point {
let c = evt.element_coordinates();
Point::new(c.x, c.y)
}