├── .eslintrc
├── .gitignore
├── .npmignore
├── .prettierrc
├── LICENSE
├── README.md
├── example
├── .gitignore
├── README.md
├── cypress.json
├── cypress
│ ├── fixtures
│ │ └── example.json
│ ├── integration
│ │ └── basicJourney.spec.js
│ ├── plugins
│ │ └── index.js
│ └── support
│ │ ├── commands.js
│ │ └── index.js
├── package-lock.json
├── package.json
├── public
│ └── index.html
└── src
│ └── index.js
├── package-lock.json
├── package.json
├── react-map-gl-geocoder-screenshot.png
└── src
└── index.js
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "node": true
5 | },
6 | "extends": ["eslint:recommended", "plugin:react/recommended", "plugin:cypress/recommended"],
7 | "parser": "babel-eslint"
8 | }
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 | /dist
12 |
13 | # misc
14 | .DS_Store
15 | .env.local
16 | .env.development.local
17 | .env.test.local
18 | .env.production.local
19 |
20 | npm-debug.log*
21 | yarn-debug.log*
22 | yarn-error.log*
23 |
24 | .idea
25 | .cache
26 | .vscode
27 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 | /dist
12 |
13 | # misc
14 | .DS_Store
15 | .env.local
16 | .env.development.local
17 | .env.test.local
18 | .env.production.local
19 |
20 | npm-debug.log*
21 | yarn-debug.log*
22 | yarn-error.log*
23 |
24 | .idea
25 | .cache
26 | .vscode
27 | *.png
28 | /example
29 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "jsxBracketSameLine": true,
3 | "printWidth": 120,
4 | "semi": false,
5 | "singleQuote": true,
6 | "arrowParens": "always"
7 | }
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Steven Miyakawa "SAM"
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 | # react-map-gl-geocoder
2 |
3 | React wrapper for mapbox-gl-geocoder for use with react-map-gl.
4 |
5 | [](https://www.npmjs.com/package/react-map-gl-geocoder) [](https://dashboard.cypress.io/projects/etguoj/runs)
6 |
7 |
8 | ## Demos
9 | * Simple Example - https://codesandbox.io/s/l7p179qr6m
10 | * Ignore Map Events Example - https://codesandbox.io/s/react-map-gl-geocoder-using-containerref-to-ignore-events-rewdh
11 |
12 | ## Installation
13 | npm
14 | ```
15 | $ npm install react-map-gl-geocoder
16 | ```
17 |
18 | or
19 |
20 | Yarn
21 | ```
22 | $ yarn add react-map-gl-geocoder
23 | ```
24 |
25 | ## Styling
26 | Import:
27 | ```js
28 | import 'react-map-gl-geocoder/dist/mapbox-gl-geocoder.css'
29 | ```
30 |
31 | or
32 |
33 | Link tag in header:
34 | ```html
35 |
36 | ```
37 |
38 |
39 | ## Props
40 | Only `mapRef` and `mapboxApiAccessToken` are required.
41 |
42 | All non-primitive prop values besides `mapRef` and `containerRef` should be memoized.
43 |
44 | | Name | Type | Default | Description |
45 | |--- | --- | --- | --- |
46 | | mapRef | Object | | Ref for react-map-gl map component.
47 | | containerRef | Object | | This can be used to place the geocoder outside of the map. The `position` prop is ignored if this is passed in. Example: https://codesandbox.io/s/v0m14q5rly
48 | | onViewportChange | Function | () => {} | Is passed updated viewport values after executing a query.
49 | | mapboxApiAccessToken | String | | https://www.mapbox.com/
50 | | inputValue | String | | Sets the search input value
51 | | origin | String | "https://api.mapbox.com" | Use to set a custom API origin.
52 | | zoom | Number | 16 | On geocoded result what zoom level should the map animate to when a `bbox` isn't found in the response. If a `bbox` is found the map will fit to the `bbox`.
53 | | placeholder | String | "Search" | Override the default placeholder attribute value.
54 | | proximity | Object | | A proximity argument: this is a geographical point given as an object with latitude and longitude properties. Search results closer to this point will be given higher priority.
55 | | trackProximity | Boolean | false | If true, the geocoder proximity will automatically update based on the map view.
56 | | collapsed | Boolean | false | If true, the geocoder control will collapse until hovered or in focus.
57 | | clearAndBlurOnEsc | Boolean | false | If true, the geocoder control will clear it's contents and blur when user presses the escape key.
58 | | clearOnBlur | Boolean | false | If true, the geocoder control will clear its value when the input blurs.
59 | | bbox | Array | | A bounding box argument: this is a bounding box given as an array in the format [minX, minY, maxX, maxY]. Search results will be limited to the bounding box.
60 | | types | String | | A comma seperated list of types that filter results to match those specified. See for available types.
61 | | countries | String | | A comma separated list of country codes to limit results to specified country or countries.
62 | | minLength | Number | 2 | Minimum number of characters to enter before results are shown.
63 | | limit | Number | 5 | Maximum number of results to show.
64 | | language | String | | Specify the language to use for response text and query result weighting. Options are IETF language tags comprised of a mandatory ISO 639-1 language code and optionally one or more IETF subtags for country or script. More than one value can also be specified, separated by commas.
65 | | filter | Function | | A function which accepts a Feature in the [Carmen GeoJSON](https://github.com/mapbox/carmen/blob/master/carmen-geojson.md) format to filter out results from the Geocoding API response before they are included in the suggestions list. Return `true` to keep the item, `false` otherwise.
66 | | localGeocoder | Function | | A function accepting the query string which performs local geocoding to supplement results from the Mapbox Geocoding API. Expected to return an Array of GeoJSON Features in the [Carmen GeoJSON](https://github.com/mapbox/carmen/blob/master/carmen-geojson.md) format.
67 | | localGeocoderOnly | Boolean | false | If true, indicates that the localGeocoder results should be the only ones returned to the user. If false, indicates that the localGeocoder results should be combined with those from the Mapbox API with the localGeocoder results ranked higher.
68 | | reverseGeocode | Boolean | false | Enable reverse geocoding. Defaults to false. Expects coordinates to be lat, lon.
69 | | enableEventLogging | Boolean | true | Allow Mapbox to collect anonymous usage statistics from the plugin.
70 | | marker | Boolean or Object | true | If true, a [Marker](https://docs.mapbox.com/mapbox-gl-js/api/#marker) will be added to the map at the location of the user-selected result using a default set of Marker options. If the value is an object, the marker will be constructed using these options. If false, no marker will be added to the map.
71 | | render | Function | | A function that specifies how the results should be rendered in the dropdown menu. Accepts a single Carmen GeoJSON object as input and return a string. Any html in the returned string will be rendered. Uses mapbox-gl-geocoder's default rendering if no function provided.
72 | | position | String | "top-right" | Position on the map to which the geocoder control will be added. Valid values are `"top-left"`, `"top-right"`, `"bottom-left"`, and `"bottom-right"`.
73 | | onInit | Function | () => {} | Is passed Mapbox geocoder instance as param and is executed after Mapbox geocoder is initialized.
74 | | onClear | Function | () => {} | Executed when the input is cleared.
75 | | onLoading | Function | () => {} | Is passed `{ query }` as a param and is executed when the geocoder is looking up a query.
76 | | onResults | Function | () => {} | Is passed `{ results }` as a param and is executed when the geocoder returns a response.
77 | | onResult | Function | () => {} | Is passed `{ result }` as a param and is executed when the geocoder input is set.
78 | | onError | Function | () => {} | Is passed `{ error }` as a param and is executed when an error occurs with the geocoder.
79 |
80 |
81 |
82 | ## Examples
83 |
84 | ### Simple Example
85 | ```js
86 | import 'mapbox-gl/dist/mapbox-gl.css'
87 | import 'react-map-gl-geocoder/dist/mapbox-gl-geocoder.css'
88 | import React, { useState, useRef, useCallback } from 'react'
89 | import MapGL from 'react-map-gl'
90 | import Geocoder from 'react-map-gl-geocoder'
91 |
92 | // Ways to set Mapbox token: https://uber.github.io/react-map-gl/#/Documentation/getting-started/about-mapbox-tokens
93 | const MAPBOX_TOKEN = 'REPLACE_WITH_YOUR_MAPBOX_TOKEN'
94 |
95 | const Example = () => {
96 | const [viewport, setViewport] = useState({
97 | latitude: 37.7577,
98 | longitude: -122.4376,
99 | zoom: 8
100 | });
101 | const mapRef = useRef();
102 | const handleViewportChange = useCallback(
103 | (newViewport) => setViewport(newViewport),
104 | []
105 | );
106 |
107 | // if you are happy with Geocoder default settings, you can just use handleViewportChange directly
108 | const handleGeocoderViewportChange = useCallback(
109 | (newViewport) => {
110 | const geocoderDefaultOverrides = { transitionDuration: 1000 };
111 |
112 | return handleViewportChange({
113 | ...newViewport,
114 | ...geocoderDefaultOverrides
115 | });
116 | },
117 | []
118 | );
119 |
120 | return (
121 |
122 |
130 |
136 |
137 |
138 | );
139 | };
140 |
141 | export default Example
142 | ```
143 |
144 | ### Ignore Map Events Example
145 | You can use the `containerRef` prop to place the `Geocoder` component outside of the `MapGL` component to avoid propagating the mouse events to the `MapGL` component. You can use CSS to position it over the map as shown in this example.
146 | ```js
147 | import 'mapbox-gl/dist/mapbox-gl.css'
148 | import 'react-map-gl-geocoder/dist/mapbox-gl-geocoder.css'
149 | import React, { useState, useRef, useCallback } from 'react'
150 | import MapGL from 'react-map-gl'
151 | import Geocoder from 'react-map-gl-geocoder'
152 |
153 | // Ways to set Mapbox token: https://uber.github.io/react-map-gl/#/Documentation/getting-started/about-mapbox-tokens
154 | const MAPBOX_TOKEN = 'REPLACE_WITH_YOUR_MAPBOX_TOKEN'
155 |
156 | const Example = () => {
157 | const [viewport, setViewport] = useState({
158 | latitude: 37.7577,
159 | longitude: -122.4376,
160 | zoom: 8,
161 | });
162 | const geocoderContainerRef = useRef();
163 | const mapRef = useRef();
164 | const handleViewportChange = useCallback(
165 | (newViewport) => setViewport(newViewport),
166 | []
167 | );
168 |
169 | return (
170 |
171 |
175 |
183 |
190 |
191 |
192 | );
193 | };
194 | ```
195 |
196 | ## Sample Screenshot
197 | 
198 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 | /dist
12 |
13 | # misc
14 | .DS_Store
15 | .env.local
16 | .env.development.local
17 | .env.test.local
18 | .env.production.local
19 |
20 | npm-debug.log*
21 | yarn-debug.log*
22 | yarn-error.log*
23 |
24 | .idea
25 | .cache
26 | .vscode
27 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # react-map-gl-geocoder-example
2 | This app can be used by developers to manual test local changes to `react-map-gl-geocoder` component.
3 |
4 | ## Getting Started
5 | 1. Install dependencies for this app by running `npm install`.
6 | 1. Run `npm start` to start app.
7 | 1. Run `npm run watch` in root of `react-map-gl-geocoder` folder to rebuild the `react-map-gl-geocoder` dependency when changes are made.
8 |
--------------------------------------------------------------------------------
/example/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "projectId": "etguoj"
3 | }
4 |
--------------------------------------------------------------------------------
/example/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
--------------------------------------------------------------------------------
/example/cypress/integration/basicJourney.spec.js:
--------------------------------------------------------------------------------
1 | describe('basic user journey', () => {
2 | it('can make a query, select a location from the suggestion list, and display marker', () => {
3 | cy.server()
4 | cy.visit('http://localhost:3000')
5 | cy.get('input').type('new york')
6 | cy.contains('New York City').click()
7 | cy.get('.mapboxgl-marker').should('exist')
8 | })
9 | })
10 |
--------------------------------------------------------------------------------
/example/cypress/plugins/index.js:
--------------------------------------------------------------------------------
1 | ///
2 | // ***********************************************************
3 | // This example plugins/index.js can be used to load plugins
4 | //
5 | // You can change the location of this file or turn off loading
6 | // the plugins file with the 'pluginsFile' configuration option.
7 | //
8 | // You can read more here:
9 | // https://on.cypress.io/plugins-guide
10 | // ***********************************************************
11 |
12 | // This function is called when a project is opened or re-opened (e.g. due to
13 | // the project's config changing)
14 |
15 | /**
16 | * @type {Cypress.PluginConfig}
17 | */
18 | // eslint-disable-next-line no-unused-vars
19 | module.exports = (on, config) => {
20 | // `on` is used to hook into various events Cypress emits
21 | // `config` is the resolved Cypress config
22 | }
23 |
--------------------------------------------------------------------------------
/example/cypress/support/commands.js:
--------------------------------------------------------------------------------
1 | // ***********************************************
2 | // This example commands.js shows you how to
3 | // create various custom commands and overwrite
4 | // existing commands.
5 | //
6 | // For more comprehensive examples of custom
7 | // commands please read more here:
8 | // https://on.cypress.io/custom-commands
9 | // ***********************************************
10 | //
11 | //
12 | // -- This is a parent command --
13 | // Cypress.Commands.add("login", (email, password) => { ... })
14 | //
15 | //
16 | // -- This is a child command --
17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
18 | //
19 | //
20 | // -- This is a dual command --
21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
22 | //
23 | //
24 | // -- This will overwrite an existing command --
25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
26 |
--------------------------------------------------------------------------------
/example/cypress/support/index.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/index.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | // Import commands.js using ES2015 syntax:
17 | import './commands'
18 |
19 | // Alternatively you can use CommonJS syntax:
20 | // require('./commands')
21 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-map-gl-geocoder-v2-example",
3 | "version": "1.0.0",
4 | "description": "\nExample usage of react-map-gl-geocoder which is a React wrapper for mapbox-gl-geocoder for use with react-map-gl",
5 | "keywords": [],
6 | "main": "src/index.js",
7 | "devDependencies": {
8 | "cypress": "^5.1.0",
9 | "react": "16.13.1",
10 | "react-dom": "16.13.1",
11 | "react-map-gl": "5.2.3",
12 | "react-map-gl-geocoder": "file:../",
13 | "react-scripts": "^3.4.3"
14 | },
15 | "scripts": {
16 | "start": "react-scripts start",
17 | "test": "cypress open"
18 | },
19 | "browserslist": {
20 | "production": [
21 | ">0.2%",
22 | "not dead",
23 | "not op_mini all"
24 | ],
25 | "development": [
26 | "last 1 chrome version",
27 | "last 1 firefox version",
28 | "last 1 safari version"
29 | ]
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/example/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
23 | React App
24 |
30 |
31 |
32 |
33 |
36 |
37 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/example/src/index.js:
--------------------------------------------------------------------------------
1 | import 'mapbox-gl/dist/mapbox-gl.css'
2 | import 'react-map-gl-geocoder/dist/mapbox-gl-geocoder.css'
3 | import React, { useState, useRef, useCallback } from 'react'
4 | import { render } from 'react-dom'
5 | import MapGL from 'react-map-gl'
6 | import Geocoder from 'react-map-gl-geocoder'
7 |
8 | // Please be a decent human and don't abuse my Mapbox API token.
9 | // If you fork this sandbox, replace my API token with your own.
10 | // Ways to set Mapbox token: https://uber.github.io/react-map-gl/#/Documentation/getting-started/about-mapbox-tokens
11 | const MAPBOX_TOKEN = 'pk.eyJ1Ijoic21peWFrYXdhIiwiYSI6ImNqcGM0d3U4bTB6dWwzcW04ZHRsbHl0ZWoifQ.X9cvdajtPbs9JDMG-CMDsA'
12 |
13 | const App = () => {
14 | const [viewport, setViewport] = useState({
15 | latitude: 37.7577,
16 | longitude: -122.4376,
17 | zoom: 8
18 | })
19 | const geocoderContainerRef = useRef()
20 | const mapRef = useRef()
21 | const handleViewportChange = useCallback((newViewport) => setViewport(newViewport), [])
22 |
23 | // if you are happy with Geocoder default settings, you can just use handleViewportChange directly
24 | const handleGeocoderViewportChange = useCallback(
25 | (newViewport) => {
26 | const geocoderDefaultOverrides = { transitionDuration: 1000 }
27 |
28 | return handleViewportChange({
29 | ...newViewport,
30 | ...geocoderDefaultOverrides
31 | })
32 | },
33 | [handleViewportChange]
34 | )
35 |
36 | return (
37 |