├── .editorconfig
├── .gitattributes
├── .github
├── dependabot.yml
└── workflows
│ ├── nodejs.yml
│ ├── pages.yml
│ └── release.yml
├── .gitignore
├── .npmignore
├── .nvmrc
├── .postcssrc.json
├── .prettierrc
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── demo
├── App.tsx
├── Demo.tsx
├── DemoPage.tsx
├── index.css
├── index.html
└── index.tsx
├── eslint.config.mjs
├── jest.config.js
├── package-lock.json
├── package.json
├── src
└── index.ts
├── tailwind.config.js
├── tests
└── geolocated.test.tsx
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 2
12 |
13 | # We recommend you to keep these unchanged
14 | end_of_line = lf
15 | charset = utf-8
16 | trim_trailing_whitespace = true
17 | insert_final_newline = true
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: npm
4 | directory: "/"
5 | schedule:
6 | interval: weekly
7 | time: "04:00"
8 | open-pull-requests-limit: 10
9 | groups:
10 | eslint:
11 | patterns:
12 | - "@eslint/*"
13 | - "@typescript-eslint/*"
14 | - "eslint-*"
15 | - "eslint"
16 | - "typescript-eslint"
17 | jest:
18 | patterns:
19 | - "@types/jest"
20 | - "jest"
21 | - "jest-environment-jsdom"
22 | - "ts-jest"
23 | react:
24 | patterns:
25 | - "@types/react"
26 | - "react"
27 | - "react-dom"
28 | tailwind:
29 | patterns:
30 | - "@tailwindcss/*"
31 | - "tailwindcss"
32 | testing-library:
33 | patterns:
34 | - "@testing-library/*"
35 |
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: Node.js CI
2 | on: [push]
3 | jobs:
4 | build:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - name: Checkout
8 | uses: actions/checkout@v3
9 | - name: Setup Node.js
10 | uses: actions/setup-node@v3
11 | with:
12 | node-version-file: .nvmrc
13 | - name: Install dependencies
14 | run: npm install
15 | - name: Build
16 | run: npm run dist
17 | - name: Test
18 | run: npm run test
19 |
--------------------------------------------------------------------------------
/.github/workflows/pages.yml:
--------------------------------------------------------------------------------
1 | name: Deploy Pages
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | permissions:
7 | actions: read
8 | contents: read
9 | pages: write
10 | id-token: write
11 |
12 | concurrency:
13 | group: "pages"
14 | cancel-in-progress: false
15 |
16 | jobs:
17 | build:
18 | runs-on: ubuntu-latest
19 | steps:
20 | - name: Checkout
21 | uses: actions/checkout@v3
22 | - name: Setup Node.js
23 | uses: actions/setup-node@v3
24 | with:
25 | node-version-file: .nvmrc
26 | - name: Install dependencies
27 | run: npm install
28 | - name: Build pages
29 | run: "npm run docs:build"
30 | - name: Upload artifact
31 | uses: actions/upload-pages-artifact@v3
32 | with:
33 | path: ./demo/dist
34 |
35 | deploy:
36 | environment:
37 | name: github-pages
38 | url: ${{ steps.deployment.outputs.page_url }}
39 | runs-on: ubuntu-latest
40 | needs: build
41 | steps:
42 | - name: Deploy to GitHub Pages
43 | id: deployment
44 | uses: actions/deploy-pages@v4
45 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 | on:
3 | push:
4 | branches:
5 | - master
6 | jobs:
7 | release:
8 | name: Release
9 | runs-on: ubuntu-latest
10 | permissions:
11 | contents: write # to be able to publish a GitHub release
12 | issues: write # to be able to comment on released issues
13 | pull-requests: write # to be able to comment on released pull requests
14 | id-token: write # to enable use of OIDC for npm provenance
15 | steps:
16 | - name: Checkout
17 | uses: actions/checkout@v3
18 | - name: Setup Node.js
19 | uses: actions/setup-node@v3
20 | with:
21 | node-version-file: .nvmrc
22 | - name: Install dependencies
23 | run: npm clean-install
24 | - name: Build
25 | run: npm run dist
26 | - name: Release
27 | env:
28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
30 | run: npx semantic-release
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | docs/build/
3 | demo/dist
4 | dist
5 | dist-modules/
6 | node_modules/
7 | coverage/
8 | .idea/
9 | .eslintcache
10 | npm-debug.log
11 | yarn-error.log
12 | .docz
13 | .parcel-cache
14 | .DS_store
15 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | coverage/
2 | demo/
3 | dist/
4 | docs/
5 | docs-resources/
6 | src/
7 | tests/
8 | .*
9 | webpack.*
10 | jest.config.js
11 | tailwind.config.js
12 | tsconfig.json
13 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 20.10.0
2 |
--------------------------------------------------------------------------------
/.postcssrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "@tailwindcss/postcss"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": false,
3 | "tabWidth": 4,
4 | "trailingComma": "all"
5 | }
6 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Please see the [Releases](https://github.com/no23reason/react-geolocated/releases) page for changes on each version.
2 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing
2 |
3 | This project uses [`semantic-release`](https://github.com/semantic-release/semantic-release).
4 | Please use [Conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) when creating commits.
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Dan Homola
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |  [](https://www.npmjs.com/package/react-geolocated) [](https://github.com/semantic-release/semantic-release)
2 |
3 | # react-geolocated - React hook for using [Geolocation API](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation)
4 |
5 | ## Demo
6 |
7 | Basic demo can be found at the [demo page](https://no23reason.github.io/react-geolocated/).
8 |
9 | ## HOC version
10 |
11 | This package used to be a HOC, not a hook. If you want to use the HOC version, please stick with versions < 4.
12 |
13 | ## Basic Usage
14 |
15 | Install using `npm`:
16 |
17 | ```bash
18 | npm install react-geolocated --save
19 | ```
20 |
21 | Then use in your application like this:
22 |
23 | ```jsx
24 | import React from "react";
25 | import { useGeolocated } from "react-geolocated";
26 |
27 | const Demo = () => {
28 | const { coords, isGeolocationAvailable, isGeolocationEnabled } =
29 | useGeolocated({
30 | positionOptions: {
31 | enableHighAccuracy: false,
32 | },
33 | userDecisionTimeout: 5000,
34 | });
35 |
36 | return !isGeolocationAvailable ? (
37 |
Your browser does not support Geolocation
38 | ) : !isGeolocationEnabled ? (
39 |
Geolocation is not enabled
40 | ) : coords ? (
41 |
42 |
43 |
44 |
latitude
45 |
{coords.latitude}
46 |
47 |
48 |
longitude
49 |
{coords.longitude}
50 |
51 |
52 |
altitude
53 |
{coords.altitude}
54 |
55 |
56 |
heading
57 |
{coords.heading}
58 |
59 |
60 |
speed
61 |
{coords.speed}
62 |
63 |
64 |
65 | ) : (
66 |
Getting the location data…
67 | );
68 | };
69 |
70 | export default Demo;
71 | ```
72 |
73 | ## Hook return value
74 |
75 | The values returned from the hook are:
76 |
77 | ```js
78 | {
79 | coords: {
80 | latitude,
81 | longitude,
82 | altitude,
83 | accuracy,
84 | altitudeAccuracy,
85 | heading,
86 | speed,
87 | },
88 | timestamp, // timestamp of when the last position was retrieved
89 | isGeolocationAvailable, // boolean flag indicating that the browser supports the Geolocation API
90 | isGeolocationEnabled, // boolean flag indicating that the user has allowed the use of the Geolocation API
91 | positionError, // object with the error returned from the Geolocation API call
92 | getPosition, // a callback you can use to trigger the location query manually
93 | }
94 | ```
95 |
96 | The `coords` value is equivalent to the [Coordinates](https://developer.mozilla.org/en-US/docs/Web/API/Coordinates) object and the `positionError` is equivalent to the [PositionError](https://developer.mozilla.org/en-US/docs/Web/API/PositionError).
97 |
98 | ## Configuration
99 |
100 | The `useGeolocated` hook takes optional configuration parameter:
101 |
102 | ```js
103 | {
104 | positionOptions: {
105 | enableHighAccuracy: true,
106 | maximumAge: 0,
107 | timeout: Infinity,
108 | },
109 | watchPosition: false,
110 | userDecisionTimeout: null,
111 | suppressLocationOnMount: false,
112 | geolocationProvider: navigator.geolocation,
113 | isOptimisticGeolocationEnabled: true,
114 | watchLocationPermissionChange: false,
115 | onError,
116 | onSuccess,
117 | }
118 | ```
119 |
120 | The `positionOptions` object corresponds to the [PositionOptions](https://developer.mozilla.org/en-US/docs/Web/API/PositionOptions) of the Geolocation API.
121 |
122 | By default the hook only sets position once. To watch the user's position and provide live updates to position, set `watchPosition = true`. The geolocation event handler is unregistered when the hook unmounts.
123 |
124 | If set, the `userDecisionTimeout` determines how much time (in milliseconds) we give the user to make the decision whether to allow to share their location or not. In Firefox, if the user declines to use their location, the Geolocation API call does not end with an error. Therefore we want to fallback to the error state if the user declines and the API does not tell us.
125 |
126 | The location is obtained when the hook mounts by default. If you want to prevent this and get the location later, set the `suppressLocationOnMount` to `true` and use the `getPosition` function returned by the hook to trigger the geolocation query manually.
127 |
128 | The `geolocationProvider` allows to specify alternative source of the geolocation API. This was added mainly for testing purposes, however feel free to use it if need be.
129 |
130 | The `isOptimisticGeolocationEnabled` allows you to set the default value of `isGeolocationEnabled`. By default it is `true`, which means `isGeolocationEnabled` will be `true` on first render. There may be cases where you don't want to assume that the user will give permission, ie you want the first value to for `isGeolocationEnabled` to be `false`. In that case, you can set `isOptimisticGeolocationEnabled` to `false`.
131 |
132 | The `watchLocationPermissionChange` allows you to watch for changes in the geolocation permissions on browsers that support the permissions API. When set to `true`, the hook will set a watch on the geolocation permission so that when this permission changes, the location will be obtained again unless the `suppressLocationOnMount` is also set to `true`.
133 |
134 | The `onError` callback is called when the geolocation query fails or when the time for the user decision passes.
135 | The `onSuccess` is called when the geolocation query succeeds.
136 |
137 | ## Browser support
138 |
139 | The package supports all the browsers with ES6 support (i.e. any modern browser). If you need to support IE11, stick to version < 4 of this package.
140 |
141 | ## Acknowledgements
142 |
143 | Many thanks belong to [@mcumpl](https://github.com/mcumpl) for the original idea for this as well as many suggestions and comments.
144 |
145 | This project uses the [react-component-boilerplate](https://github.com/survivejs/react-component-boilerplate).
146 |
147 | ## License
148 |
149 | _react-geolocated_ is available under MIT. See [LICENSE](https://github.com/no23reason/react-geolocated/tree/master/LICENSE) for more details.
150 |
--------------------------------------------------------------------------------
/demo/App.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import GithubCorner from "react-github-corner";
3 |
4 | import { DemoPage } from "./DemoPage";
5 |
6 | export const App = () => {
7 | return (
8 |
9 |
10 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/demo/Demo.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useGeolocated } from "../src";
3 |
4 | const getDirection = (degrees: number, isLongitude: boolean) =>
5 | degrees > 0 ? (isLongitude ? "E" : "N") : isLongitude ? "W" : "S";
6 |
7 | // adapted from http://stackoverflow.com/a/5786281/2546338
8 | const formatDegrees = (degrees: number, isLongitude: boolean) =>
9 | `${0 | degrees}° ${
10 | 0 | (((degrees < 0 ? (degrees = -degrees) : degrees) % 1) * 60)
11 | }' ${0 | (((degrees * 60) % 1) * 60)}" ${getDirection(
12 | degrees,
13 | isLongitude,
14 | )}`;
15 |
16 | export const Demo = () => {
17 | const {
18 | coords,
19 | getPosition,
20 | isGeolocationAvailable,
21 | isGeolocationEnabled,
22 | positionError,
23 | } = useGeolocated({
24 | positionOptions: {
25 | enableHighAccuracy: false,
26 | },
27 | userDecisionTimeout: 5000,
28 | watchLocationPermissionChange: true,
29 | });
30 |
31 | return (
32 |
19 | react-geolocated is a{" "}
20 |
24 | configurable
25 | {" "}
26 | React Hook that makes using the Geolocation API
27 | easy, abstracting away some browser-specific quirks (differences
28 | on how they handle permissions for example).
29 |