├── .eslintignore ├── .gitignore ├── documentation.yml ├── flow-typed └── .eslintrc ├── .prettierrc ├── .travis.yml ├── test ├── index.test.js ├── useLeafletIsMoving.test.js ├── useLeafletIsZooming.test.js ├── useLeafletZoom.test.js ├── useLeafletCenter.test.js └── useLeafletBounds.test.js ├── .babelrc ├── CHANGELOG.md ├── src ├── index.js ├── index.d.ts ├── useLeafletIsMoving.js ├── useLeafletIsZooming.js ├── useLeafletZoom.js ├── useLeafletCenter.js ├── onLeafletEvent.js ├── useLeafletBounds.js ├── onLeafletInput.js └── useLeafletMap.js ├── .flowconfig ├── .editorconfig ├── .eslintrc ├── LICENSE ├── package.json └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage 2 | dist 3 | node_modules 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | coverage 3 | dist 4 | node_modules 5 | *.log 6 | flow-typed/npm 7 | -------------------------------------------------------------------------------- /documentation.yml: -------------------------------------------------------------------------------- 1 | toc: 2 | - useLeafletZoom 3 | - useLeafletMap 4 | - useLeafletCenter 5 | - useLeafletBounds 6 | -------------------------------------------------------------------------------- /flow-typed/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "flowtype/no-types-missing-file-annotation": "off", 4 | "prettier/prettier": "off", 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | printWidth: 150, 3 | semi: false, 4 | singleQuote: false, 5 | trailingComma: "all", 6 | useTabs: true, 7 | endOfLine: "lf", 8 | } 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - v8 4 | script: 5 | - npm run flowinstall 6 | - npm run lint 7 | - npm run test -- --coverage 8 | cache: 9 | - npm ci 10 | after_success: 11 | - npm run sendcodecov 12 | -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import "../src/index" 4 | 5 | declare var describe: Function 6 | declare var it: Function 7 | 8 | describe("stub for checking coverage", () => { 9 | it("shouldn't do anything", () => {}) 10 | }) 11 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": 8, 8 | }, 9 | }, 10 | ], 11 | "@babel/preset-flow", 12 | "@babel/preset-react", 13 | ], 14 | "plugins": [ 15 | "@babel/plugin-proposal-class-properties", 16 | ], 17 | } 18 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## 1.6.0 3 | 4 | - added typescript typings 5 | 6 | ## 1.5.1 7 | 8 | - fix unsubscribing from events in useLeafletIsMoving & useLeafletIsZooming implementation. 9 | 10 | ## 1.5.0 11 | 12 | - added [useLeafletIsMoving](README.md#useleafletismoving) & [useLeafletIsZooming](README.md#useleafletiszooming) hooks. 13 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | export { useLeafletZoom } from "./useLeafletZoom" 3 | export { useLeafletMap } from "./useLeafletMap" 4 | export { useLeafletBounds } from "./useLeafletBounds" 5 | export { useLeafletCenter } from "./useLeafletCenter" 6 | export { useLeafletIsMoving } from "./useLeafletIsMoving" 7 | export { useLeafletIsZooming } from "./useLeafletIsZooming" 8 | -------------------------------------------------------------------------------- /src/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Map } from "leaflet" 2 | 3 | export function useLeafletZoom(): number 4 | export function useLeafletMap(): Map | undefined 5 | export function useLeafletBounds(): [[number, number], [number, number]] 6 | export function useLeafletCenter(): [number, number] 7 | export function useLeafletIsMoving(): boolean 8 | export function useLeafletIsZooming(): boolean 9 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | .*/dist 3 | .*/coverage 4 | 5 | [include] 6 | 7 | [libs] 8 | 9 | [lints] 10 | 11 | [options] 12 | esproposal.class_instance_fields=enable 13 | esproposal.class_static_fields=enable 14 | esproposal.decorators=ignore 15 | esproposal.export_star_as=enable 16 | esproposal.optional_chaining=enable 17 | esproposal.nullish_coalescing=enable 18 | experimental.const_params=true 19 | module.use_strict=true 20 | -------------------------------------------------------------------------------- /.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 = tab 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 | -------------------------------------------------------------------------------- /src/useLeafletIsMoving.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { useLeafletInput } from "./onLeafletInput" 3 | 4 | /** 5 | * React hook to see if a user is moving the [react-leaflet map](https://react-leaflet.js.org/). 6 | * 7 | * ```javascript 8 | * const MyComponent = () => { 9 | * const isMoving = useLeafletIsMoving() 10 | * return ... 11 | * } 12 | * ``` 13 | * 14 | * @returns true if a user is moving the map. 15 | */ 16 | 17 | export const useLeafletIsMoving = (): boolean => useLeafletInput("movestart", "moveend") 18 | -------------------------------------------------------------------------------- /src/useLeafletIsZooming.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { useLeafletInput } from "./onLeafletInput" 3 | 4 | /** 5 | * React hook to see if a user is zooming the [react-leaflet map](https://react-leaflet.js.org/). 6 | * 7 | * ```javascript 8 | * const MyComponent = () => { 9 | * const isZooming = useLeafletIsZooming() 10 | * return ... 11 | * } 12 | * ``` 13 | * 14 | * @returns true if a user is zooming the map. 15 | */ 16 | 17 | export const useLeafletIsZooming = (): boolean => useLeafletInput("zoomstart", "zoomend") 18 | -------------------------------------------------------------------------------- /src/useLeafletZoom.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { useLeafletData } from "./onLeafletEvent" 3 | 4 | /** 5 | * React hook for getting current zoom of react-leaflet [Map](https://react-leaflet.js.org/docs/en/components.html#map). 6 | * 7 | * ```javascript 8 | * const MyLayer = () => { 9 | * const zoom = useLeafletZoom() 10 | * return zoom > 10 ? () : () 11 | * } 12 | * ``` 13 | * 14 | * @returns current zoom. 15 | */ 16 | 17 | export const useLeafletZoom = (): number => useLeafletData(getMapZoom, "zoomend") 18 | 19 | const getMapZoom = map => (map && map.getZoom()) || 0 20 | -------------------------------------------------------------------------------- /src/useLeafletCenter.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { useLeafletData } from "./onLeafletEvent" 3 | 4 | /** 5 | * React hook for getting current center of react-leaflet [Map](https://react-leaflet.js.org/docs/en/components.html#map). 6 | * 7 | * ```javascript 8 | * const MyComponent = () => { 9 | * const [lat, lng] = useLeafletCenter() 10 | * return ... 11 | * } 12 | * ``` 13 | * 14 | * @returns [lat, lng] of the map center. 15 | */ 16 | 17 | export const useLeafletCenter = (): [number, number] => useLeafletData(getMapCenter, "moveend") 18 | 19 | const getMapCenter = map => { 20 | if (!map) return [0, 0] 21 | const { lat, lng } = map.getCenter() 22 | return [lat, lng] 23 | } 24 | -------------------------------------------------------------------------------- /src/onLeafletEvent.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Map } from "leaflet" 3 | import { useState, useEffect } from "react" 4 | import { useLeafletMap } from "./useLeafletMap" 5 | 6 | export const useLeafletData = (getLeafletData: (map: Map | void) => T, event: string): T => { 7 | const map: Map | void = useLeafletMap() 8 | 9 | const [data, setData] = useState(() => getLeafletData(map)) 10 | 11 | useEffect(() => { 12 | let effectMounted = true 13 | 14 | const doCallback = () => effectMounted && setData(getLeafletData(map)) 15 | 16 | setImmediate(doCallback) 17 | 18 | if (map) map.on(event, doCallback) 19 | 20 | return () => { 21 | effectMounted = false 22 | if (map) map.off(event, doCallback) 23 | } 24 | }, [event, getLeafletData, map]) 25 | 26 | return data 27 | } 28 | -------------------------------------------------------------------------------- /src/useLeafletBounds.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { useLeafletData } from "./onLeafletEvent" 3 | 4 | /** 5 | * React hook for getting current bounds of visible area of react-leaflet [Map](https://react-leaflet.js.org/docs/en/components.html#map). 6 | * 7 | * ```javascript 8 | * const MyComponent = () => { 9 | * const [[south, west], [north, east]] = useLeafletBounds() 10 | * return ... 11 | * } 12 | * ``` 13 | * 14 | * @returns [[south, west], [north, east]] for visible area. 15 | */ 16 | 17 | export const useLeafletBounds = (): [[number, number], [number, number]] => useLeafletData(getMapBounds, "moveend") 18 | 19 | const getMapBounds = map => { 20 | if (!map) 21 | return [ 22 | [Infinity, Infinity], 23 | [-Infinity, -Infinity], 24 | ] 25 | const bounds = map.getBounds() 26 | return [ 27 | [bounds.getSouth(), bounds.getWest()], 28 | [bounds.getNorth(), bounds.getEast()], 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /src/onLeafletInput.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Map } from "leaflet" 3 | import { useState, useEffect } from "react" 4 | import { useLeafletMap } from "./useLeafletMap" 5 | 6 | export const useLeafletInput = (inputStartEvent: string, inputStopEvent: string, onGetInitialState: (map: Map) => boolean = getFalse): boolean => { 7 | const map: Map | void = useLeafletMap() 8 | 9 | const [isInput, setIsInput] = useState(onGetInitialState(map)) 10 | 11 | useEffect(() => { 12 | let effectMounted = true 13 | 14 | const handleStart = () => effectMounted && setIsInput(true) 15 | const handleEnd = () => effectMounted && setIsInput(false) 16 | 17 | if (map) { 18 | map.on(inputStartEvent, handleStart) 19 | map.on(inputStopEvent, handleEnd) 20 | } 21 | 22 | return () => { 23 | effectMounted = false 24 | if (map) { 25 | map.off(inputStartEvent, handleStart) 26 | map.off(inputStopEvent, handleEnd) 27 | } 28 | } 29 | }, [inputStartEvent, inputStopEvent, map]) 30 | 31 | return isInput 32 | } 33 | 34 | const getFalse = () => false 35 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": [ 4 | "airbnb-base", 5 | "plugin:flowtype/recommended", 6 | "plugin:prettier/recommended", 7 | "prettier/flowtype", 8 | "plugin:react/recommended", 9 | ], 10 | "plugins": [ 11 | "flowtype", 12 | "flowtype-errors", 13 | "react-hooks", 14 | ], 15 | "env": { 16 | "jest": true, 17 | }, 18 | "settings": { 19 | "react": { 20 | "version": "detect", 21 | }, 22 | }, 23 | "rules": { 24 | "react-hooks/rules-of-hooks": "error", 25 | "react-hooks/exhaustive-deps": "warn", 26 | "flowtype-errors/show-errors": "error", 27 | "no-restricted-syntax": [ 28 | "error", 29 | "WithStatement", 30 | "LabeledStatement", 31 | "ForInStatement", 32 | ], 33 | "no-await-in-loop": "off", 34 | "no-return-await": "off", 35 | "import/no-default-export": "error", 36 | "import/prefer-default-export": "off", 37 | "func-names": "off", 38 | "no-void": "off", 39 | "no-plusplus": "off", 40 | "require-yield": "off", 41 | "no-use-before-define": "off", 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Vadzim Zieńka 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 | -------------------------------------------------------------------------------- /test/useLeafletIsMoving.test.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from "react" 4 | import ReactDOM from "react-dom" 5 | import { Map } from "react-leaflet" 6 | import { useLeafletIsMoving } from "../src/useLeafletIsMoving" 7 | 8 | declare var describe: Function 9 | declare var it: Function 10 | declare var expect: Function 11 | 12 | describe("useLeafletIsMoving", () => { 13 | let isMoving = -1 14 | 15 | const UseLeafletIsMoving = () => { 16 | isMoving = useLeafletIsMoving() 17 | return <> 18 | } 19 | 20 | const div = global.document.createElement("div") 21 | 22 | it("should not throw", () => { 23 | ReactDOM.render(, div) 24 | expect(isMoving).toBe(false) 25 | 26 | ReactDOM.render( 27 | 28 | 29 | , 30 | div, 31 | ) 32 | expect(isMoving).toBe(false) 33 | 34 | ReactDOM.render( 35 | 36 | 37 | , 38 | div, 39 | ) 40 | expect(isMoving).toBe(false) 41 | 42 | ReactDOM.render( 43 | 44 | {null} 45 | , 46 | div, 47 | ) 48 | expect(isMoving).toBe(false) 49 | }) 50 | }) 51 | -------------------------------------------------------------------------------- /test/useLeafletIsZooming.test.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from "react" 4 | import ReactDOM from "react-dom" 5 | import { Map } from "react-leaflet" 6 | import { useLeafletIsZooming } from "../src/useLeafletIsZooming" 7 | 8 | declare var describe: Function 9 | declare var it: Function 10 | declare var expect: Function 11 | 12 | describe("useLeafletIsZooming", () => { 13 | let isZooming = -1 14 | 15 | const UseLeafletIsZooming = () => { 16 | isZooming = useLeafletIsZooming() 17 | return <> 18 | } 19 | 20 | const div = global.document.createElement("div") 21 | 22 | it("should not throw", () => { 23 | ReactDOM.render(, div) 24 | expect(isZooming).toBe(false) 25 | 26 | ReactDOM.render( 27 | 28 | 29 | , 30 | div, 31 | ) 32 | expect(isZooming).toBe(false) 33 | 34 | ReactDOM.render( 35 | 36 | 37 | , 38 | div, 39 | ) 40 | expect(isZooming).toBe(false) 41 | 42 | ReactDOM.render( 43 | 44 | {null} 45 | , 46 | div, 47 | ) 48 | expect(isZooming).toBe(false) 49 | }) 50 | }) 51 | -------------------------------------------------------------------------------- /test/useLeafletZoom.test.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from "react" 4 | import ReactDOM from "react-dom" 5 | import { Map } from "react-leaflet" 6 | import { useLeafletZoom } from "../src/useLeafletZoom" 7 | 8 | declare var describe: Function 9 | declare var it: Function 10 | declare var expect: Function 11 | 12 | describe("useLeafletZoom", () => { 13 | let zoom = -1 14 | 15 | const UseLeafletZoom = () => { 16 | zoom = useLeafletZoom() 17 | return <> 18 | } 19 | 20 | const div = global.document.createElement("div") 21 | 22 | it("should return 0 without leaflet", () => { 23 | ReactDOM.render(, div) 24 | expect(zoom).toBe(0) 25 | }) 26 | 27 | it("should return initial zoom", () => { 28 | ReactDOM.render( 29 | 30 | 31 | , 32 | div, 33 | ) 34 | expect(zoom).toBe(10) 35 | }) 36 | 37 | it("should react on zoom change", () => { 38 | ReactDOM.render( 39 | 40 | 41 | , 42 | div, 43 | ) 44 | expect(zoom).toBe(12) 45 | }) 46 | 47 | it("should not react after unmount", () => { 48 | ReactDOM.render( 49 | 50 | {null} 51 | , 52 | div, 53 | ) 54 | expect(zoom).toBe(12) 55 | }) 56 | }) 57 | -------------------------------------------------------------------------------- /test/useLeafletCenter.test.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from "react" 4 | import ReactDOM from "react-dom" 5 | import { Map } from "react-leaflet" 6 | import { useLeafletCenter } from "../src/useLeafletCenter" 7 | 8 | declare var describe: Function 9 | declare var it: Function 10 | declare var expect: Function 11 | 12 | describe("useLeafletCenter", () => { 13 | let center 14 | 15 | const UseLeafletCenter = () => { 16 | center = useLeafletCenter() 17 | return <> 18 | } 19 | 20 | const div = global.document.createElement("div") 21 | 22 | it("should return zeroed center without leaflet", () => { 23 | ReactDOM.render(, div) 24 | expect(center).toEqual([0, 0]) 25 | }) 26 | 27 | it("should return initial center", () => { 28 | ReactDOM.render( 29 | 30 | 31 | , 32 | div, 33 | ) 34 | 35 | expect(center).toEqual([1.2, 3.4]) 36 | }) 37 | 38 | it("should react on center change", () => { 39 | ReactDOM.render( 40 | 41 | 42 | , 43 | div, 44 | ) 45 | expect(center).toEqual([5.6, 7.8]) 46 | }) 47 | 48 | it("should not react after unmount", () => { 49 | ReactDOM.render( 50 | 51 | {null} 52 | , 53 | div, 54 | ) 55 | expect(center).toEqual([5.6, 7.8]) 56 | }) 57 | }) 58 | -------------------------------------------------------------------------------- /src/useLeafletMap.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Map } from "leaflet" 3 | import { useLeaflet } from "react-leaflet" 4 | 5 | /** 6 | * React hook for getting current leaflet [map](https://leafletjs.com/reference.html#map). Returns the same value as the `map` member of the `leaflet` prop when using [withLeaflet](https://react-leaflet.js.org/docs/en/context.html) HOC from react-lealfet [module](https://www.npmjs.com/package/react-leaflet). 7 | * 8 | * Usage: 9 | * 10 | * ```javascript 11 | * import React from "react" 12 | * import { Map } from "react-leaflet" 13 | * import { useLeafletMap } from "use-leaflet" 14 | * 15 | * const MyLeafletComponent = (props) => { 16 | * const map = useLeafletMap() 17 | * return ( 18 | * <... onClick={() => map.fitBounds(turf.bbox(props.activeShape))}> 19 | * ... 20 | * 21 | * ) 22 | * } 23 | * 24 | * const App = () => ( 25 | * 26 | * 27 | * 28 | * ) 29 | * ``` 30 | * 31 | * Keep in mind, that `useLeafletMap` hook will work only in components which are used within [Map](https://react-leaflet.js.org/docs/en/components.html#map) component, the same as `withLeaflet` HOC from `react-leaflet`. 32 | * 33 | * @returns current leaflet map. 34 | */ 35 | 36 | export const useLeafletMap = (): Map | void => useLeaflet().map 37 | 38 | /** 39 | * @external Map 40 | * @see leaflet {@link https://leafletjs.com/reference.html#map Map} type. 41 | */ 42 | -------------------------------------------------------------------------------- /test/useLeafletBounds.test.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from "react" 4 | import ReactDOM from "react-dom" 5 | import { Map } from "react-leaflet" 6 | import { useLeafletBounds } from "../src/useLeafletBounds" 7 | 8 | declare var describe: Function 9 | declare var it: Function 10 | declare var expect: Function 11 | 12 | describe("useLeafletBounds", () => { 13 | let bounds 14 | 15 | const UseLeafletBounds = () => { 16 | bounds = useLeafletBounds() 17 | return <> 18 | } 19 | 20 | const div = global.document.createElement("div") 21 | 22 | it("should return empty bounds without leaflet", () => { 23 | ReactDOM.render(, div) 24 | expect(bounds).toEqual([ 25 | [Infinity, Infinity], 26 | [-Infinity, -Infinity], 27 | ]) 28 | }) 29 | 30 | it("should return initial bounds", () => { 31 | ReactDOM.render( 32 | 39 | 40 | , 41 | div, 42 | ) 43 | 44 | expect(bounds).toEqual([ 45 | [60.23981116999893, 25.312500000000004], 46 | [60.23981116999893, 25.312500000000004], 47 | ]) 48 | }) 49 | 50 | it("should react on bounds change", () => { 51 | ReactDOM.render( 52 | 59 | 60 | , 61 | div, 62 | ) 63 | expect(bounds).toEqual([ 64 | [62.2679226294176, 28.125000000000004], 65 | [62.2679226294176, 28.125000000000004], 66 | ]) 67 | }) 68 | 69 | it("should not react after unmount", () => { 70 | ReactDOM.render( 71 | 78 | {null} 79 | , 80 | div, 81 | ) 82 | expect(bounds).toEqual([ 83 | [62.2679226294176, 28.125000000000004], 84 | [62.2679226294176, 28.125000000000004], 85 | ]) 86 | }) 87 | }) 88 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "use-leaflet", 3 | "version": "1.6.1", 4 | "description": "useLeaflet hook for react-leaflet", 5 | "license": "MIT", 6 | "repository": "vadzim/use-leaflet", 7 | "main": "dist/index.js", 8 | "types": "src/index.d.ts", 9 | "author": { 10 | "name": "Vadzim Zieńka", 11 | "email": "v@vadzim.info", 12 | "url": "https://github.com/vadzim" 13 | }, 14 | "files": [ 15 | "dist", 16 | "src", 17 | "CHANGELOG.md" 18 | ], 19 | "scripts": { 20 | "test": "jest", 21 | "coverage": "npm test -- --coverage --collectCoverageFrom=src/**/*.js", 22 | "lint": "eslint .", 23 | "flow": "flow check", 24 | "flowinstall": "flow-typed install --ignoreDeps=dev", 25 | "docs": "documentation --config documentation.yml readme src --section=API", 26 | "postdocs": "git add README.md", 27 | "clean": "rimraf dist", 28 | "flowbuild": "flow-copy-source src dist", 29 | "prebuild": "npm run docs && npm run clean && npm run flowbuild", 30 | "build": "babel src -d dist", 31 | "preversion": "npm run flowinstall && npm run lint && npm test && npm run build", 32 | "postpublish": "git push origin master --follow-tags", 33 | "sendcodecov": "codecov --token=$CODECOV_TOKEN" 34 | }, 35 | "lint-changed": { 36 | "*.js": [ 37 | "eslint --fix" 38 | ] 39 | }, 40 | "keywords": [ 41 | "useLeaflet", 42 | "react", 43 | "hook", 44 | "hooks", 45 | "use", 46 | "leaflet", 47 | "react-leaflet" 48 | ], 49 | "dependencies": {}, 50 | "peerDependencies": { 51 | "react": "16 || 17", 52 | "react-leaflet": "2", 53 | "leaflet": "1" 54 | }, 55 | "devDependencies": { 56 | "@babel/cli": "^7.7.5", 57 | "@babel/core": "^7.7.5", 58 | "@babel/plugin-proposal-class-properties": "^7.7.4", 59 | "@babel/preset-env": "^7.7.6", 60 | "@babel/preset-flow": "^7.7.4", 61 | "@babel/preset-react": "^7.7.4", 62 | "@types/leaflet": "^1.5.6", 63 | "babel-eslint": "^10.0.3", 64 | "babel-jest": "^24.9.0", 65 | "codecov": "^3.6.1", 66 | "documentation": "^12.1.4", 67 | "eslint": "^6.7.2", 68 | "eslint-config-airbnb-base": "^14.0.0", 69 | "eslint-config-prettier": "^6.7.0", 70 | "eslint-plugin-flowtype": "^4.5.2", 71 | "eslint-plugin-flowtype-errors": "^4.1.0", 72 | "eslint-plugin-import": "^2.19.1", 73 | "eslint-plugin-prettier": "^3.1.1", 74 | "eslint-plugin-react": "^7.17.0", 75 | "eslint-plugin-react-hooks": "^2.3.0", 76 | "flow-bin": "^0.113.0", 77 | "flow-copy-source": "^2.0.9", 78 | "flow-typed": "^2.6.2", 79 | "jest": "^24.9.0", 80 | "leaflet": "^1.6.0", 81 | "lint-changed": "0.0.0-development", 82 | "prettier": "^1.19.1", 83 | "react": "^16.12.0", 84 | "react-dom": "^16.12.0", 85 | "react-hooks-testing-library": "^0.6.0", 86 | "react-leaflet": "^2.6.0", 87 | "react-test-renderer": "^16.12.0", 88 | "rimraf": "^3.0.0" 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # use-leaflet 2 | 3 | [![NPM version](https://img.shields.io/npm/v/use-leaflet.svg?style=flat-square)](https://npmjs.org/package/use-leaflet) 4 | [![Build Status](https://img.shields.io/travis/vadzim/use-leaflet/master.svg?style=flat-square)](https://travis-ci.org/vadzim/use-leaflet) 5 | [![Coverage Status](https://img.shields.io/codecov/c/github/vadzim/use-leaflet/master.svg?style=flat-square)](https://codecov.io/gh/vadzim/use-leaflet/branch/master) 6 | 7 | Hooks for using with [react-leaflet](https://www.npmjs.com/package/react-leaflet). 8 | 9 | Example of usage: 10 | 11 | Installation: `npm i use-leaflet` 12 | 13 | ## API 14 | 15 | 16 | 17 | #### Table of Contents 18 | 19 | - [useLeafletZoom](#useleafletzoom) 20 | - [useLeafletMap](#useleafletmap) 21 | - [useLeafletCenter](#useleafletcenter) 22 | - [useLeafletBounds](#useleafletbounds) 23 | - [useLeafletIsMoving](#useleafletismoving) 24 | - [useLeafletIsZooming](#useleafletiszooming) 25 | - [Map](#map) 26 | 27 | ### useLeafletZoom 28 | 29 | React hook for getting current zoom of react-leaflet [Map](https://react-leaflet.js.org/docs/en/components.html#map). 30 | 31 | ```javascript 32 | const MyLayer = () => { 33 | const zoom = useLeafletZoom() 34 | return zoom > 10 ? () : () 35 | } 36 | ``` 37 | 38 | Returns **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** current zoom. 39 | 40 | ### useLeafletMap 41 | 42 | React hook for getting current leaflet [map](https://leafletjs.com/reference.html#map). Returns the same value as the `map` member of the `leaflet` prop when using [withLeaflet](https://react-leaflet.js.org/docs/en/context.html) HOC from react-lealfet [module](https://www.npmjs.com/package/react-leaflet). 43 | 44 | Usage: 45 | 46 | ```javascript 47 | import React from "react" 48 | import { Map } from "react-leaflet" 49 | import { useLeafletMap } from "use-leaflet" 50 | 51 | const MyLeafletComponent = (props) => { 52 | const map = useLeafletMap() 53 | return ( 54 | <... onClick={() => map.fitBounds(turf.bbox(props.activeShape))}> 55 | ... 56 | 57 | ) 58 | } 59 | 60 | const App = () => ( 61 | 62 | 63 | 64 | ) 65 | ``` 66 | 67 | Keep in mind, that `useLeafletMap` hook will work only in components which are used within [Map](https://react-leaflet.js.org/docs/en/components.html#map) component, the same as `withLeaflet` HOC from `react-leaflet`. 68 | 69 | Returns **([Map](#map) | void)** current leaflet map. 70 | 71 | ### useLeafletCenter 72 | 73 | React hook for getting current center of react-leaflet [Map](https://react-leaflet.js.org/docs/en/components.html#map). 74 | 75 | ```javascript 76 | const MyComponent = () => { 77 | const [lat, lng] = useLeafletCenter() 78 | return ... 79 | } 80 | ``` 81 | 82 | Returns **\[[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)]** [lat, lng] of the map center. 83 | 84 | ### useLeafletBounds 85 | 86 | React hook for getting current bounds of visible area of react-leaflet [Map](https://react-leaflet.js.org/docs/en/components.html#map). 87 | 88 | ```javascript 89 | const MyComponent = () => { 90 | const [[south, west], [north, east]] = useLeafletBounds() 91 | return ... 92 | } 93 | ``` 94 | 95 | Returns **\[\[[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)], \[[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number), [number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)]]** \[[south, west], [north, east]] for visible area. 96 | 97 | ### useLeafletIsMoving 98 | 99 | React hook to see if a user is moving the [react-leaflet map](https://react-leaflet.js.org/). 100 | 101 | ```javascript 102 | const MyComponent = () => { 103 | const isMoving = useLeafletIsMoving() 104 | return ... 105 | } 106 | ``` 107 | 108 | Returns **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** true if a user is moving the map. 109 | 110 | ### useLeafletIsZooming 111 | 112 | React hook to see if a user is zooming the [react-leaflet map](https://react-leaflet.js.org/). 113 | 114 | ```javascript 115 | const MyComponent = () => { 116 | const isZooming = useLeafletIsZooming() 117 | return ... 118 | } 119 | ``` 120 | 121 | Returns **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** true if a user is zooming the map. 122 | 123 | ### Map 124 | 125 | - **See: leaflet [Map](https://leafletjs.com/reference.html#map) type.** 126 | --------------------------------------------------------------------------------