react-window-size-listener
Version:
Minimalistic React hook for listening to window resize events with built-in debouncing.
1 lines • 5.6 kB
Source Map (JSON)
{"version":3,"file":"index.modern.mjs","sources":["../src/index.ts"],"sourcesContent":["import { useState, useEffect } from 'react';\n\nexport interface WindowSize {\n width: number;\n height: number;\n}\n\nexport interface UseWindowSizeOptions {\n /**\n * Amount of time in milliseconds to wait before updating the state after the last resize event.\n * Defaults to 100ms.\n */\n debounceTime?: number;\n}\n\n/**\n * Hook that tracks the window size (window.innerWidth/Height) with optional debouncing.\n *\n * @param options Configuration options\n * @returns Object containing `width` and `height` of the window.\n */\nexport function useWindowSize(options: UseWindowSizeOptions = {}): WindowSize {\n const { debounceTime = 100 } = options;\n\n const [windowSize, setWindowSize] = useState<WindowSize>(() => {\n if (typeof window !== 'undefined') {\n return {\n width: window.innerWidth,\n height: window.innerHeight,\n };\n }\n return { width: 0, height: 0 };\n });\n\n useEffect(() => {\n if (typeof window === 'undefined') {\n return;\n }\n\n let timeoutId: number | null = null;\n\n const handleResize = () => {\n if (timeoutId) {\n window.clearTimeout(timeoutId);\n }\n\n timeoutId = window.setTimeout(() => {\n setWindowSize({\n width: window.innerWidth,\n height: window.innerHeight,\n });\n }, debounceTime);\n };\n\n window.addEventListener(\"resize\", handleResize);\n\n return () => {\n window.removeEventListener(\"resize\", handleResize);\n if (timeoutId) {\n window.clearTimeout(timeoutId);\n }\n };\n }, [debounceTime]);\n\n return windowSize;\n}\n\n/**\n * Hook that tracks the visual viewport size with optional debouncing.\n * Uses the Visual Viewport API which accounts for pinch-zoom, on-screen keyboards,\n * and browser chrome on mobile devices.\n * Falls back to window.innerWidth/Height if Visual Viewport API is not available.\n *\n * @param options Configuration options\n * @returns Object containing `width` and `height` of the visual viewport.\n */\nexport function useViewportSize(options: UseWindowSizeOptions = {}): WindowSize {\n const { debounceTime = 100 } = options;\n\n const [viewportSize, setViewportSize] = useState<WindowSize>(() => {\n if (typeof window === 'undefined') {\n return { width: 0, height: 0 };\n }\n if (window.visualViewport) {\n return {\n width: window.visualViewport.width,\n height: window.visualViewport.height,\n };\n }\n return {\n width: window.innerWidth,\n height: window.innerHeight,\n };\n });\n\n useEffect(() => {\n if (typeof window === 'undefined') {\n return;\n }\n\n let timeoutId: number | null = null;\n\n const handleResize = () => {\n if (timeoutId) {\n window.clearTimeout(timeoutId);\n }\n\n timeoutId = window.setTimeout(() => {\n if (window.visualViewport) {\n setViewportSize({\n width: window.visualViewport.width,\n height: window.visualViewport.height,\n });\n } else {\n setViewportSize({\n width: window.innerWidth,\n height: window.innerHeight,\n });\n }\n }, debounceTime);\n };\n\n // Use Visual Viewport API if available, otherwise fallback to window\n const target = window.visualViewport || window;\n target.addEventListener(\"resize\", handleResize);\n\n // For visual viewport, also listen to scroll events (viewport position changes during pinch-zoom)\n if (window.visualViewport) {\n window.visualViewport.addEventListener(\"scroll\", handleResize);\n }\n\n return () => {\n target.removeEventListener(\"resize\", handleResize);\n if (window.visualViewport) {\n window.visualViewport.removeEventListener(\"scroll\", handleResize);\n }\n if (timeoutId) {\n window.clearTimeout(timeoutId);\n }\n };\n }, [debounceTime]);\n\n return viewportSize;\n}\n"],"names":["useWindowSize","options","debounceTime","windowSize","setWindowSize","useState","window","width","innerWidth","height","innerHeight","useEffect","timeoutId","handleResize","clearTimeout","setTimeout","addEventListener","removeEventListener","useViewportSize","viewportSize","setViewportSize","visualViewport","target"],"mappings":"gDAqBgB,SAAAA,EAAcC,EAAgC,IAC5D,MAAMC,aAAEA,EAAe,KAAQD,GAExBE,EAAYC,GAAiBC,EAAqB,IACjC,oBAAXC,OACF,CACLC,MAAOD,OAAOE,WACdC,OAAQH,OAAOI,aAGZ,CAAEH,MAAO,EAAGE,OAAQ,IAiC7B,OA9BAE,EAAU,KACR,GAAsB,oBAAXL,OACT,OAGF,IAAIM,EAA2B,KAE/B,MAAMC,EAAeA,KACfD,GACFN,OAAOQ,aAAaF,GAGtBA,EAAYN,OAAOS,WAAW,KAC5BX,EAAc,CACZG,MAAOD,OAAOE,WACdC,OAAQH,OAAOI,eAEhBR,IAKL,OAFAI,OAAOU,iBAAiB,SAAUH,GAE3B,KACLP,OAAOW,oBAAoB,SAAUJ,GACjCD,GACFN,OAAOQ,aAAaF,KAGvB,CAACV,IAEGC,CACT,UAWgBe,EAAgBjB,EAAgC,CAAA,GAC9D,MAAMC,aAAEA,EAAe,KAAQD,GAExBkB,EAAcC,GAAmBf,EAAqB,IACrC,oBAAXC,OACF,CAAEC,MAAO,EAAGE,OAAQ,GAEzBH,OAAOe,eACF,CACLd,MAAOD,OAAOe,eAAed,MAC7BE,OAAQH,OAAOe,eAAeZ,QAG3B,CACLF,MAAOD,OAAOE,WACdC,OAAQH,OAAOI,cAmDnB,OA/CAC,EAAU,KACR,GAAsB,oBAAXL,OACT,OAGF,IAAIM,EAA2B,KAE/B,MAAMC,EAAeA,KACfD,GACFN,OAAOQ,aAAaF,GAGtBA,EAAYN,OAAOS,WAAW,KACxBT,OAAOe,eACTD,EAAgB,CACdb,MAAOD,OAAOe,eAAed,MAC7BE,OAAQH,OAAOe,eAAeZ,SAGhCW,EAAgB,CACdb,MAAOD,OAAOE,WACdC,OAAQH,OAAOI,eAGlBR,IAICoB,EAAShB,OAAOe,gBAAkBf,OAQxC,OAPAgB,EAAON,iBAAiB,SAAUH,GAG9BP,OAAOe,gBACTf,OAAOe,eAAeL,iBAAiB,SAAUH,GAG5C,KACLS,EAAOL,oBAAoB,SAAUJ,GACjCP,OAAOe,gBACTf,OAAOe,eAAeJ,oBAAoB,SAAUJ,GAElDD,GACFN,OAAOQ,aAAaF,KAGvB,CAACV,IAEGiB,CACT"}