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 };