LCOV - code coverage report
Current view: top level - dashql-app/src/ui/json - json_tool_state.tsx Coverage Total Hit
Test: DashQL 915828b Lines: 97.7 % 43 42
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import * as React from 'react';
       2              : 
       3              : type Action = Record<string, boolean>;
       4              : type Dispatch = (action: Action) => void;
       5              : type Listener = () => void;
       6              : 
       7              : /// Hover changes on every mouseenter and mouseleave.
       8              : /// We therefore keep the tool visibility in a store that notifies only the copy buttons of the changed nodes,
       9              : /// instead of a context value that re-renders every copy button of the tree.
      10            1 : export class ToolVisibilityStore {
      11            1 :     protected visible: Map<string, boolean> = new Map();
      12            1 :     protected listeners: Map<string, Set<Listener>> = new Map();
      13              : 
      14            1 :     public dispatch: Dispatch = (action: Action) => {
      15            1 :         for (const [key, value] of Object.entries(action)) {
      16            1 :             if ((this.visible.get(key) ?? false) === value) {
      17            0 :                 continue;
      18              :             }
      19            1 :             this.visible.set(key, value);
      20            1 :             for (const listener of this.listeners.get(key) ?? []) {
      21            1 :                 listener();
      22              :             }
      23            1 :         }
      24            1 :     };
      25            1 :     public subscribe(key: string, listener: Listener): () => void {
      26            1 :         let listeners = this.listeners.get(key);
      27            1 :         if (!listeners) {
      28            1 :             listeners = new Set();
      29            1 :             this.listeners.set(key, listeners);
      30            1 :         }
      31            1 :         listeners.add(listener);
      32            1 :         return () => {
      33            1 :             listeners.delete(listener);
      34            1 :             if (listeners.size == 0) {
      35            1 :                 this.listeners.delete(key);
      36              :             }
      37            1 :         };
      38            1 :     }
      39            1 :     public isVisible(key: string): boolean {
      40            1 :         return this.visible.get(key) ?? false;
      41            1 :     }
      42            1 : }
      43              : 
      44            1 : const Context = React.createContext<ToolVisibilityStore | null>(null);
      45              : 
      46            1 : export function useToolVisibility(key: string): boolean {
      47            1 :     const store = React.useContext(Context);
      48            1 :     const subscribe = React.useCallback((listener: Listener) => store?.subscribe(key, listener) ?? (() => { }), [store, key]);
      49            1 :     const getSnapshot = React.useCallback(() => store?.isVisible(key) ?? false, [store, key]);
      50            1 :     return React.useSyncExternalStore(subscribe, getSnapshot);
      51            1 : }
      52              : 
      53            1 : const noopDispatch: Dispatch = () => { };
      54              : 
      55            1 : export function useToolVisibilityDispatch(): Dispatch {
      56            1 :     return React.useContext(Context)?.dispatch ?? noopDispatch;
      57            1 : }
      58              : 
      59              : interface ShowToolsProps {
      60              :     store: ToolVisibilityStore;
      61              : }
      62              : 
      63            1 : export const ToolVisibilityStateProvider: React.FC<React.PropsWithChildren<ShowToolsProps>> = ({ store, children }) => {
      64            1 :     return <Context.Provider value={store}>{children}</Context.Provider>;
      65            1 : };
        

Generated by: LCOV version 2.0-1