├── .gitignore ├── package.json ├── LICENSE ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tiny-use-media", 3 | "description": "react hook for getting breakpoints state in runtime", 4 | "version": "1.0.5", 5 | "browser": "./index.js", 6 | "author": { 7 | "name": "Valeriy Komlev", 8 | "email": "komlev88@gmail.com", 9 | "url": "https://komlev.me/" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/komlev/tiny-use-media.git" 14 | }, 15 | "keywords": [ 16 | "react", 17 | "hooks", 18 | "media", 19 | "matchMedia", 20 | "breakpoint", 21 | "breakpoints", 22 | "useMedia" 23 | ], 24 | "license": "MIT", 25 | "scripts": { 26 | "publish": "clean-publish" 27 | }, 28 | "devDependencies": { 29 | "clean-publish": "^4.0.0" 30 | }, 31 | "peerDependencies": { 32 | "react": ">=16.8" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Valeriy Komlev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tiny-use-media 2 | 3 | Small (0.5 Kb) react hook for getting media breakpoints state info in runtime 4 | 5 | ## Usage 6 | 7 | ``` 8 | npm i tiny-use-media --save 9 | ``` 10 | 11 | Adn in your react code 12 | 13 | ```js 14 | import { useMedia } from "tiny-use-media"; 15 | 16 | // ... 17 | 18 | const { current, md, lg } = useMedia({ 19 | sm: 640, 20 | md: 768, 21 | lg: 1024, 22 | xl: 1280, 23 | }); 24 | 25 | console.log({ current, md, lg }); 26 | /* 27 | if you current screen size is 900px 28 | it will print: 29 | { current: 'md', md: true, lg: false } 30 | */ 31 | ``` 32 | 33 | ## API 34 | 35 | Input: 36 | 37 | ```js 38 | // object with breakpoints names/values 39 | const breakpointsConfig = { 40 | mobile: 320, // min-width for mobile 41 | tablet: 640, // min-width for tablet 42 | desktop: 1024, // min-width for desktop 43 | }; 44 | 45 | useMedia(breakpointsConfig); 46 | ``` 47 | 48 | Output: 49 | 50 | ```js 51 | const output = useMedia(breakpointsConfig); 52 | ``` 53 | 54 | Output contains "**current**" field which corresponds to a current breakpoint. 55 | 56 | It also contains boolean values for each provided breakpoint. 57 | 58 | E.g. output for screen size of 900px 59 | 60 | ```js 61 | { 62 | current: "tablet", 63 | mobile: true, 64 | tablet: true, 65 | desktop: false 66 | } 67 | ``` 68 | 69 | ## License 70 | 71 | MIT 72 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import { useMemo, useState, useEffect } from "react"; 2 | let isClient = typeof window !== "undefined", 3 | getCurrent = (queries) => { 4 | let index = queries.findIndex((query) => isClient && !query.q.matches), 5 | queryIndex = (~index ? index : queries.length) - 1; 6 | return queryIndex >= 0 ? queries[queryIndex].bp : void 0; 7 | }, 8 | getResult = (queries) => { 9 | let current = getCurrent(queries), 10 | currentIndex = queries.findIndex((query) => query.bp === current), 11 | res = queries.reduce((acc, q, index) => { 12 | acc[q.bp] = currentIndex >= index; 13 | return acc; 14 | }, {}); 15 | res.current = current; 16 | return res; 17 | }, 18 | useMedia = (breakpoints) => { 19 | let queries = useMemo( 20 | () => 21 | Object.keys(breakpoints) 22 | .sort((a, b) => +breakpoints[a] - +breakpoints[b]) 23 | .map((bp) => { 24 | let q = isClient 25 | ? window.matchMedia(`(min-width:${breakpoints[bp]}px)`) 26 | : void 0; 27 | return { q, bp }; 28 | }), 29 | Object.values(breakpoints) 30 | ); 31 | let [result, setResult] = useState(getResult(queries)); 32 | useEffect(() => { 33 | let handler = () => setResult(getResult(queries)); 34 | queries.forEach((query) => { 35 | try { 36 | query.q.addEventListener("change", handler); 37 | } catch (err) { 38 | query.q.addListener(handler); 39 | } 40 | }); 41 | return () => 42 | queries.forEach((query) => { 43 | try { 44 | query.q.removeEventListener("change", handler); 45 | } catch (err) { 46 | query.q.removeListener(handler); 47 | } 48 | }); 49 | }, [queries]); 50 | return result; 51 | }; 52 | export { useMedia }; 53 | --------------------------------------------------------------------------------