github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/ui/dashboard/src/hooks/useBreakpoint.tsx (about)

     1  import React from "react";
     2  import useWindowSize from "./useWindowSize";
     3  import { useCallback, useEffect, useState } from "react";
     4  
     5  type IBreakpointContext = {
     6    currentBreakpoint: string | null;
     7    maxBreakpoint(breakpointAndDown: string): boolean;
     8    minBreakpoint(breakpointAndUp: string): boolean;
     9    width: number;
    10  };
    11  
    12  const BreakpointContext = React.createContext<IBreakpointContext | null>(null);
    13  
    14  const smBreakpoint = 640;
    15  const mdBreakpoint = 768;
    16  const lgBreakpoint = 1024;
    17  const xlBreakpoint = 1280;
    18  const xxlBreakpoint = 1536;
    19  
    20  const getBreakpoint = (width: number) => {
    21    if (width === 0) return null;
    22    if (width < smBreakpoint) return "xs";
    23    if (width < mdBreakpoint) return "sm";
    24    if (width < lgBreakpoint) return "md";
    25    if (width < xlBreakpoint) return "lg";
    26    if (width < xxlBreakpoint) return "xl";
    27    if (width >= xxlBreakpoint) return "2xl";
    28    return null;
    29  };
    30  
    31  const checkMaxBreakpoint = (
    32    currentBreakpoint: string | null,
    33    breakpointAndDown: string
    34  ): boolean => {
    35    // If we have no current breakpoint, return false
    36    if (!currentBreakpoint) return false;
    37    // We always display xxl
    38    if (breakpointAndDown === "2xl") return true;
    39    // If xl and down, then check if current breakpoint is less than xl
    40    if (breakpointAndDown === "xl") {
    41      return currentBreakpoint !== "2xl";
    42    }
    43    // If lg and down, then check if current breakpoint is less than xl
    44    if (breakpointAndDown === "lg") {
    45      return currentBreakpoint !== "xl";
    46    }
    47    // If md and down, then check if current breakpoint is less than lg
    48    if (breakpointAndDown === "md") {
    49      return !(currentBreakpoint === "lg" || currentBreakpoint === "xl");
    50    }
    51    // If sm and down, then check if current breakpoint is less than md
    52    if (breakpointAndDown === "sm") {
    53      return !(
    54        currentBreakpoint === "md" ||
    55        currentBreakpoint === "lg" ||
    56        currentBreakpoint === "xl"
    57      );
    58    }
    59    // If xs and down, then check if current breakpoint is less than sm
    60    if (breakpointAndDown === "xs") {
    61      return !(
    62        currentBreakpoint === "sm" ||
    63        currentBreakpoint === "md" ||
    64        currentBreakpoint === "lg" ||
    65        currentBreakpoint === "xl"
    66      );
    67    }
    68    // Else it's an unknown breakpoint and down, so return false
    69    return false;
    70  };
    71  
    72  const checkMinBreakpoint = (
    73    currentBreakpoint: string | null,
    74    breakpointAndUp: string
    75  ): boolean => {
    76    // If we have no current breakpoint, return false
    77    if (!currentBreakpoint) return false;
    78    // We always display xs
    79    if (breakpointAndUp === "xs") return true;
    80    // If sm and up, then check if current breakpoint is less than sm
    81    if (breakpointAndUp === "sm") {
    82      return currentBreakpoint !== "xs";
    83    }
    84    // If md and up, then check if current breakpoint is less than md
    85    if (breakpointAndUp === "md") {
    86      return !(currentBreakpoint === "xs" || currentBreakpoint === "sm");
    87    }
    88    // If lg and up, then check if current breakpoint is less than lg
    89    if (breakpointAndUp === "lg") {
    90      return !(
    91        currentBreakpoint === "xs" ||
    92        currentBreakpoint === "sm" ||
    93        currentBreakpoint === "md"
    94      );
    95    }
    96    // If xl and up, then check if current breakpoint is less than xl
    97    if (breakpointAndUp === "xl") {
    98      return !(
    99        currentBreakpoint === "xs" ||
   100        currentBreakpoint === "sm" ||
   101        currentBreakpoint === "md" ||
   102        currentBreakpoint === "lg"
   103      );
   104    }
   105    // If xl and up, then check if current breakpoint is less than xl
   106    if (breakpointAndUp === "2xl") {
   107      return !(
   108        currentBreakpoint === "xs" ||
   109        currentBreakpoint === "sm" ||
   110        currentBreakpoint === "md" ||
   111        currentBreakpoint === "lg" ||
   112        currentBreakpoint === "xl"
   113      );
   114    }
   115    // Else it's an unknown breakpoint and up, so return false
   116    return false;
   117  };
   118  
   119  const BreakpointProvider = ({ children }: { children: React.ReactNode }) => {
   120    const [width] = useWindowSize();
   121    const [currentBreakpoint, setCurrentBreakpoint] = useState(
   122      getBreakpoint(width)
   123    );
   124    useEffect(() => {
   125      setCurrentBreakpoint(getBreakpoint(width));
   126    }, [width]);
   127    const maxBreakpoint = useCallback(
   128      (breakpointAndDown) =>
   129        checkMaxBreakpoint(currentBreakpoint, breakpointAndDown),
   130      [currentBreakpoint]
   131    );
   132    const minBreakpoint = useCallback(
   133      (breakpointAndUp) => checkMinBreakpoint(currentBreakpoint, breakpointAndUp),
   134      [currentBreakpoint]
   135    );
   136    return (
   137      <BreakpointContext.Provider
   138        value={{
   139          currentBreakpoint,
   140          maxBreakpoint,
   141          minBreakpoint,
   142          width,
   143        }}
   144      >
   145        {children}
   146      </BreakpointContext.Provider>
   147    );
   148  };
   149  
   150  const useBreakpoint = () => {
   151    const context = React.useContext(BreakpointContext);
   152    if (context === undefined) {
   153      throw new Error("useBreakpoint must be used within a BreakpointContext");
   154    }
   155    return context as IBreakpointContext;
   156  };
   157  
   158  export { BreakpointProvider, useBreakpoint };