All files / apps/host/src/contexts FabContext.tsx

75% Statements 24/32
100% Branches 2/2
62.5% Functions 10/16
79.16% Lines 19/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61                                      5x   5x 87x 86x 2x   84x       5x 47x   5x 40x     5x       5x                 5x 16x 16x   16x 16x 16x   16x    
import React, { ReactNode, useEffect, useMemo, useState } from 'react';
 
import { createContext, useContextSelector } from 'use-context-selector';
 
export interface FabState {
  fabOffset: number;
  fabHidden: boolean;
}
 
export interface FabActions {
  setFabOffset: (offset: number) => void;
  setFabHidden: (hidden: boolean) => void;
}
 
interface FabContextValue {
  state: FabState;
  actions: FabActions;
}
 
const FabContext = createContext<FabContextValue | null>(null);
 
const useFabSelector = <T,>(selector: (ctx: FabContextValue) => T): T => {
  return useContextSelector(FabContext, ctx => {
    if (!ctx) {
      throw new Error('useFabSelector must be used within a FabProvider');
    }
    return selector(ctx);
  });
};
 
export const useFabStateSelector = <T,>(selector: (state: FabState) => T): T =>
  useFabSelector(ctx => selector(ctx.state));
 
export const useFabActionsSelector = <T,>(selector: (actions: FabActions) => T): T =>
  useFabSelector(ctx => selector(ctx.actions));
 
/** Setter passed down to remotes so they can anchor the FAB above their bottom button. */
export const useSetFabOffset = (): ((offset: number) => void) =>
  useFabActionsSelector(a => a.setFabOffset);
 
/** Hides the chat FAB while `hidden` is true; always restores it on unmount. */
export const useFabHidden = (hidden: boolean): void => {
  const setFabHidden = useFabActionsSelector(a => a.setFabHidden);
 
  useEffect(() => {
    setFabHidden(hidden);
    return () => setFabHidden(false);
  }, [hidden, setFabHidden]);
};
 
export const FabProvider = ({ children }: { children: ReactNode }) => {
  const [fabOffset, setFabOffset] = useState(0);
  const [fabHidden, setFabHidden] = useState(false);
 
  const state = useMemo<FabState>(() => ({ fabOffset, fabHidden }), [fabOffset, fabHidden]);
  const actions = useMemo<FabActions>(() => ({ setFabOffset, setFabHidden }), []);
  const value = useMemo<FabContextValue>(() => ({ state, actions }), [state, actions]);
 
  return <FabContext.Provider value={value}>{children}</FabContext.Provider>;
};