LCOV - code coverage report
Current view: top level - dashql-app/src/ui/foundations - row_context_menu.ts Coverage Total Hit
Test: DashQL 915828b Lines: 100.0 % 27 27
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import * as React from 'react';
       2              : 
       3              : /// The right click of a row that opens the action menu of the row.
       4              : /// The row spreads `onContextMenu`, its action menu registers its opener with `useRowContextMenuOpener`.
       5              : export interface RowContextMenu {
       6              :     /// The handler of the right click of the row
       7              :     onContextMenu: (event: React.MouseEvent<HTMLElement>) => void;
       8              :     /// The opener of the action menu, null while no menu is registered
       9              :     openerRef: React.RefObject<(() => void) | null>;
      10              : }
      11              : 
      12              : /// Create the right click of a row
      13            1 : export function useRowContextMenu(): RowContextMenu {
      14            1 :     const openerRef = React.useRef<(() => void) | null>(null);
      15            1 :     const onContextMenu = React.useCallback((event: React.MouseEvent<HTMLElement>) => {
      16            1 :         const open = openerRef.current;
      17            1 :         if (open == null || !opensRowContextMenu(event)) return;
      18            1 :         event.preventDefault();
      19            1 :         open();
      20            1 :     }, []);
      21            1 :     return React.useMemo(() => ({ onContextMenu, openerRef }), [onContextMenu]);
      22            1 : }
      23              : 
      24              : /// Register the opener of the action menu of a row
      25            1 : export function useRowContextMenuOpener(menu: RowContextMenu | undefined, open: () => void): void {
      26            1 :     const openRef = React.useRef(open);
      27            1 :     openRef.current = open;
      28            1 :     React.useEffect(() => {
      29            1 :         if (menu == null) return;
      30            1 :         const opener = () => openRef.current();
      31            1 :         menu.openerRef.current = opener;
      32            1 :         return () => {
      33            1 :             if (menu.openerRef.current === opener) menu.openerRef.current = null;
      34            1 :         };
      35            1 :     }, [menu]);
      36            1 : }
      37              : 
      38              : // React bubbles the events of the portaled overlays through the row, those keep their own right click.
      39              : // Text fields and editors keep the native menu with copy and paste.
      40            1 : function opensRowContextMenu(event: React.MouseEvent<HTMLElement>): boolean {
      41            1 :     const target = event.target;
      42            1 :     if (!(target instanceof Element) || !event.currentTarget.contains(target)) return false;
      43            1 :     return target.closest('input, textarea, select, [contenteditable]:not([contenteditable="false"])') == null;
      44            1 : }
        

Generated by: LCOV version 2.0-1