├── .gitattributes ├── .gitignore ├── .github ├── docs │ └── logo.png └── workflows │ ├── size.yml │ └── main.yml ├── .lintstagedrc.json ├── .huskyrc.json ├── .eslintignore ├── src ├── types.ts ├── modules.d.ts └── index.tsx ├── .editorconfig ├── test └── usePlatform.test.tsx ├── .eslintrc.js ├── LICENSE ├── CONTRIBUTING.md ├── tsconfig.json ├── package.json └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.{ts,tsx} text eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | .DS_Store 3 | node_modules 4 | .cache 5 | dist 6 | -------------------------------------------------------------------------------- /.github/docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraBeatris/use-platform/HEAD/.github/docs/logo.png -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "src/**/*.{ts,tsx}": [ 3 | "yarn lint", 4 | "git add" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.huskyrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "pre-commit": "lint-staged", 4 | "pre-push": "yarn lint" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Lint all files except .eslintrc.js 2 | !.eslintrc.js 3 | 4 | # Dependencies 5 | node_modules/ 6 | 7 | # Build Output 8 | dist/ 9 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | export interface UsePlatformPayload { 2 | isIOS: boolean; 3 | isLinux: boolean; 4 | isWindows: boolean; 5 | isAndroid: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /.github/workflows/size.yml: -------------------------------------------------------------------------------- 1 | name: size 2 | on: [pull_request] 3 | jobs: 4 | size: 5 | runs-on: ubuntu-latest 6 | env: 7 | CI_JOB_NUMBER: 1 8 | steps: 9 | - uses: actions/checkout@v1 10 | - uses: andresz1/size-limit-action@v1 11 | with: 12 | github_token: ${{ secrets.GITHUB_TOKEN }} 13 | -------------------------------------------------------------------------------- /src/modules.d.ts: -------------------------------------------------------------------------------- 1 | const [isLinux, isWindows]: Array<() => boolean>; 2 | 3 | const [isIOS, isAndroid]: Array; 4 | 5 | declare module "is-ios" { 6 | export default isIOS; 7 | } 8 | 9 | declare module "is-linux" { 10 | export default isLinux; 11 | } 12 | 13 | declare module "is-android" { 14 | export default isAndroid; 15 | } 16 | 17 | declare module "is-windows" { 18 | export default isWindows; 19 | } 20 | -------------------------------------------------------------------------------- /test/usePlatform.test.tsx: -------------------------------------------------------------------------------- 1 | import { renderHook } from "@testing-library/react-hooks"; 2 | 3 | import usePlatform from "../src"; 4 | 5 | const platformFlags = ["isIOS", "isLinux", "isWindows", "isAndroid"]; 6 | 7 | describe("usePlatform", () => { 8 | it("should support all platforms", () => { 9 | const { result } = renderHook(() => usePlatform()); 10 | 11 | platformFlags.forEach((flag) => { 12 | expect(result.current).toHaveProperty(flag); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | "plugin:@typescript-eslint/recommended", 4 | "@jungsoft/eslint-config/react", 5 | "@jungsoft/eslint-config/typescript", 6 | ], 7 | rules: { 8 | "react/react-in-jsx-scope": "off", 9 | "one-var": [2, { 10 | const: "never", 11 | }], 12 | "@typescript-eslint/explicit-function-return-type": "off", 13 | }, 14 | settings: { 15 | "import/resolver": { 16 | typescript: {}, 17 | node: { 18 | extensions: [ 19 | ".ts", 20 | ".tsx", 21 | ], 22 | }, 23 | }, 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push] 3 | jobs: 4 | build: 5 | name: Build, lint, and test on Node ${{ matrix.node }} and ${{ matrix.os }} 6 | 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | matrix: 10 | node: ['10.x', '12.x', '14.x'] 11 | os: [ubuntu-latest, windows-latest, macOS-latest] 12 | 13 | steps: 14 | - name: Checkout repo 15 | uses: actions/checkout@v2 16 | 17 | - name: Use Node ${{ matrix.node }} 18 | uses: actions/setup-node@v1 19 | with: 20 | node-version: ${{ matrix.node }} 21 | 22 | - name: Install deps and build (with cache) 23 | uses: bahmutov/npm-install@v1 24 | 25 | - name: Lint 26 | run: yarn lint 27 | 28 | - name: Test 29 | run: yarn test --ci --coverage --maxWorkers=2 30 | 31 | - name: Build 32 | run: yarn build 33 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import { useMemo } from "react"; 2 | import isIOS from "is-ios"; 3 | import isLinux from "is-linux"; 4 | import isAndroid from "is-android"; 5 | import isWindows from "is-windows"; 6 | 7 | import { UsePlatformPayload } from "./types"; 8 | 9 | /** 10 | * Modern mac computers return the following navigator: MacIntel 11 | * 12 | * But the old ones return: 13 | * - Mac68K Macintosh 68K system. 14 | * - MacPPC Macintosh PowerPC system. 15 | * 16 | * So we should always check for the "MAC" string in order to detect 17 | * an Mac device 18 | */ 19 | const isMac = navigator 20 | .platform 21 | .toUpperCase() 22 | .includes("MAC"); 23 | 24 | /** 25 | * Returns an object with user agent platform flags 26 | */ 27 | const usePlatform = () => useMemo(() => ({ 28 | isIOS, 29 | isMac, 30 | isLinux: isLinux(), 31 | isWindows: isWindows(), 32 | isAndroid, 33 | }), []); 34 | 35 | export default usePlatform; 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Laura Beatris 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 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thanks you so much for your interest in contributing to this project! 4 | 5 | ## About our deal 6 | 7 | Hi! I'm Laura and i'm the creator and maintainer of this project. 8 | 9 | If you encounter bugs, please **do** open an issue describing the bug and including steps to easily reproduce it (bonus points for a CodeSandbox that demonstrates the problem). 10 | 11 | If you have an idea for an enhancement, go ahead and share it via an issue, but please don't expect a timely response. 12 | 13 | This project is MIT-licensed, and this means that you can implement and use whatever enhancements you'd like. 14 | 15 | ## Commits and Code Style 16 | 17 | [Husky](https://github.com/typicode/husky) execute scrips according to git hooks in order to test if a developer is following the [Eslint Lint Rules](https://github.com/LauraBeatris/gobarber-web/blob/master/.eslintrc.js). 18 | 19 | ## Bug reports 20 | 21 | If you encounter a problem with this project, please open an issue. Be sure to include: 22 | 23 | - Package version 24 | - Node and React versions 25 | - Brief but thorough description of the issue 26 | - Link to a CodeSandbox (or similar) demonstrating the problem (optional, but highly recommended, especially for complex problems) 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // see https://www.typescriptlang.org/tsconfig to better understand tsconfigs 3 | "include": ["src", "types"], 4 | "compilerOptions": { 5 | "module": "esnext", 6 | "lib": ["dom", "esnext"], 7 | "importHelpers": true, 8 | // output .d.ts declaration files for consumers 9 | "declaration": true, 10 | // output .js.map sourcemap files for consumers 11 | "sourceMap": true, 12 | // match output dir to input dir. e.g. dist/index instead of dist/src/index 13 | "rootDir": "./src", 14 | // stricter type-checking for stronger correctness. Recommended by TS 15 | "strict": true, 16 | // linter checks for common issues 17 | "noImplicitReturns": true, 18 | "noFallthroughCasesInSwitch": true, 19 | // noUnused* overlap with @typescript-eslint/no-unused-vars, can disable if duplicative 20 | "noUnusedLocals": true, 21 | "noUnusedParameters": true, 22 | // use Node's module resolution algorithm, instead of the legacy TS one 23 | "moduleResolution": "node", 24 | // transpile JSX to React.createElement 25 | "jsx": "react", 26 | // interop between ESM and CJS modules. Recommended by TS 27 | "esModuleInterop": true, 28 | // significant perf increase by skipping checking .d.ts files, particularly those in node_modules. Recommended by TS 29 | "skipLibCheck": true, 30 | // error out if import and file system have a casing mismatch. Recommended by TS 31 | "forceConsistentCasingInFileNames": true, 32 | // `tsdx build` ignores this option, but it is commonly used when type-checking separately with `tsc` 33 | "noEmit": true, 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "license": "MIT", 4 | "main": "dist/index.js", 5 | "typings": "dist/index.d.ts", 6 | "files": [ 7 | "dist", 8 | "src" 9 | ], 10 | "engines": { 11 | "node": ">=10" 12 | }, 13 | "scripts": { 14 | "start": "tsdx watch", 15 | "build": "tsdx build", 16 | "test": "tsdx test --passWithNoTests", 17 | "lint": "eslint ./ --ext=.ts,.tsx --fix", 18 | "prepare": "tsdx build", 19 | "size": "size-limit", 20 | "analyze": "size-limit --why" 21 | }, 22 | "peerDependencies": { 23 | "react": ">=16" 24 | }, 25 | "name": "use-platform", 26 | "author": "Laura Beatris", 27 | "module": "dist/use-platform.esm.js", 28 | "size-limit": [ 29 | { 30 | "path": "dist/use-platform.cjs.production.min.js", 31 | "limit": "10 KB" 32 | }, 33 | { 34 | "path": "dist/use-platform.esm.js", 35 | "limit": "10 KB" 36 | } 37 | ], 38 | "devDependencies": { 39 | "@jungsoft/eslint-config": "4.0.1", 40 | "@size-limit/preset-small-lib": "^4.7.0", 41 | "@testing-library/react-hooks": "^3.4.2", 42 | "@types/react": "^16.9.56", 43 | "@types/react-dom": "^16.9.9", 44 | "@typescript-eslint/eslint-plugin": "^4.4.1", 45 | "@typescript-eslint/parser": "^4.4.1", 46 | "babel-eslint": "^10.1.0", 47 | "eslint": "^7.13.0", 48 | "eslint-config-airbnb": "^18.2.0", 49 | "eslint-import-resolver-typescript": "^2.3.0", 50 | "eslint-plugin-import": "^2.22.1", 51 | "eslint-plugin-jsx-a11y": "^6.3.1", 52 | "eslint-plugin-react": "^7.20.0", 53 | "eslint-plugin-react-hooks": "^4.1.2", 54 | "eslint-plugin-react-native": "^3.10.0", 55 | "eslint-plugin-react-native-globals": "^0.1.2", 56 | "husky": "^4.3.0", 57 | "lint-staged": "^10.5.1", 58 | "react": "^17.0.1", 59 | "react-dom": "^17.0.1", 60 | "size-limit": "^4.7.0", 61 | "tsdx": "^0.14.1", 62 | "tslib": "^2.0.3", 63 | "typescript": "^4.0.5" 64 | }, 65 | "dependencies": { 66 | "is-android": "^1.0.1", 67 | "is-ios": "^2.0.1", 68 | "is-linux": "^1.0.1", 69 | "is-windows": "^1.0.2", 70 | "react-test-renderer": "^17.0.1" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |

6 | Returns flags to make conditions based on the user-agent platform 7 |

8 | 9 | [![Author](https://img.shields.io/badge/author-LauraBeatris-F55441?style=flat-square)](https://github.com/LauraBeatris) 10 | [![Languages](https://img.shields.io/github/languages/count/LauraBeatris/use-platform?color=%23F55441&style=flat-square)](#) 11 | [![Stars](https://img.shields.io/github/stars/LauraBeatris/use-platform?color=F55441&style=flat-square)](https://github.com/LauraBeatris/use-platform/stargazers) 12 | [![Forks](https://img.shields.io/github/forks/LauraBeatris/use-platform?color=%23F55441&style=flat-square)](https://github.com/LauraBeatris/use-platform/network/members) 13 | [![Contributors](https://img.shields.io/github/contributors/LauraBeatris/use-platform?color=F55441&style=flat-square)](https://github.com/LauraBeatris/use-platform/graphs/contributors) 14 | 15 | ## :pushpin: Table of Contents 16 | 17 | * [Installation](#construction_worker-installation) 18 | * [Found a bug? Missing a specific feature?](#bug-issues) 19 | * [Contributing](#tada-contributing) 20 | * [License](#closed_book-license) 21 | 22 | ## :construction_worker: Installation 23 | 24 | ### via npm 25 | 26 | ``` 27 | npm install use-platform 28 | ``` 29 | 30 | ### via yarn 31 | 32 | ``` 33 | yarn add use-platform 34 | ``` 35 | 36 | ## :airplane: Usage 37 | 38 | Make conditions based on the user-agent platform 39 | 40 | ``` 41 | const SignInScreen: React.FC = () => { 42 | const { isMac, isIOS } = usePlatform(); 43 | 44 | const shouldShowSignInWithApple = isMac || isIOS; 45 | 46 | return ( 47 |
48 | { 49 | shouldShowSignInWithApple && ( 50 | 53 | ) 54 | } 55 | 56 | ) 57 | } 58 | ``` 59 | 60 | ## :bug: Issues 61 | 62 | Feel free to **file a new issue** with a respective title and description on the [use-platform](https://github.com/LauraBeatris/use-platform/issues) repository. If you already found a solution to your problem, **I would love to review your pull request**! Have a look at our [contribution guidelines](https://github.com/LauraBeatris/use-platform/blob/master/CONTRIBUTING.md) to find out about the coding standards. 63 | 64 | ## :tada: Contributing 65 | 66 | Check out the [contributing](https://github.com/LauraBeatris/use-platform/blob/master/CONTRIBUTING.md) page to see the best places to file issues, start discussions and begin contributing. 67 | 68 | ## :closed_book: License 69 | 70 | Released in 2020 71 | This package is under the [MIT license](https://github.com/LauraBeatris/use-platform/master/LICENSE). 72 | 73 | Made with love by [Laura Beatris](https://github.com/LauraBeatris) 💜🚀 74 | --------------------------------------------------------------------------------