(props: ContextMenuContentProps)
| 410 | /// - `data-state`: Indicates if the state of the context menu. Values are `open` or `closed`. |
| 411 | #[component] |
| 412 | pub fn ContextMenuContent(props: ContextMenuContentProps) -> Element { |
| 413 | let mut ctx: ContextMenuCtx = use_context(); |
| 414 | let position = ctx.position; |
| 415 | let (x, y) = position(); |
| 416 | |
| 417 | let open = ctx.open; |
| 418 | |
| 419 | let onkeydown = move |event: Event<KeyboardData>| { |
| 420 | match event.key() { |
| 421 | Key::Escape => ctx.focus.clear_focus(), |
| 422 | Key::ArrowDown => { |
| 423 | ctx.focus.focus_next(); |
| 424 | } |
| 425 | Key::ArrowUp => { |
| 426 | if open() { |
| 427 | ctx.focus.focus_prev(); |
| 428 | } |
| 429 | } |
| 430 | Key::Home => ctx.focus.focus_first(), |
| 431 | Key::End => ctx.focus.focus_last(), |
| 432 | _ => return, |
| 433 | } |
| 434 | event.prevent_default(); |
| 435 | }; |
| 436 | |
| 437 | let mut menu_ref: Signal<Option<std::rc::Rc<MountedData>>> = use_signal(|| None); |
| 438 | let focused = move || open() && !ctx.focus.any_focused(); |
| 439 | // If the menu is open, but no item is focused, focus the div itself to capture events |
| 440 | use_effect(move || { |
| 441 | let Some(menu) = menu_ref() else { |
| 442 | return; |
| 443 | }; |
| 444 | if focused() { |
| 445 | spawn(async move { |
| 446 | // Focus the menu itself to capture keyboard events |
| 447 | _ = menu.set_focus(true).await; |
| 448 | }); |
| 449 | } |
| 450 | }); |
| 451 | |
| 452 | let unique_id = use_unique_id(); |
| 453 | let id = use_id_or(unique_id, props.id); |
| 454 | |
| 455 | let render = use_animated_open(id, open); |
| 456 | |
| 457 | use_outside_dismiss(ctx.root_id, move || { |
| 458 | ctx.focus.clear_focus(); |
| 459 | ctx.set_open.call(false); |
| 460 | }); |
| 461 | |
| 462 | // A `position: fixed` menu pinned to a click point drifts away from the |
| 463 | // click target as soon as the page scrolls. Native context menus block |
| 464 | // scroll while open; match that by suppressing wheel/touchmove outside |
| 465 | // the menu without mutating page-level overflow styles. |
| 466 | use_effect_with_cleanup(move || { |
| 467 | if !open() { |
| 468 | return Box::new(|| {}) as Box<dyn FnOnce()>; |
| 469 | } |
nothing calls this directly
no test coverage detected