├── .gitignore ├── .github └── dependabot.yml ├── changelog.md ├── lib ├── index.d.ts └── index.js ├── tsconfig.json ├── package.json ├── src └── index.tsx └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # node.js 2 | # 3 | node_modules/ 4 | npm-debug.log 5 | yarn-error.log 6 | package-lock.json 7 | yarn.lock -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "23:30" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | #### Version 1.0.13 2 | 3 | 1. stupid package.json infinite loop fix 4 | 5 | 6 | #### Version 1.0.12 7 | 8 | 1. Removed the `react-native-device-info` as a peerDepenency 9 | 2. Added ChangeLog.md 10 | 3. Updated Readme.md 11 | 12 | 13 | -------------------------------------------------------------------------------- /lib/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { StatusBarProps } from 'react-native'; 3 | export interface SafeAreaDeciderProps { 4 | statusBarHiddenForNotch: boolean; 5 | statusBarHiddenForNonNotch: boolean; 6 | backgroundColor?: string; 7 | } 8 | declare const SafeAreaDecider: ({ statusBarHiddenForNotch, statusBarHiddenForNonNotch, backgroundColor, ...rest }: SafeAreaDeciderProps & StatusBarProps) => JSX.Element | null; 9 | export default SafeAreaDecider; 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "include": ["src"], 4 | "exclude": [ 5 | "node_modules", 6 | "babel.config.js", 7 | "metro.config.js", 8 | "jest.config.js" 9 | ], 10 | "compilerOptions": { 11 | "lib": ["es5", "es6", "esnext.asynciterable"], 12 | "allowSyntheticDefaultImports": false, 13 | "esModuleInterop": false, 14 | "jsx": "react", 15 | "moduleResolution": "node", 16 | "strict": true, 17 | "target": "esnext", 18 | "resolveJsonModule": true, 19 | "outDir": "./lib", 20 | "declaration": true 21 | } 22 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-smart-statusbar", 3 | "version": "1.0.24", 4 | "description": "The smart status bar for react-native that intelligently handles safe area across iOS and Android, background color etc", 5 | "main": "lib/index.js", 6 | "types": "lib", 7 | "scripts": { 8 | "build": "npm run prettier:write && tsc -p .", 9 | "prettier:base": "prettier --parser typescript --single-quote", 10 | "prettier:check": "npm run prettier:base -- --list-different \"src/**/*.tsx\"", 11 | "prettier:write": "npm run prettier:base -- --write \"src/**/*.tsx\"" 12 | }, 13 | "husky": { 14 | "hooks": { 15 | "pre-commit": "lint-staged" 16 | } 17 | }, 18 | "lint-staged": { 19 | "src/**/*.tsx": [ 20 | "npm run prettier:write", 21 | "git add" 22 | ] 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "git+https://github.com/irohitb/react-native-smart-statusbar.git" 27 | }, 28 | "keywords": [ 29 | "react-native", 30 | "status-bar", 31 | "react-native-status-bar", 32 | "safe-area", 33 | "safearea", 34 | "react-native-safe-area" 35 | ], 36 | "author": "", 37 | "license": "MIT", 38 | "bugs": { 39 | "url": "https://github.com/irohitb/react-native-smart-statusbar/issues" 40 | }, 41 | "devDependencies": { 42 | "@types/react-native": "^0.64.2", 43 | "husky": "^7.0.1", 44 | "lint-staged": "^10.2.10", 45 | "prettier": "^2.0.5", 46 | "typescript": "^4.1.3" 47 | }, 48 | "homepage": "https://github.com/irohitb/react-native-smart-statusbar#readme", 49 | "peerDependencies": { 50 | "react": ">=16.12.0", 51 | "react-native": ">=0.61", 52 | "react-native-device-info": ">=5.4.1" 53 | }, 54 | "dependencies": { 55 | "react-native-device-info": "^8.1.5" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import DeviceInfo from 'react-native-device-info'; 3 | import { View, StatusBar, Platform, Dimensions, } from 'react-native'; 4 | const SafeAreaDecider = ({ statusBarHiddenForNotch = false, statusBarHiddenForNonNotch = false, backgroundColor, ...rest }) => { 5 | const [state, setState] = React.useState({ 6 | navbarHeight: '', 7 | deviceHaveNotch: false, 8 | }); 9 | const isComponentMounted = React.useRef(true); 10 | React.useEffect(() => { 11 | async function setNotchProperties() { 12 | const deviceHaveNotch = await DeviceInfo.hasNotch(); 13 | if (isComponentMounted.current) { 14 | const iOSHeight = deviceHaveNotch ? 44 : 20; 15 | setState({ 16 | navbarHeight: iOSHeight, 17 | deviceHaveNotch: deviceHaveNotch, 18 | }); 19 | } 20 | else if (Platform.OS === 'android') { 21 | setState({ 22 | navbarHeight: StatusBar.currentHeight, 23 | deviceHaveNotch: deviceHaveNotch, 24 | }); 25 | } 26 | } 27 | setNotchProperties(); 28 | return () => { 29 | isComponentMounted.current = false; 30 | }; 31 | }, []); 32 | const { deviceHaveNotch, navbarHeight } = state; 33 | if (deviceHaveNotch) { 34 | return (React.createElement(View, { style: { 35 | height: navbarHeight || '', 36 | backgroundColor: backgroundColor, 37 | width: Dimensions.get('window').width, 38 | } }, 39 | React.createElement(StatusBar, { ...rest, translucent: true, hidden: statusBarHiddenForNotch }))); 40 | } 41 | else if (!deviceHaveNotch && Platform.OS === 'ios') { 42 | return (React.createElement(View, { style: { 43 | backgroundColor: backgroundColor, 44 | width: Dimensions.get('window').width, 45 | } }, 46 | React.createElement(StatusBar, { ...rest, translucent: true, hidden: statusBarHiddenForNonNotch }))); 47 | } 48 | else if (!deviceHaveNotch && Platform.OS === 'android') { 49 | return (React.createElement(StatusBar, { ...rest, backgroundColor: backgroundColor, hidden: statusBarHiddenForNonNotch })); 50 | } 51 | else { 52 | return null; 53 | } 54 | }; 55 | export default SafeAreaDecider; 56 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import DeviceInfo from 'react-native-device-info'; 3 | import { 4 | View, 5 | StatusBarProps, 6 | StatusBar, 7 | Platform, 8 | Dimensions, 9 | } from 'react-native'; 10 | 11 | export interface SafeAreaDeciderProps { 12 | statusBarHiddenForNotch: boolean; 13 | statusBarHiddenForNonNotch: boolean; 14 | backgroundColor?: string; 15 | } 16 | 17 | interface Istate { 18 | navbarHeight?: number | ''; //StatusBar.currentHeight gives undefined 19 | deviceHaveNotch: boolean; 20 | } 21 | const SafeAreaDecider = ({ 22 | statusBarHiddenForNotch = false, 23 | statusBarHiddenForNonNotch = false, 24 | backgroundColor, 25 | ...rest 26 | }: SafeAreaDeciderProps & StatusBarProps) => { 27 | const [state, setState] = React.useState({ 28 | navbarHeight: '', 29 | deviceHaveNotch: false, 30 | }); 31 | 32 | const isComponentMounted = React.useRef(true); 33 | React.useEffect(() => { 34 | async function setNotchProperties() { 35 | const deviceHaveNotch = await DeviceInfo.hasNotch(); 36 | if (isComponentMounted.current) { 37 | const iOSHeight = deviceHaveNotch ? 44 : 20; 38 | setState({ 39 | navbarHeight: iOSHeight, 40 | deviceHaveNotch: deviceHaveNotch, 41 | }); 42 | } else if (Platform.OS === 'android') { 43 | setState({ 44 | navbarHeight: StatusBar.currentHeight, 45 | deviceHaveNotch: deviceHaveNotch, 46 | }); 47 | } 48 | } 49 | setNotchProperties(); 50 | return () => { 51 | isComponentMounted.current = false; 52 | }; 53 | }, []); 54 | const { deviceHaveNotch, navbarHeight } = state; 55 | if (deviceHaveNotch) { 56 | return ( 57 | 64 | 66 | ); 67 | } else if (!deviceHaveNotch && Platform.OS === 'ios') { 68 | return ( 69 | 75 | 77 | ); 78 | } else if (!deviceHaveNotch && Platform.OS === 'android') { 79 | return ( 80 |