use leptos::prelude::*; use web_sys::MouseEvent; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; // ── Kendi reaktif Context Menu implementasyonumuz ── // leptos-shadcn-context-menu v0.8.1'de ContextMenuContent'te // `if open.get()` statik kontrolü reaktif değil. Aşağıda // `Show` bileşeni ile düzgün reaktif versiyon yer alıyor. #[component] pub fn TorrentContextMenu( children: Children, torrent_hash: String, on_action: Callback<(String, String)>, ) -> impl IntoView { let hash = StoredValue::new(torrent_hash); let on_action = StoredValue::new(on_action); let open = RwSignal::new(false); let position = RwSignal::new((0i32, 0i32)); // Sağ tıklama handler let on_contextmenu = move |e: MouseEvent| { e.prevent_default(); e.stop_propagation(); position.set((e.client_x(), e.client_y())); open.set(true); }; // Menü dışına tıklandığında kapanma Effect::new(move |_| { if open.get() { let cb = Closure::wrap(Box::new(move |_: MouseEvent| { open.set(false); }) as Box); let window = web_sys::window().unwrap(); let document = window.document().unwrap(); let _ = document.add_event_listener_with_callback( "click", cb.as_ref().unchecked_ref(), ); // Cleanup: tek sefer dinleyici — click yakalandığında otomatik kapanıp listener kalıyor // ama open=false olduğunda effect tekrar çalışmaz, böylece sorun yok. cb.forget(); } }); let menu_action = move |action: &'static str| { open.set(false); on_action.get_value().run((action.to_string(), hash.get_value())); }; view! {
{children()}
{ let (x, y) = position.get(); // Menü yaklaşık boyutları let menu_width = 200; let menu_height = 220; let window = web_sys::window().unwrap(); let vw = window.inner_width().unwrap().as_f64().unwrap() as i32; let vh = window.inner_height().unwrap().as_f64().unwrap() as i32; // Sağa taşarsa sola aç, alta taşarsa yukarı aç let final_x = if x + menu_width > vw { x - menu_width } else { x }; let final_y = if y + menu_height > vh { y - menu_height } else { y }; let final_x = final_x.max(0); let final_y = final_y.max(0); view! {
// Start
"Start"
// Stop
"Stop"
// Recheck
"Recheck"
// Separator
// Remove
"Remove"
// Remove with Data
"Remove with Data"
} } } }