├── .eslintignore ├── .eslintrc.cjs ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ └── feature-request.yml ├── SECURITY.md └── workflows │ ├── release.yml │ ├── test.yml │ └── website.yml ├── .gitignore ├── .ocularrc.js ├── .prettierrc ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── TESTING.md ├── docs ├── .gitignore ├── README.md ├── api-reference │ ├── mapbox │ │ ├── attribution-control.md │ │ ├── fullscreen-control.md │ │ ├── geolocate-control.md │ │ ├── layer.md │ │ ├── map-provider.md │ │ ├── map.md │ │ ├── marker.md │ │ ├── navigation-control.md │ │ ├── popup.md │ │ ├── scale-control.md │ │ ├── source.md │ │ ├── types.md │ │ ├── use-control.md │ │ └── use-map.md │ └── maplibre │ │ ├── attribution-control.md │ │ ├── fullscreen-control.md │ │ ├── geolocate-control.md │ │ ├── layer.md │ │ ├── logo-control.md │ │ ├── map-provider.md │ │ ├── map.md │ │ ├── marker.md │ │ ├── navigation-control.md │ │ ├── popup.md │ │ ├── scale-control.md │ │ ├── source.md │ │ ├── terrain-control.md │ │ ├── types.md │ │ ├── use-control.md │ │ └── use-map.md ├── contributing.md ├── get-started │ ├── adding-custom-data.md │ ├── get-started.md │ ├── mapbox-tokens.md │ ├── state-management.md │ └── tips-and-tricks.md ├── table-of-contents.json ├── upgrade-guide.md └── whats-new.md ├── examples ├── .data │ ├── bart-station.json │ ├── cities.json │ ├── feature-example-sf.json │ ├── us-election-2016.json │ └── us-income.geojson ├── .eslintrc ├── get-started │ ├── basic │ │ ├── README.md │ │ ├── app.jsx │ │ ├── index.html │ │ ├── package.json │ │ └── vite.config.js │ ├── controlled │ │ ├── README.md │ │ ├── app.jsx │ │ ├── index.html │ │ ├── package.json │ │ └── vite.config.js │ ├── hook │ │ ├── README.md │ │ ├── app.jsx │ │ ├── controls.jsx │ │ ├── controls2.jsx │ │ ├── index.html │ │ ├── map.jsx │ │ ├── package.json │ │ └── vite.config.js │ ├── maplibre │ │ ├── README.md │ │ ├── app.jsx │ │ ├── index.html │ │ └── package.json │ ├── nextjs │ │ ├── .gitignore │ │ ├── README.md │ │ ├── next.config.js │ │ ├── package.json │ │ └── pages │ │ │ ├── _app.js │ │ │ └── index.js │ └── redux │ │ ├── README.md │ │ ├── app.jsx │ │ ├── controls.jsx │ │ ├── index.html │ │ ├── map.jsx │ │ ├── package.json │ │ ├── store.js │ │ └── vite.config.js ├── mapbox │ ├── clusters │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── layers.ts │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── controls │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── pin.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── custom-cursor │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── custom-overlay │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── custom-overlay.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── deckgl-overlay │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ └── app.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── draggable-markers │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── pin.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── draw-polygon │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── draw-control.ts │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── filter │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── map-style.ts │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── geocoder │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── geocoder-control.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── geojson-animation │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── geojson │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ ├── map-style.ts │ │ │ └── utils.ts │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── heatmap │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── map-style.ts │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── interaction │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── layers │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── map-style-basic-v8.json │ ├── side-by-side │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── terrain │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── viewport-animation │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ └── zoom-to-bounds │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ ├── app.tsx │ │ ├── control-panel.tsx │ │ └── map-style.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js ├── maplibre │ ├── clusters │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── layers.ts │ │ └── tsconfig.json │ ├── controls │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── pin.tsx │ │ └── tsconfig.json │ ├── custom-cursor │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ └── tsconfig.json │ ├── custom-overlay │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── custom-overlay.tsx │ │ └── tsconfig.json │ ├── deckgl-overlay │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ └── app.tsx │ │ └── tsconfig.json │ ├── draggable-markers │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── pin.tsx │ │ └── tsconfig.json │ ├── draw-polygon │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── draw-control.ts │ │ └── tsconfig.json │ ├── filter │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── map-style.ts │ │ └── tsconfig.json │ ├── geocoder │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── geocoder-control.tsx │ │ └── tsconfig.json │ ├── geojson-animation │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ └── tsconfig.json │ ├── geojson │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ ├── map-style.ts │ │ │ └── utils.ts │ │ └── tsconfig.json │ ├── globe │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ └── tsconfig.json │ ├── heatmap │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── map-style.ts │ │ └── tsconfig.json │ ├── interaction │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ └── tsconfig.json │ ├── layers │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ └── tsconfig.json │ ├── map-style-basic-v8.json │ ├── side-by-side │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ └── tsconfig.json │ ├── terrain │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ └── tsconfig.json │ ├── viewport-animation │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ │ ├── app.tsx │ │ │ └── control-panel.tsx │ │ └── tsconfig.json │ └── zoom-to-bounds │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ ├── app.tsx │ │ ├── control-panel.tsx │ │ └── map-style.tsx │ │ └── tsconfig.json └── vite.config.local.js ├── index.html ├── lerna.json ├── modules ├── main │ ├── README.md │ ├── package.json │ ├── src │ │ ├── mapbox-legacy │ │ │ ├── components │ │ │ │ ├── attribution-control.ts │ │ │ │ ├── fullscreen-control.ts │ │ │ │ ├── geolocate-control.ts │ │ │ │ ├── layer.ts │ │ │ │ ├── map.tsx │ │ │ │ ├── marker.ts │ │ │ │ ├── navigation-control.ts │ │ │ │ ├── popup.ts │ │ │ │ ├── scale-control.ts │ │ │ │ ├── source.ts │ │ │ │ ├── use-control.ts │ │ │ │ └── use-map.tsx │ │ │ ├── index.ts │ │ │ ├── mapbox │ │ │ │ ├── create-ref.ts │ │ │ │ └── mapbox.ts │ │ │ ├── types │ │ │ │ ├── common.ts │ │ │ │ ├── events.ts │ │ │ │ ├── internal.ts │ │ │ │ ├── lib.ts │ │ │ │ └── style-spec.ts │ │ │ └── utils │ │ │ │ ├── apply-react-style.ts │ │ │ │ ├── assert.ts │ │ │ │ ├── deep-equal.ts │ │ │ │ ├── set-globals.ts │ │ │ │ ├── style-utils.ts │ │ │ │ ├── transform.ts │ │ │ │ └── use-isomorphic-layout-effect.ts │ │ ├── mapbox.ts │ │ └── maplibre.ts │ ├── test │ │ ├── components │ │ │ ├── controls.spec.jsx │ │ │ ├── index.js │ │ │ ├── layer.spec.jsx │ │ │ ├── map.spec.jsx │ │ │ ├── marker.spec.jsx │ │ │ ├── popup.spec.jsx │ │ │ ├── source.spec.jsx │ │ │ └── use-map.spec.jsx │ │ └── utils │ │ │ ├── apply-react-style.spec.js │ │ │ ├── deep-equal.spec.js │ │ │ ├── index.js │ │ │ ├── mapbox-gl-mock │ │ │ ├── edge_insets.js │ │ │ ├── lng_lat.js │ │ │ ├── lng_lat_bounds.js │ │ │ ├── transform.js │ │ │ └── util.js │ │ │ ├── style-utils.spec.js │ │ │ ├── test-utils.jsx │ │ │ └── transform.spec.js │ └── tsconfig.json ├── react-mapbox │ ├── package.json │ ├── src │ │ ├── components │ │ │ ├── attribution-control.ts │ │ │ ├── fullscreen-control.ts │ │ │ ├── geolocate-control.ts │ │ │ ├── layer.ts │ │ │ ├── map.tsx │ │ │ ├── marker.ts │ │ │ ├── navigation-control.ts │ │ │ ├── popup.ts │ │ │ ├── scale-control.ts │ │ │ ├── source.ts │ │ │ ├── use-control.ts │ │ │ └── use-map.tsx │ │ ├── index.ts │ │ ├── mapbox │ │ │ ├── create-ref.ts │ │ │ ├── mapbox.ts │ │ │ └── proxy-transform.ts │ │ ├── types │ │ │ ├── common.ts │ │ │ ├── events.ts │ │ │ ├── internal.ts │ │ │ ├── lib.ts │ │ │ └── style-spec.ts │ │ └── utils │ │ │ ├── apply-react-style.ts │ │ │ ├── assert.ts │ │ │ ├── compare-class-names.ts │ │ │ ├── deep-equal.ts │ │ │ ├── set-globals.ts │ │ │ ├── style-utils.ts │ │ │ ├── transform.ts │ │ │ └── use-isomorphic-layout-effect.ts │ ├── test │ │ ├── components │ │ │ ├── controls.spec.jsx │ │ │ ├── index.js │ │ │ ├── layer.spec.jsx │ │ │ ├── map.spec.jsx │ │ │ ├── marker.spec.jsx │ │ │ ├── popup.spec.jsx │ │ │ ├── source.spec.jsx │ │ │ └── use-map.spec.jsx │ │ └── utils │ │ │ ├── apply-react-style.spec.js │ │ │ ├── compare-class-names.spec.js │ │ │ ├── deep-equal.spec.js │ │ │ ├── index.js │ │ │ ├── mapbox-gl-mock │ │ │ ├── edge_insets.js │ │ │ ├── lng_lat.js │ │ │ ├── lng_lat_bounds.js │ │ │ ├── transform.js │ │ │ └── util.js │ │ │ ├── style-utils.spec.js │ │ │ ├── test-utils.jsx │ │ │ ├── token.js │ │ │ └── transform.spec.js │ └── tsconfig.json └── react-maplibre │ ├── package.json │ ├── src │ ├── components │ │ ├── attribution-control.ts │ │ ├── fullscreen-control.ts │ │ ├── geolocate-control.ts │ │ ├── layer.ts │ │ ├── logo-control.ts │ │ ├── map.tsx │ │ ├── marker.ts │ │ ├── navigation-control.ts │ │ ├── popup.ts │ │ ├── scale-control.ts │ │ ├── source.ts │ │ ├── terrain-control.ts │ │ ├── use-control.ts │ │ └── use-map.tsx │ ├── index.ts │ ├── maplibre │ │ ├── create-ref.ts │ │ └── maplibre.ts │ ├── types │ │ ├── common.ts │ │ ├── events.ts │ │ ├── internal.ts │ │ ├── lib.ts │ │ └── style-spec.ts │ └── utils │ │ ├── apply-react-style.ts │ │ ├── assert.ts │ │ ├── compare-class-names.ts │ │ ├── deep-equal.ts │ │ ├── set-globals.ts │ │ ├── style-utils.ts │ │ ├── transform.ts │ │ └── use-isomorphic-layout-effect.ts │ ├── test │ ├── .eslintrc │ ├── components │ │ ├── controls.spec.jsx │ │ ├── index.js │ │ ├── layer.spec.jsx │ │ ├── map.spec.jsx │ │ ├── marker.spec.jsx │ │ ├── popup.spec.jsx │ │ ├── source.spec.jsx │ │ └── use-map.spec.jsx │ └── utils │ │ ├── apply-react-style.spec.js │ │ ├── compare-class-names.spec.js │ │ ├── deep-equal.spec.js │ │ ├── index.js │ │ ├── style-utils.spec.js │ │ ├── test-utils.jsx │ │ └── transform.spec.js │ └── tsconfig.json ├── package.json ├── scripts └── update-release-branch.sh ├── test ├── .eslintrc ├── apps │ └── reuse-maps │ │ ├── index.html │ │ ├── package.json │ │ ├── src │ │ └── app.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js ├── browser.js ├── data │ ├── glyph │ │ └── UberMove │ │ │ └── 0-255 │ ├── sprite │ │ └── tools │ │ │ └── 14 │ │ │ ├── sprites.json │ │ │ └── sprites.png │ ├── style.json │ └── tile │ │ └── v1 │ │ └── 12 │ │ └── 655 │ │ ├── 1582 │ │ ├── COMPOSITE │ │ └── POI │ │ └── 1583 │ │ ├── COMPOSITE │ │ └── POI ├── node.js ├── render │ ├── golden-images │ │ ├── alt-empty-map.png │ │ ├── basic-map.png │ │ ├── geolocate-control.png │ │ ├── marker.png │ │ ├── navigation-control.png │ │ ├── popup.png │ │ ├── source-01.png │ │ ├── source-02.png │ │ └── uber-map.png │ ├── index.jsx │ └── test-cases.jsx ├── size │ ├── mapbox-legacy.js │ ├── mapbox.js │ └── maplibre.js ├── src │ └── exports.ts └── test-utils.js ├── tsconfig.json ├── website ├── .eslintignore ├── .gitignore ├── babel.config.js ├── docusaurus.config.js ├── package.json ├── src │ ├── examples │ │ ├── index.mdx │ │ ├── mapbox │ │ │ ├── clusters.mdx │ │ │ ├── controls.mdx │ │ │ ├── custom-cursor.mdx │ │ │ ├── draggable-markers.mdx │ │ │ ├── draw-polygon.mdx │ │ │ ├── filter.mdx │ │ │ ├── geocoder.mdx │ │ │ ├── geojson-animation.mdx │ │ │ ├── geojson.mdx │ │ │ ├── heatmap.mdx │ │ │ ├── interaction.mdx │ │ │ ├── layers.mdx │ │ │ ├── side-by-side.mdx │ │ │ ├── terrain.mdx │ │ │ ├── viewport-animation.mdx │ │ │ └── zoom-to-bounds.mdx │ │ ├── maplibre │ │ │ ├── clusters.mdx │ │ │ ├── controls.mdx │ │ │ ├── custom-cursor.mdx │ │ │ ├── draggable-markers.mdx │ │ │ ├── draw-polygon.mdx │ │ │ ├── filter.mdx │ │ │ ├── geocoder.mdx │ │ │ ├── geojson-animation.mdx │ │ │ ├── geojson.mdx │ │ │ ├── heatmap.mdx │ │ │ ├── interaction.mdx │ │ │ ├── layers.mdx │ │ │ ├── side-by-side.mdx │ │ │ ├── terrain.mdx │ │ │ ├── viewport-animation.mdx │ │ │ └── zoom-to-bounds.mdx │ │ └── table-of-contents.json │ ├── mapbox-gl.css │ ├── maplibre-gl.css │ ├── pages │ │ └── index.jsx │ └── styles.css ├── static │ ├── favicon.ico │ └── images │ │ ├── examples │ │ ├── clusters.jpg │ │ ├── controls.jpg │ │ ├── custom-cursor.jpg │ │ ├── draggable-markers.jpg │ │ ├── draw-polygon.jpg │ │ ├── filter.jpg │ │ ├── geocoder.jpg │ │ ├── geojson-animation.jpg │ │ ├── geojson.jpg │ │ ├── heatmap.jpg │ │ ├── interaction.jpg │ │ ├── layers.jpg │ │ ├── side-by-side.jpg │ │ ├── terrain.jpg │ │ ├── viewport-animation.jpg │ │ └── zoom-to-bounds.jpg │ │ ├── hero-sm.jpg │ │ ├── hero.jpg │ │ ├── icon-high-precision.svg │ │ ├── icon-layers.svg │ │ ├── icon-react.svg │ │ ├── visgl-logo-dark.png │ │ ├── visgl-logo-light.png │ │ └── visgl-logo.png └── yarn.lock └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | test/ 4 | modules/**/test/ 5 | **/vite.config.js 6 | examples/vite.config.local.js 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: I have a question / I need help 4 | url: https://github.com/visgl/react-map-gl/discussions 5 | about: Ask generic questions or request help here 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Request for a new feature or enhancement 3 | title: "[Feat]" 4 | labels: feature 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Tell us what you are using react-map-gl for and how we can make it better. 10 | This project is maintained by volunteers and sponsoring companies. While we cannot promise a timeline for any specific feature, we try to prioritize those that will benefit the most users. 11 | - type: textarea 12 | attributes: 13 | label: Target Use Case 14 | description: How would this benefit you and other developers? 15 | validations: 16 | required: true 17 | - type: textarea 18 | attributes: 19 | label: Proposal 20 | description: How would this feature work? If it's a new API, use code samples to show how it will be used. If it's visual, link to an image that illustrate the desired effect. 21 | validations: 22 | required: true 23 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Security updates are applied only to the latest release. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released. 10 | 11 | Please disclose it at [security advisory](https://github.com/visgl/react-map-gl/security/advisories/new). 12 | 13 | This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure. 14 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | # On every pull request, but only on push to master 4 | on: 5 | push: 6 | branches: 7 | - master 8 | pull_request: 9 | 10 | jobs: 11 | test-node: 12 | runs-on: ubuntu-22.04 13 | 14 | steps: 15 | - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 16 | - uses: volta-cli/action@2d68418f32546fd191eb666e232b321d5726484d # v4.1.1 17 | with: 18 | cache: "yarn" 19 | 20 | - name: Install dependencies 21 | run: | 22 | yarn bootstrap 23 | 24 | - name: Run tests 25 | env: 26 | VITE_MAPBOX_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN_CI }} 27 | run: | 28 | yarn lint 29 | yarn test ci 30 | 31 | - name: Coveralls 32 | uses: coverallsapp/github-action@09b709cf6a16e30b0808ba050c7a6e8a5ef13f8d # v1.2.5 33 | with: 34 | github-token: ${{ secrets.GITHUB_TOKEN }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | dist-es6/ 3 | 4 | node_modules 5 | .nyc_output/ 6 | coverage 7 | npm-debug.log 8 | 9 | package-lock.json 10 | examples/**/yarn.lock 11 | test/**/yarn.lock 12 | **/package-lock.json 13 | **/tsconfig.tsbuildinfo 14 | yarn-error.log 15 | .DS_Store 16 | .reify-cache 17 | tsconfig.tsbuildinfo 18 | 19 | .idea 20 | -------------------------------------------------------------------------------- /.ocularrc.js: -------------------------------------------------------------------------------- 1 | /** @typedef {import('@vis.gl/dev-tools').OcularConfig} OcularConfig */ 2 | import {resolve} from 'path'; 3 | 4 | /** @type {OcularConfig} */ 5 | export default { 6 | lint: { 7 | paths: ['modules', 'test', 'examples'] 8 | }, 9 | 10 | coverage: { 11 | test: 'browser' 12 | }, 13 | 14 | aliases: { 15 | }, 16 | 17 | browserTest: { 18 | server: {wait: 5000} 19 | }, 20 | 21 | entry: { 22 | test: 'test/node.js', 23 | 'test-browser': 'test/browser.js', 24 | size: [ 25 | 'test/size/mapbox-legacy.js', 26 | 'test/size/maplibre.js', 27 | 'test/size/mapbox.js' 28 | ] 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | printWidth: 100 2 | semi: true 3 | singleQuote: true 4 | trailingComma: none 5 | bracketSpacing: false 6 | arrowParens: avoid 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | react-map-gl is an [OpenJS Foundation](https://openjsf.org/) project. Please be mindful of and adhere to the OpenJS Foundation's [Code of Conduct](https://github.com/openjs-foundation/cross-project-council/blob/main/CODE_OF_CONDUCT.md) when contributing to react-map-gl. -------------------------------------------------------------------------------- /TESTING.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | ## Unit, Lint 4 | 5 | ``` 6 | npm run test 7 | ``` 8 | 9 | ## Browser 10 | 11 | ``` 12 | npm run test-browser 13 | ``` 14 | 15 | **You'll need to specify a valid Mapbox Access Token in the URL** for the tests to pass. 16 | 17 | ``` 18 | http://localhost:8080/?access_token=MAPBOX_ACCESS_TOKEN 19 | ``` 20 | 21 | # Bumping Mapbox Version 22 | 23 | Always pin Mapbox to a specific release. 24 | 25 | The React controls (`NavigationControl`, `Popup` and `Marker`) are dependent on 26 | the Mapbox stylesheet, and may be broken by Mapbox updates. 27 | Always run `examples/controls` after bumping Mapbox version to make sure they 28 | still work. 29 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | api-reference/web-mercator-viewport.md 2 | -------------------------------------------------------------------------------- /docs/api-reference/mapbox/map-provider.md: -------------------------------------------------------------------------------- 1 | # MapProvider 2 | 3 | A [Context.Provider](https://reactjs.org/docs/context.html#contextprovider) that facilitates map operations outside of the component that directly renders a [Map](./map.md). 4 | 5 | The component should wrap all nodes in which you may want to access the maps: 6 | 7 | ```tsx 8 | import {MapProvider} from 'react-map-gl/mapbox'; 9 | 10 | function Root() { 11 | return ( 12 | 13 | { 14 | // Application tree, somewhere one or more component(s) are rendered 15 | } 16 | 17 | ); 18 | } 19 | ``` 20 | 21 | See [useMap](./use-map.md) for more information. 22 | 23 | 24 | ## Source 25 | 26 | [use-map.tsx](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/use-map.tsx) 27 | -------------------------------------------------------------------------------- /docs/api-reference/maplibre/map-provider.md: -------------------------------------------------------------------------------- 1 | # MapProvider 2 | 3 | A [Context.Provider](https://reactjs.org/docs/context.html#contextprovider) that facilitates map operations outside of the component that directly renders a [Map](./map.md). 4 | 5 | The component should wrap all nodes in which you may want to access the maps: 6 | 7 | ```tsx 8 | import {MapProvider} from 'react-map-gl/maplibre'; 9 | 10 | function Root() { 11 | return ( 12 | 13 | { 14 | // Application tree, somewhere one or more component(s) are rendered 15 | } 16 | 17 | ); 18 | } 19 | ``` 20 | 21 | See [useMap](./use-map.md) for more information. 22 | 23 | 24 | ## Source 25 | 26 | [use-map.tsx](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/use-map.tsx) 27 | -------------------------------------------------------------------------------- /docs/contributing.md: -------------------------------------------------------------------------------- 1 | ../CONTRIBUTING.md -------------------------------------------------------------------------------- /examples/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "import/no-unresolved": 0, 4 | "import/no-extraneous-dependencies": 0 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/get-started/basic/README.md: -------------------------------------------------------------------------------- 1 | # react-map-gl Example: Using Map as a stateful component 2 | 3 | This example shows a minimal app configuration to use react-map-gl's Map component with automatic view state updates. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | Alternative to acquiring a Mapbox token, visit the [maplibre-gl example](../maplibre). 10 | 11 | ```bash 12 | npm i 13 | npm run start 14 | ``` 15 | 16 | To build a production version: 17 | 18 | ```bash 19 | npm run build 20 | ``` 21 | -------------------------------------------------------------------------------- /examples/get-started/basic/app.jsx: -------------------------------------------------------------------------------- 1 | /* global document */ 2 | import * as React from 'react'; 3 | import {createRoot} from 'react-dom/client'; 4 | import Map, {Marker} from 'react-map-gl/mapbox'; 5 | 6 | import 'mapbox-gl/dist/mapbox-gl.css'; 7 | 8 | const MAPBOX_TOKEN = ''; // Set your mapbox token here 9 | 10 | function Root() { 11 | return ( 12 | 22 | 23 | 24 | ); 25 | } 26 | 27 | const root = createRoot(document.body.appendChild(document.createElement('div'))); 28 | root.render(); 29 | -------------------------------------------------------------------------------- /examples/get-started/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/get-started/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "build": "vite build" 5 | }, 6 | "dependencies": { 7 | "react": "^18.0.0", 8 | "react-dom": "^18.0.0", 9 | "react-map-gl": "^8.0.0", 10 | "mapbox-gl": "^3.5.0" 11 | }, 12 | "devDependencies": { 13 | "typescript": "^5.0.0", 14 | "vite": "^4.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/get-started/basic/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/get-started/controlled/README.md: -------------------------------------------------------------------------------- 1 | # react-map-gl Example: Using Map as a controlled component 2 | 3 | This example shows a minimal app configuration to use react-map-gl's Map component with external view state management. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | Alternative to acquiring a Mapbox token, you can install `maplibre-gl` and change all `import from 'react-map-gl/mapbox'` to `import from 'react-map-gl/maplibre'`. You also need to supply a third-party or self-hosted `mapStyle` URL. 10 | 11 | ```bash 12 | npm i 13 | npm run start 14 | ``` 15 | 16 | To build a production version: 17 | 18 | ```bash 19 | npm run build 20 | ``` 21 | -------------------------------------------------------------------------------- /examples/get-started/controlled/app.jsx: -------------------------------------------------------------------------------- 1 | /* global document */ 2 | import * as React from 'react'; 3 | import {createRoot} from 'react-dom/client'; 4 | import Map, {Marker} from 'react-map-gl/mapbox'; 5 | 6 | import 'mapbox-gl/dist/mapbox-gl.css'; 7 | 8 | const MAPBOX_TOKEN = ''; // Set your mapbox token here 9 | 10 | function Root() { 11 | const [viewState, setViewState] = React.useState({ 12 | latitude: 37.8, 13 | longitude: -122.4, 14 | zoom: 14 15 | }); 16 | 17 | return ( 18 | setViewState(evt.viewState)} 21 | style={{width: 800, height: 600}} 22 | mapStyle="mapbox://styles/mapbox/streets-v9" 23 | mapboxAccessToken={MAPBOX_TOKEN} 24 | > 25 | 26 | 27 | ); 28 | } 29 | 30 | const root = createRoot(document.body.appendChild(document.createElement('div'))); 31 | root.render(); 32 | -------------------------------------------------------------------------------- /examples/get-started/controlled/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/get-started/controlled/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "build": "vite build" 5 | }, 6 | "dependencies": { 7 | "react": "^18.0.0", 8 | "react-dom": "^18.0.0", 9 | "react-map-gl": "^8.0.0", 10 | "mapbox-gl": "^3.5.0" 11 | }, 12 | "devDependencies": { 13 | "typescript": "^5.0.0", 14 | "vite": "^4.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/get-started/controlled/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/get-started/hook/README.md: -------------------------------------------------------------------------------- 1 | # react-map-gl Example: Using Map with a State Management System 2 | 3 | This example shows how to use react-map-gl's Map component with the `useMap` hook. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `map.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | Alternative to acquiring a Mapbox token, you can install `maplibre-gl` and change all `import from 'react-map-gl/mapbox'` to `import from 'react-map-gl/maplibre'`. You also need to supply a third-party or self-hosted `mapStyle` URL. 10 | 11 | ```bash 12 | npm i 13 | npm run start 14 | ``` 15 | 16 | To build a production version: 17 | 18 | ```bash 19 | npm run build 20 | ``` 21 | -------------------------------------------------------------------------------- /examples/get-started/hook/app.jsx: -------------------------------------------------------------------------------- 1 | /* global document */ 2 | import * as React from 'react'; 3 | import {createRoot} from 'react-dom/client'; 4 | import {MapProvider} from 'react-map-gl/mapbox'; 5 | 6 | import Map from './map'; 7 | import Controls from './controls'; 8 | 9 | function Root() { 10 | // Note: `useMap` will not work here, only child components of `MapProvider` or `Map` can use `useMap` 11 | 12 | return ( 13 | 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | const root = createRoot(document.body.appendChild(document.createElement('div'))); 21 | root.render(); 22 | -------------------------------------------------------------------------------- /examples/get-started/hook/controls2.jsx: -------------------------------------------------------------------------------- 1 | // import {useMap} from 'react-map-gl/mapbox'; 2 | 3 | export default function Controls2() { 4 | /** 5 | * ## This is how `useMap` works: 6 | * This component does nothing. It's purpose is to demo `useMap`. 7 | * When a component is a child of ``, `useMap` has a `current` field that references the containing map. 8 | * See https://visgl.github.io/react-map-gl/docs/api-reference/use-map 9 | * See https://visgl.github.io/react-map-gl/docs/api-reference/types#mapref 10 | * ``` 11 | * const maps = useMap(); 12 | * console.log('Controls2 useMap()', maps); 13 | * ``` 14 | * ### First render: 15 | * ``` 16 | * { 17 | * "current": {...}, // this is the same as `mymap` 18 | * "mymap": {...} 19 | * } 20 | * ``` 21 | */ 22 | 23 | return null; 24 | } 25 | -------------------------------------------------------------------------------- /examples/get-started/hook/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/get-started/hook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "build": "vite build" 5 | }, 6 | "dependencies": { 7 | "react": "^18.0.0", 8 | "react-dom": "^18.0.0", 9 | "react-map-gl": "^8.0.0", 10 | "mapbox-gl": "^3.5.0" 11 | }, 12 | "devDependencies": { 13 | "typescript": "^5.0.0", 14 | "vite": "^4.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/get-started/hook/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/get-started/maplibre/README.md: -------------------------------------------------------------------------------- 1 | # react-map-gl Example: Using with Maplibre 2 | 3 | This example shows a minimal app configuration to use react-map-gl with [Maplibre GL JS](https://maplibre.org/). 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | 12 | To build a production version: 13 | 14 | ```bash 15 | npm run build 16 | ``` 17 | 18 | ## Attribution 19 | 20 | The basemap in this example is provided by [CARTO free basemap service](https://carto.com/basemaps). -------------------------------------------------------------------------------- /examples/get-started/maplibre/app.jsx: -------------------------------------------------------------------------------- 1 | /* global document */ 2 | import * as React from 'react'; 3 | import {createRoot} from 'react-dom/client'; 4 | import Map, {Marker} from 'react-map-gl/maplibre'; 5 | 6 | import 'maplibre-gl/dist/maplibre-gl.css'; 7 | 8 | function Root() { 9 | return ( 10 | 19 | 20 | 21 | ); 22 | } 23 | 24 | const root = createRoot(document.body.appendChild(document.createElement('div'))); 25 | root.render(); 26 | -------------------------------------------------------------------------------- /examples/get-started/maplibre/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/get-started/maplibre/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "build": "vite build" 5 | }, 6 | "dependencies": { 7 | "maplibre-gl": "^5.0.0", 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0" 11 | }, 12 | "devDependencies": { 13 | "typescript": "^5.0.0", 14 | "vite": "^4.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/get-started/nextjs/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /examples/get-started/nextjs/next.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | 3 | module.exports = { 4 | reactStrictMode: true, 5 | 6 | webpack: config => { 7 | // Optional: Enables reading mapbox token from environment variable 8 | config.plugins.push(new webpack.EnvironmentPlugin({MapboxAccessToken: ''})); 9 | return config; 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /examples/get-started/nextjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "dev": "next dev", 4 | "build": "next build", 5 | "start": "next start", 6 | "lint": "next lint" 7 | }, 8 | "dependencies": { 9 | "next": "12.0.7", 10 | "react": "17.0.2", 11 | "react-dom": "17.0.2", 12 | "react-map-gl": "^8.0.0", 13 | "mapbox-gl": "^3.5.0" 14 | }, 15 | "devDependencies": { 16 | "eslint": "8.5.0", 17 | "eslint-config-next": "12.0.7" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/get-started/nextjs/pages/_app.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export default function MyApp({Component, pageProps}) { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /examples/get-started/nextjs/pages/index.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Head from 'next/head'; 3 | import Map, {Marker} from 'react-map-gl/mapbox'; 4 | 5 | import 'mapbox-gl/dist/mapbox-gl.css'; 6 | 7 | const MAPBOX_TOKEN = ''; // Set your mapbox token here 8 | 9 | export default function Home() { 10 | return ( 11 |
12 | 13 | react-map-gl example 14 | 15 | 16 | 26 | 27 | 28 |
29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /examples/get-started/redux/README.md: -------------------------------------------------------------------------------- 1 | # react-map-gl Example: Using Map with a State Management System 2 | 3 | This example shows how to use react-map-gl's Map component with react-redux. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `map.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | Alternative to acquiring a Mapbox token, you can install `maplibre-gl` and change all `import from 'react-map-gl/mapbox'` to `import from 'react-map-gl/maplibre'`. You also need to supply a third-party or self-hosted `mapStyle` URL. 10 | 11 | ```bash 12 | npm i 13 | npm run start 14 | ``` 15 | 16 | To build a production version: 17 | 18 | ```bash 19 | npm run build 20 | ``` 21 | -------------------------------------------------------------------------------- /examples/get-started/redux/app.jsx: -------------------------------------------------------------------------------- 1 | /* global document */ 2 | import * as React from 'react'; 3 | import {createRoot} from 'react-dom/client'; 4 | import {Provider} from 'react-redux'; 5 | import store from './store'; 6 | 7 | import Map from './map'; 8 | import Controls from './controls'; 9 | 10 | function Root() { 11 | return ( 12 | 13 | 14 | 15 | 16 | ); 17 | } 18 | 19 | const root = createRoot(document.body.appendChild(document.createElement('div'))); 20 | root.render(); 21 | -------------------------------------------------------------------------------- /examples/get-started/redux/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/get-started/redux/map.jsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import Map from 'react-map-gl/mapbox'; 3 | 4 | import {useCallback} from 'react'; 5 | import {useSelector, useDispatch} from 'react-redux'; 6 | 7 | import 'mapbox-gl/dist/mapbox-gl.css'; 8 | 9 | const MAPBOX_TOKEN = ''; // Set your mapbox token here 10 | 11 | export default function MapView() { 12 | const mapStyle = useSelector(s => s.mapStyle); 13 | const viewState = useSelector(s => s.viewState); 14 | const dispatch = useDispatch(); 15 | 16 | const onMove = useCallback(evt => { 17 | dispatch({type: 'setViewState', payload: evt.viewState}); 18 | }, []); 19 | 20 | return ( 21 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /examples/get-started/redux/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "build": "vite build" 5 | }, 6 | "dependencies": { 7 | "react": "^18.0.0", 8 | "react-dom": "^18.0.0", 9 | "react-map-gl": "^8.0.0", 10 | "react-redux": "^7.0.0", 11 | "mapbox-gl": "^3.5.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/get-started/redux/store.js: -------------------------------------------------------------------------------- 1 | import {createStore} from 'redux'; 2 | 3 | function mapStateReducer(state, action) { 4 | switch (action.type) { 5 | case 'setViewState': 6 | return {...state, viewState: action.payload}; 7 | 8 | default: 9 | return state; 10 | } 11 | } 12 | 13 | const defaultMapState = { 14 | mapStyle: 'mapbox://styles/mapbox/streets-v11', 15 | viewState: { 16 | latitude: 37.8, 17 | longitude: -122.4, 18 | zoom: 14 19 | } 20 | }; 21 | 22 | export default createStore(mapStateReducer, defaultMapState); 23 | -------------------------------------------------------------------------------- /examples/get-started/redux/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/clusters/README.md: -------------------------------------------------------------------------------- 1 | # Example: Supercluster 2 | 3 | This app reproduces Mapbox's [Create and style clusters](https://docs.mapbox.com/mapbox-gl-js/example/cluster/) example. 4 | 5 | This example showcases how to visualize points as clusters. 6 | 7 | ## Usage 8 | 9 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 10 | 11 | ```bash 12 | npm i 13 | npm run start 14 | ``` 15 | 16 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 17 | - Run `npm install maplibre-gl` 18 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 19 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 20 | -------------------------------------------------------------------------------- /examples/mapbox/clusters/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 32 | 33 | 34 |
35 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /examples/mapbox/clusters/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "mapbox-gl": "^3.5.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mapbox/clusters/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Create and Style Clusters

7 |

Use Mapbox GL JS' built-in functions to visualize points as clusters.

8 | 16 |
17 | ); 18 | } 19 | 20 | export default React.memo(ControlPanel); 21 | -------------------------------------------------------------------------------- /examples/mapbox/clusters/src/layers.ts: -------------------------------------------------------------------------------- 1 | import type {LayerProps} from 'react-map-gl/mapbox'; 2 | 3 | export const clusterLayer: LayerProps = { 4 | id: 'clusters', 5 | type: 'circle', 6 | source: 'earthquakes', 7 | filter: ['has', 'point_count'], 8 | paint: { 9 | 'circle-color': ['step', ['get', 'point_count'], '#51bbd6', 100, '#f1f075', 750, '#f28cb1'], 10 | 'circle-radius': ['step', ['get', 'point_count'], 20, 100, 30, 750, 40] 11 | } 12 | }; 13 | 14 | export const clusterCountLayer: LayerProps = { 15 | id: 'cluster-count', 16 | type: 'symbol', 17 | source: 'earthquakes', 18 | filter: ['has', 'point_count'], 19 | layout: { 20 | 'text-field': '{point_count_abbreviated}', 21 | 'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'], 22 | 'text-size': 12 23 | } 24 | }; 25 | 26 | export const unclusteredPointLayer: LayerProps = { 27 | id: 'unclustered-point', 28 | type: 'circle', 29 | source: 'earthquakes', 30 | filter: ['!', ['has', 'point_count']], 31 | paint: { 32 | 'circle-color': '#11b4da', 33 | 'circle-radius': 4, 34 | 'circle-stroke-width': 1, 35 | 'circle-stroke-color': '#fff' 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /examples/mapbox/clusters/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/clusters/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/controls/README.md: -------------------------------------------------------------------------------- 1 | # Example: Controls 2 | 3 | Demonstrates how various control components can be used with react-map-gl. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/controls/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 32 | 33 | 34 |
35 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /examples/mapbox/controls/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "mapbox-gl": "^3.5.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mapbox/controls/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Marker, Popup, NavigationControl and FullscreenControl

7 |

8 | Map showing top 20 most populated cities of the United States. Click on a marker to learn 9 | more. 10 |

11 |

12 | Data source:{' '} 13 | 14 | Wikipedia 15 | 16 |

17 | 25 |
26 | ); 27 | } 28 | 29 | export default React.memo(ControlPanel); 30 | -------------------------------------------------------------------------------- /examples/mapbox/controls/src/pin.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | const ICON = `M20.2,15.7L20.2,15.7c1.1-1.6,1.8-3.6,1.8-5.7c0-5.6-4.5-10-10-10S2,4.5,2,10c0,2,0.6,3.9,1.6,5.4c0,0.1,0.1,0.2,0.2,0.3 4 | c0,0,0.1,0.1,0.1,0.2c0.2,0.3,0.4,0.6,0.7,0.9c2.6,3.1,7.4,7.6,7.4,7.6s4.8-4.5,7.4-7.5c0.2-0.3,0.5-0.6,0.7-0.9 5 | C20.1,15.8,20.2,15.8,20.2,15.7z`; 6 | 7 | const pinStyle = { 8 | cursor: 'pointer', 9 | fill: '#d00', 10 | stroke: 'none' 11 | }; 12 | 13 | function Pin({size = 20}) { 14 | return ( 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | export default React.memo(Pin); 22 | -------------------------------------------------------------------------------- /examples/mapbox/controls/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/controls/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/custom-cursor/README.md: -------------------------------------------------------------------------------- 1 | # Example: Custom Cursor 2 | 3 | This example showcases how to dynamically change the cursor over the map based on interactivity. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/custom-cursor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "mapbox-gl": "^3.5.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mapbox/custom-cursor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/custom-cursor/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/custom-overlay/README.md: -------------------------------------------------------------------------------- 1 | # Example: SVG overlay 2 | 3 | This app shows how to implement a custom control that draws arbitrary React content that responds to camera updates. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/custom-overlay/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "d3-shape": "^3.1.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0", 12 | "mapbox-gl": "^3.5.0" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.0.0", 16 | "vite": "^4.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/mapbox/custom-overlay/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/custom-overlay/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/deckgl-overlay/README.md: -------------------------------------------------------------------------------- 1 | # Example: DeckGL Overlay 2 | 3 | This example demonstrates using [deck.gl](https://deck.gl) to render a data overlay on top of react-map-gl. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/deckgl-overlay/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 18 | 19 | 20 |
21 | 22 | 26 | 27 | -------------------------------------------------------------------------------- /examples/mapbox/deckgl-overlay/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "deck.gl": "^8.8.0-beta.2", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0", 12 | "mapbox-gl": "^3.5.0" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.0.0", 16 | "vite": "^4.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/mapbox/deckgl-overlay/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/deckgl-overlay/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/draggable-markers/README.md: -------------------------------------------------------------------------------- 1 | # Example: Draggable Marker 2 | 3 | Demonstrates how Marker component can be dragged with react-map-gl. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/draggable-markers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 33 | 34 | 35 |
36 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /examples/mapbox/draggable-markers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "mapbox-gl": "^3.5.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mapbox/draggable-markers/src/pin.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | const ICON = `M20.2,15.7L20.2,15.7c1.1-1.6,1.8-3.6,1.8-5.7c0-5.6-4.5-10-10-10S2,4.5,2,10c0,2,0.6,3.9,1.6,5.4c0,0.1,0.1,0.2,0.2,0.3 4 | c0,0,0.1,0.1,0.1,0.2c0.2,0.3,0.4,0.6,0.7,0.9c2.6,3.1,7.4,7.6,7.4,7.6s4.8-4.5,7.4-7.5c0.2-0.3,0.5-0.6,0.7-0.9 5 | C20.1,15.8,20.2,15.8,20.2,15.7z`; 6 | 7 | const pinStyle = { 8 | fill: '#d00', 9 | stroke: 'none' 10 | }; 11 | 12 | function Pin(props) { 13 | const {size = 20} = props; 14 | 15 | return ( 16 | 17 | 18 | 19 | ); 20 | } 21 | 22 | export default React.memo(Pin); 23 | -------------------------------------------------------------------------------- /examples/mapbox/draggable-markers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/draggable-markers/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/draw-polygon/README.md: -------------------------------------------------------------------------------- 1 | # Example: Draw Polygon 2 | 3 | This app reproduces Mapbox's [Draw a polygon and calculate its area](https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-draw/) example. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/draw-polygon/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "@mapbox/mapbox-gl-draw": "^1.3.0", 9 | "@types/mapbox__mapbox-gl-draw": "^1.2.3", 10 | "@turf/area": "^6.5.0", 11 | "react": "^18.0.0", 12 | "react-dom": "^18.0.0", 13 | "react-map-gl": "^8.0.0", 14 | "mapbox-gl": "^3.5.0" 15 | }, 16 | "devDependencies": { 17 | "typescript": "^5.0.0", 18 | "vite": "^4.0.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/mapbox/draw-polygon/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import area from '@turf/area'; 3 | 4 | function ControlPanel(props) { 5 | let polygonArea = 0; 6 | for (const polygon of props.polygons) { 7 | polygonArea += area(polygon); 8 | } 9 | 10 | return ( 11 |
12 |

Draw Polygon

13 | {polygonArea > 0 && ( 14 |

15 | {Math.round(polygonArea * 100) / 100}
16 | square meters 17 |

18 | )} 19 | 27 |
28 | ); 29 | } 30 | 31 | export default React.memo(ControlPanel); 32 | -------------------------------------------------------------------------------- /examples/mapbox/draw-polygon/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/draw-polygon/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/filter/README.md: -------------------------------------------------------------------------------- 1 | # Example: Highlight By Filter 2 | 3 | This app reproduces Mapbox's [Highlight features containing similar data](https://www.mapbox.com/mapbox-gl-js/example/query-similar-features/) example. 4 | 5 | This example showcases how to dynamically add/remove filters from layers. 6 | 7 | ## Usage 8 | 9 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 10 | 11 | ```bash 12 | npm i 13 | npm run start 14 | ``` 15 | 16 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 17 | - Run `npm install maplibre-gl` 18 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 19 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 20 | -------------------------------------------------------------------------------- /examples/mapbox/filter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "mapbox-gl": "^3.5.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mapbox/filter/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Highlight Features Containing Similar Data

7 |

Hover over counties to highlight counties that share the same name.

8 | 16 |
17 | ); 18 | } 19 | 20 | export default React.memo(ControlPanel); 21 | -------------------------------------------------------------------------------- /examples/mapbox/filter/src/map-style.ts: -------------------------------------------------------------------------------- 1 | import type {FillLayerSpecification} from 'react-map-gl/mapbox'; 2 | 3 | export const countiesLayer: FillLayerSpecification = { 4 | id: 'counties', 5 | source: '', 6 | type: 'fill', 7 | 'source-layer': 'original', 8 | paint: { 9 | 'fill-outline-color': 'rgba(0,0,0,0.1)', 10 | 'fill-color': 'rgba(0,0,0,0.1)' 11 | } 12 | }; 13 | // Highlighted county polygons 14 | export const highlightLayer: FillLayerSpecification = { 15 | id: 'counties-highlighted', 16 | type: 'fill', 17 | source: 'counties', 18 | 'source-layer': 'original', 19 | paint: { 20 | 'fill-outline-color': '#484896', 21 | 'fill-color': '#6e599f', 22 | 'fill-opacity': 0.75 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /examples/mapbox/filter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/filter/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/geocoder/README.md: -------------------------------------------------------------------------------- 1 | # Example: Geocoder 2 | 3 | This app reproduces Mapbox's [Add a geocoder](https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-geocoder/) example. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/geocoder/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "@mapbox/mapbox-gl-geocoder": "^4.7.4", 9 | "@types/mapbox__mapbox-gl-geocoder": "^4.7.2", 10 | "react": "^18.0.0", 11 | "react-dom": "^18.0.0", 12 | "react-map-gl": "^8.0.0", 13 | "mapbox-gl": "^3.5.0" 14 | }, 15 | "devDependencies": { 16 | "typescript": "^5.0.0", 17 | "vite": "^4.0.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/mapbox/geocoder/src/app.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {createRoot} from 'react-dom/client'; 3 | import Map from 'react-map-gl/mapbox'; 4 | 5 | import GeocoderControl from './geocoder-control'; 6 | import ControlPanel from './control-panel'; 7 | 8 | // eslint-disable-next-line 9 | const TOKEN = process.env.MapboxAccessToken; // Set your mapbox token here 10 | 11 | export default function App() { 12 | return ( 13 | <> 14 | 23 | 24 | 25 | 26 | 27 | ); 28 | } 29 | 30 | export function renderToDom(container) { 31 | createRoot(container).render(); 32 | } 33 | -------------------------------------------------------------------------------- /examples/mapbox/geocoder/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Geocoder

7 | 15 |
16 | ); 17 | } 18 | 19 | export default React.memo(ControlPanel); 20 | -------------------------------------------------------------------------------- /examples/mapbox/geocoder/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/geocoder/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/geojson-animation/README.md: -------------------------------------------------------------------------------- 1 | # Example: Animated GeoJSON 2 | 3 | This app reproduces Mapbox's [Animate point along line](https://www.mapbox.com/mapbox-gl-js/example/animate-point-along-line/) example. 4 | 5 | This example showcases how to dynamically add and update custom data sources. 6 | 7 | ## Usage 8 | 9 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 10 | 11 | ```bash 12 | npm i 13 | npm run start 14 | ``` 15 | 16 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 17 | - Run `npm install maplibre-gl` 18 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 19 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 20 | -------------------------------------------------------------------------------- /examples/mapbox/geojson-animation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 32 | 33 | 34 |
35 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /examples/mapbox/geojson-animation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "mapbox-gl": "^3.5.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mapbox/geojson-animation/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Animated GeoJSON

7 |

Render animation by updating GeoJSON data source.

8 | 16 |
17 | ); 18 | } 19 | 20 | export default React.memo(ControlPanel); 21 | -------------------------------------------------------------------------------- /examples/mapbox/geojson-animation/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/geojson-animation/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/geojson/README.md: -------------------------------------------------------------------------------- 1 | # Example: GeoJSON 2 | 3 | This example showcases how to dynamically add and update custom data sources. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/geojson/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "d3-array": "^3.1.1", 9 | "d3-scale": "^4.0.2", 10 | "mapbox-gl": "^3.5.0", 11 | "react": "^18.0.0", 12 | "react-dom": "^18.0.0", 13 | "react-map-gl": "^8.0.0" 14 | }, 15 | "devDependencies": { 16 | "typescript": "^5.0.0", 17 | "vite": "^4.0.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/mapbox/geojson/src/map-style.ts: -------------------------------------------------------------------------------- 1 | import type {LayerProps} from 'react-map-gl/mapbox'; 2 | 3 | // For more information on data-driven styles, see https://www.mapbox.com/help/gl-dds-ref/ 4 | export const dataLayer: LayerProps = { 5 | id: 'data', 6 | type: 'fill', 7 | paint: { 8 | 'fill-color': { 9 | type: 'interval', 10 | property: 'percentile', 11 | stops: [ 12 | [0, '#3288bd'], 13 | [1, '#66c2a5'], 14 | [2, '#abdda4'], 15 | [3, '#e6f598'], 16 | [4, '#ffffbf'], 17 | [5, '#fee08b'], 18 | [6, '#fdae61'], 19 | [7, '#f46d43'], 20 | [8, '#d53e4f'] 21 | ] 22 | }, 23 | 'fill-opacity': 0.8 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /examples/mapbox/geojson/src/utils.ts: -------------------------------------------------------------------------------- 1 | import {range} from 'd3-array'; 2 | import {scaleQuantile} from 'd3-scale'; 3 | 4 | import type GeoJSON from 'geojson'; 5 | 6 | export function updatePercentiles( 7 | featureCollection: GeoJSON.FeatureCollection, 8 | accessor: (f: GeoJSON.Feature) => number 9 | ): GeoJSON.FeatureCollection { 10 | const {features} = featureCollection; 11 | const scale = scaleQuantile().domain(features.map(accessor)).range(range(9)); 12 | return { 13 | type: 'FeatureCollection', 14 | features: features.map(f => { 15 | const value = accessor(f); 16 | const properties = { 17 | ...f.properties, 18 | value, 19 | percentile: scale(value) 20 | }; 21 | return {...f, properties}; 22 | }) 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /examples/mapbox/geojson/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/geojson/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/heatmap/README.md: -------------------------------------------------------------------------------- 1 | # Example: Heatmap layer 2 | 3 | This app reproduces Mapbox's [Create a heatmap layer](https://docs.mapbox.com/mapbox-gl-js/example/heatmap-layer/) example. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/heatmap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "mapbox-gl": "^3.5.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mapbox/heatmap/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/heatmap/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/interaction/README.md: -------------------------------------------------------------------------------- 1 | # Example: Interaction 2 | 3 | This example showcases how to toggle/limit user interaction. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/interaction/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "mapbox-gl": "^3.5.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mapbox/interaction/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/interaction/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/layers/README.md: -------------------------------------------------------------------------------- 1 | # Example: Layers 2 | 3 | This example showcases how to dynamically change layer styles and show/hide layers. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/layers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "immutable": "^4.0.0", 9 | "mapbox-gl": "^3.5.0", 10 | "react": "^18.0.0", 11 | "react-dom": "^18.0.0", 12 | "react-map-gl": "^8.0.0" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.0.0", 16 | "vite": "^4.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/mapbox/layers/src/app.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useState} from 'react'; 3 | import {createRoot} from 'react-dom/client'; 4 | import Map from 'react-map-gl/mapbox'; 5 | import ControlPanel from './control-panel'; 6 | 7 | const MAPBOX_TOKEN = ''; // Set your mapbox token here 8 | 9 | export default function App() { 10 | const [mapStyle, setMapStyle] = useState(null); 11 | 12 | return ( 13 | <> 14 | 24 | 25 | 26 | 27 | ); 28 | } 29 | 30 | export function renderToDom(container) { 31 | createRoot(container).render(); 32 | } 33 | -------------------------------------------------------------------------------- /examples/mapbox/layers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/layers/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/side-by-side/README.md: -------------------------------------------------------------------------------- 1 | # Example: Side By Side 2 | 3 | Demonstrates how to synchronize two maps with react-map-gl. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/side-by-side/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 33 | 34 | 35 |
36 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /examples/mapbox/side-by-side/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "mapbox-gl": "^3.5.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mapbox/side-by-side/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/side-by-side/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/terrain/README.md: -------------------------------------------------------------------------------- 1 | # Example: 3D Terrain 2 | 3 | Demonstrates how to add 3D terrain with react-map-gl. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/terrain/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 33 | 34 | 35 |
36 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /examples/mapbox/terrain/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "mapbox-gl": "^3.5.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mapbox/terrain/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

3D Terrain

7 |

Add 3D terrain and sky to a map.

8 | 9 | 17 |
18 | ); 19 | } 20 | 21 | export default React.memo(ControlPanel); 22 | -------------------------------------------------------------------------------- /examples/mapbox/terrain/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/terrain/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/viewport-animation/README.md: -------------------------------------------------------------------------------- 1 | # Example: Viewport Animation 2 | 3 | This example showcases how to transition smoothly between one viewport to another. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/viewport-animation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 32 | 33 | 34 |
35 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /examples/mapbox/viewport-animation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "mapbox-gl": "^3.5.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/mapbox/viewport-animation/src/app.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useRef, useCallback} from 'react'; 3 | import {createRoot} from 'react-dom/client'; 4 | import Map, {MapRef} from 'react-map-gl/mapbox'; 5 | 6 | import ControlPanel from './control-panel'; 7 | 8 | const MAPBOX_TOKEN = ''; // Set your mapbox token here 9 | 10 | const initialViewState = { 11 | latitude: 37.7751, 12 | longitude: -122.4193, 13 | zoom: 11, 14 | bearing: 0, 15 | pitch: 0 16 | }; 17 | 18 | export default function App() { 19 | const mapRef = useRef(); 20 | 21 | const onSelectCity = useCallback(({longitude, latitude}) => { 22 | mapRef.current?.flyTo({center: [longitude, latitude], duration: 2000}); 23 | }, []); 24 | 25 | return ( 26 | <> 27 | 33 | 34 | 35 | ); 36 | } 37 | 38 | export function renderToDom(container) { 39 | createRoot(container).render(); 40 | } 41 | -------------------------------------------------------------------------------- /examples/mapbox/viewport-animation/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import CITIES from '../../../.data/cities.json'; 4 | 5 | function ControlPanel(props) { 6 | return ( 7 |
8 |

Camera Transition

9 |

Smooth animate of the viewport.

10 | 18 |
19 | 20 | {CITIES.filter(city => city.state === 'California').map((city, index) => ( 21 |
22 | props.onSelectCity(city)} 28 | /> 29 | 30 |
31 | ))} 32 |
33 | ); 34 | } 35 | 36 | export default React.memo(ControlPanel); 37 | -------------------------------------------------------------------------------- /examples/mapbox/viewport-animation/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/viewport-animation/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/mapbox/zoom-to-bounds/README.md: -------------------------------------------------------------------------------- 1 | # Example: Zoom To Bounds 2 | 3 | Demonstrates how to zoom to a bounding box with react-map-gl. 4 | 5 | ## Usage 6 | 7 | To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | 14 | Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: 15 | - Run `npm install maplibre-gl` 16 | - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` 17 | - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL 18 | -------------------------------------------------------------------------------- /examples/mapbox/zoom-to-bounds/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 33 | 34 | 35 |
36 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /examples/mapbox/zoom-to-bounds/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "@turf/bbox": "^6.5.0", 9 | "mapbox-gl": "^3.5.0", 10 | "react": "^18.0.0", 11 | "react-dom": "^18.0.0", 12 | "react-map-gl": "^8.0.0" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.0.0", 16 | "vite": "^4.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/mapbox/zoom-to-bounds/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Zoom to Bounding Box

7 |

Click on a San Fransisco Neighborhood to zoom in.

8 | 16 |
17 | ); 18 | } 19 | 20 | export default React.memo(ControlPanel); 21 | -------------------------------------------------------------------------------- /examples/mapbox/zoom-to-bounds/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/mapbox/zoom-to-bounds/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/maplibre/clusters/README.md: -------------------------------------------------------------------------------- 1 | # Example: Supercluster 2 | 3 | This app reproduces Maplibre's [Create and style clusters](https://maplibre.org/maplibre-gl-js/docs/examples/cluster/) example. 4 | 5 | This example showcases how to visualize points as clusters. 6 | 7 | ## Usage 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | -------------------------------------------------------------------------------- /examples/maplibre/clusters/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 32 | 33 | 34 |
35 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /examples/maplibre/clusters/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "maplibre-gl": "^5.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/clusters/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Create and Style Clusters

7 |

Use Maplibre GL JS' built-in functions to visualize points as clusters.

8 | 16 |
17 | ); 18 | } 19 | 20 | export default React.memo(ControlPanel); 21 | -------------------------------------------------------------------------------- /examples/maplibre/clusters/src/layers.ts: -------------------------------------------------------------------------------- 1 | import type {LayerProps} from 'react-map-gl/maplibre'; 2 | 3 | export const clusterLayer: LayerProps = { 4 | id: 'clusters', 5 | type: 'circle', 6 | source: 'earthquakes', 7 | filter: ['has', 'point_count'], 8 | paint: { 9 | 'circle-color': ['step', ['get', 'point_count'], '#51bbd6', 100, '#f1f075', 750, '#f28cb1'], 10 | 'circle-radius': ['step', ['get', 'point_count'], 20, 100, 30, 750, 40] 11 | } 12 | }; 13 | 14 | export const clusterCountLayer: LayerProps = { 15 | id: 'cluster-count', 16 | type: 'symbol', 17 | source: 'earthquakes', 18 | filter: ['has', 'point_count'], 19 | layout: { 20 | 'text-field': '{point_count_abbreviated}', 21 | 'text-size': 12 22 | } 23 | }; 24 | 25 | export const unclusteredPointLayer: LayerProps = { 26 | id: 'unclustered-point', 27 | type: 'circle', 28 | source: 'earthquakes', 29 | filter: ['!', ['has', 'point_count']], 30 | paint: { 31 | 'circle-color': '#11b4da', 32 | 'circle-radius': 4, 33 | 'circle-stroke-width': 1, 34 | 'circle-stroke-color': '#fff' 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /examples/maplibre/clusters/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/controls/README.md: -------------------------------------------------------------------------------- 1 | # Example: Controls 2 | 3 | Demonstrates how various control components can be used with react-maplibre. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/controls/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 32 | 33 | 34 |
35 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /examples/maplibre/controls/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "maplibre-gl": "^5.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/controls/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Marker, Popup, NavigationControl and FullscreenControl

7 |

8 | Map showing top 20 most populated cities of the United States. Click on a marker to learn 9 | more. 10 |

11 |

12 | Data source:{' '} 13 | 14 | Wikipedia 15 | 16 |

17 | 25 |
26 | ); 27 | } 28 | 29 | export default React.memo(ControlPanel); 30 | -------------------------------------------------------------------------------- /examples/maplibre/controls/src/pin.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | const ICON = `M20.2,15.7L20.2,15.7c1.1-1.6,1.8-3.6,1.8-5.7c0-5.6-4.5-10-10-10S2,4.5,2,10c0,2,0.6,3.9,1.6,5.4c0,0.1,0.1,0.2,0.2,0.3 4 | c0,0,0.1,0.1,0.1,0.2c0.2,0.3,0.4,0.6,0.7,0.9c2.6,3.1,7.4,7.6,7.4,7.6s4.8-4.5,7.4-7.5c0.2-0.3,0.5-0.6,0.7-0.9 5 | C20.1,15.8,20.2,15.8,20.2,15.7z`; 6 | 7 | const pinStyle = { 8 | cursor: 'pointer', 9 | fill: '#d00', 10 | stroke: 'none' 11 | }; 12 | 13 | function Pin({size = 20}) { 14 | return ( 15 | 16 | 17 | 18 | ); 19 | } 20 | 21 | export default React.memo(Pin); 22 | -------------------------------------------------------------------------------- /examples/maplibre/controls/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/custom-cursor/README.md: -------------------------------------------------------------------------------- 1 | # Example: Custom Cursor 2 | 3 | This example showcases how to dynamically change the cursor over the map based on interactivity. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/custom-cursor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "maplibre-gl": "^5.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/custom-cursor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/custom-overlay/README.md: -------------------------------------------------------------------------------- 1 | # Example: SVG overlay 2 | 3 | This app shows how to implement a custom control that draws arbitrary React content that responds to camera updates. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/custom-overlay/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "d3-shape": "^3.1.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0", 12 | "maplibre-gl": "^5.0.0" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.0.0", 16 | "vite": "^4.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/maplibre/custom-overlay/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/deckgl-overlay/README.md: -------------------------------------------------------------------------------- 1 | # Example: DeckGL Overlay 2 | 3 | This example demonstrates using [deck.gl](https://deck.gl) to render a data overlay on top of react-maplibre. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/deckgl-overlay/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 18 | 19 | 20 |
21 | 22 | 26 | 27 | -------------------------------------------------------------------------------- /examples/maplibre/deckgl-overlay/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "deck.gl": "^9.0.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0", 12 | "maplibre-gl": "^5.0.0" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.0.0", 16 | "vite": "^4.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/maplibre/deckgl-overlay/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/draggable-markers/README.md: -------------------------------------------------------------------------------- 1 | # Example: Draggable Marker 2 | 3 | Demonstrates how Marker component can be dragged with react-maplibre. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/draggable-markers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 33 | 34 | 35 |
36 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /examples/maplibre/draggable-markers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "maplibre-gl": "^5.0.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/draggable-markers/src/pin.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | const ICON = `M20.2,15.7L20.2,15.7c1.1-1.6,1.8-3.6,1.8-5.7c0-5.6-4.5-10-10-10S2,4.5,2,10c0,2,0.6,3.9,1.6,5.4c0,0.1,0.1,0.2,0.2,0.3 4 | c0,0,0.1,0.1,0.1,0.2c0.2,0.3,0.4,0.6,0.7,0.9c2.6,3.1,7.4,7.6,7.4,7.6s4.8-4.5,7.4-7.5c0.2-0.3,0.5-0.6,0.7-0.9 5 | C20.1,15.8,20.2,15.8,20.2,15.7z`; 6 | 7 | const pinStyle = { 8 | fill: '#d00', 9 | stroke: 'none' 10 | }; 11 | 12 | function Pin(props) { 13 | const {size = 20} = props; 14 | 15 | return ( 16 | 17 | 18 | 19 | ); 20 | } 21 | 22 | export default React.memo(Pin); 23 | -------------------------------------------------------------------------------- /examples/maplibre/draggable-markers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/draw-polygon/README.md: -------------------------------------------------------------------------------- 1 | # Example: Draw Polygon 2 | 3 | This app reproduces Mapbox's [Draw a polygon and calculate its area](https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-draw/) example. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/draw-polygon/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 32 | 33 | 34 |
35 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /examples/maplibre/draw-polygon/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "@mapbox/mapbox-gl-draw": "^1.3.0", 9 | "@types/mapbox__mapbox-gl-draw": "^1.2.3", 10 | "@turf/area": "^6.5.0", 11 | "react": "^18.0.0", 12 | "react-dom": "^18.0.0", 13 | "react-map-gl": "^8.0.0", 14 | "maplibre-gl": "^5.0.0" 15 | }, 16 | "devDependencies": { 17 | "typescript": "^5.0.0", 18 | "vite": "^4.0.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/maplibre/draw-polygon/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import area from '@turf/area'; 3 | 4 | function ControlPanel(props) { 5 | let polygonArea = 0; 6 | for (const polygon of props.polygons) { 7 | polygonArea += area(polygon); 8 | } 9 | 10 | return ( 11 |
12 |

Draw Polygon

13 | {polygonArea > 0 && ( 14 |

15 | {Math.round(polygonArea * 100) / 100}
16 | square meters 17 |

18 | )} 19 | 27 |
28 | ); 29 | } 30 | 31 | export default React.memo(ControlPanel); 32 | -------------------------------------------------------------------------------- /examples/maplibre/draw-polygon/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/filter/README.md: -------------------------------------------------------------------------------- 1 | # Example: Highlight By Filter 2 | 3 | This app reproduces Mapbox's [Highlight features containing similar data](https://www.mapbox.com/mapbox-gl-js/example/query-similar-features/) example. 4 | 5 | This example showcases how to dynamically add/remove filters from layers. 6 | 7 | ## Usage 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | -------------------------------------------------------------------------------- /examples/maplibre/filter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "maplibre-gl": "^5.0.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/filter/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Highlight Features Containing Similar Data

7 |

Hover over counties to highlight counties that share the same name.

8 | 16 |
17 | ); 18 | } 19 | 20 | export default React.memo(ControlPanel); 21 | -------------------------------------------------------------------------------- /examples/maplibre/filter/src/map-style.ts: -------------------------------------------------------------------------------- 1 | import type {FillLayerSpecification} from 'react-map-gl/maplibre'; 2 | 3 | export const countiesLayer: FillLayerSpecification = { 4 | id: 'counties', 5 | source: '', 6 | type: 'fill', 7 | paint: { 8 | 'fill-outline-color': 'rgba(0,0,0,0.1)', 9 | 'fill-color': 'rgba(0,0,0,0.1)' 10 | } 11 | }; 12 | // Highlighted county polygons 13 | export const highlightLayer: FillLayerSpecification = { 14 | id: 'counties-highlighted', 15 | type: 'fill', 16 | source: 'counties', 17 | paint: { 18 | 'fill-outline-color': '#484896', 19 | 'fill-color': '#6e599f', 20 | 'fill-opacity': 0.75 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /examples/maplibre/filter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/geocoder/README.md: -------------------------------------------------------------------------------- 1 | # Example: Geocoder 2 | 3 | This app reproduces Maplibre's [Geocode with Nominatim](https://maplibre.org/maplibre-gl-js/docs/examples/geocoder/) example. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/geocoder/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 32 | 33 | 34 |
35 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /examples/maplibre/geocoder/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "@maplibre/maplibre-gl-geocoder": "^1.5.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0", 12 | "maplibre-gl": "^5.0.0" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.0.0", 16 | "vite": "^4.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/maplibre/geocoder/src/app.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {createRoot} from 'react-dom/client'; 3 | import {Map} from 'react-map-gl/maplibre'; 4 | 5 | import GeocoderControl from './geocoder-control'; 6 | import ControlPanel from './control-panel'; 7 | 8 | import '@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css'; 9 | 10 | export default function App() { 11 | return ( 12 | <> 13 | 21 | 22 | 23 | 24 | 25 | ); 26 | } 27 | 28 | export function renderToDom(container) { 29 | createRoot(container).render(); 30 | } 31 | -------------------------------------------------------------------------------- /examples/maplibre/geocoder/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Geocoder

7 | 15 |
16 | ); 17 | } 18 | 19 | export default React.memo(ControlPanel); 20 | -------------------------------------------------------------------------------- /examples/maplibre/geocoder/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/geojson-animation/README.md: -------------------------------------------------------------------------------- 1 | # Example: Animated GeoJSON 2 | 3 | This app reproduces Maplibre's [Animate point along line](https://maplibre.org/maplibre-gl-js/docs/examples/animate-point-along-line/) example. 4 | 5 | This example showcases how to dynamically add and update custom data sources. 6 | 7 | ## Usage 8 | 9 | ```bash 10 | npm i 11 | npm run start 12 | ``` 13 | -------------------------------------------------------------------------------- /examples/maplibre/geojson-animation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 32 | 33 | 34 |
35 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /examples/maplibre/geojson-animation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "maplibre-gl": "^5.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/geojson-animation/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Animated GeoJSON

7 |

Render animation by updating GeoJSON data source.

8 | 16 |
17 | ); 18 | } 19 | 20 | export default React.memo(ControlPanel); 21 | -------------------------------------------------------------------------------- /examples/maplibre/geojson-animation/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/geojson/README.md: -------------------------------------------------------------------------------- 1 | # Example: GeoJSON 2 | 3 | This example showcases how to dynamically add and update custom data sources. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/geojson/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "d3-array": "^3.1.1", 9 | "d3-scale": "^4.0.2", 10 | "maplibre-gl": "^5.0.0", 11 | "react": "^18.0.0", 12 | "react-dom": "^18.0.0", 13 | "react-map-gl": "^8.0.0" 14 | }, 15 | "devDependencies": { 16 | "typescript": "^5.0.0", 17 | "vite": "^4.0.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/maplibre/geojson/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel(props) { 4 | const {year} = props; 5 | 6 | return ( 7 |
8 |

Interactive GeoJSON

9 |

10 | Map showing median household income by state in year {year}. Hover over a state to 11 | see details. 12 |

13 |

14 | Data source: US Census Bureau 15 |

16 | 24 |
25 | 26 |
27 | 28 | props.onChange(evt.target.value)} 35 | /> 36 |
37 |
38 | ); 39 | } 40 | 41 | export default React.memo(ControlPanel); 42 | -------------------------------------------------------------------------------- /examples/maplibre/geojson/src/map-style.ts: -------------------------------------------------------------------------------- 1 | import type {LayerProps} from 'react-map-gl/maplibre'; 2 | 3 | // For more information on data-driven styles, see https://maplibre.org/maplibre-style-spec/expressions/ 4 | export const dataLayer: LayerProps = { 5 | id: 'data', 6 | type: 'fill', 7 | paint: { 8 | 'fill-color': { 9 | type: 'interval', 10 | property: 'percentile', 11 | stops: [ 12 | [0, '#3288bd'], 13 | [1, '#66c2a5'], 14 | [2, '#abdda4'], 15 | [3, '#e6f598'], 16 | [4, '#ffffbf'], 17 | [5, '#fee08b'], 18 | [6, '#fdae61'], 19 | [7, '#f46d43'], 20 | [8, '#d53e4f'] 21 | ] 22 | }, 23 | 'fill-opacity': 0.8 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /examples/maplibre/geojson/src/utils.ts: -------------------------------------------------------------------------------- 1 | import {range} from 'd3-array'; 2 | import {scaleQuantile} from 'd3-scale'; 3 | 4 | import type GeoJSON from 'geojson'; 5 | 6 | export function updatePercentiles( 7 | featureCollection: GeoJSON.FeatureCollection, 8 | accessor: (f: GeoJSON.Feature) => number 9 | ): GeoJSON.FeatureCollection { 10 | const {features} = featureCollection; 11 | const scale = scaleQuantile().domain(features.map(accessor)).range(range(9)); 12 | return { 13 | type: 'FeatureCollection', 14 | features: features.map(f => { 15 | const value = accessor(f); 16 | const properties = { 17 | ...f.properties, 18 | value, 19 | percentile: scale(value) 20 | }; 21 | return {...f, properties}; 22 | }) 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /examples/maplibre/geojson/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/globe/README.md: -------------------------------------------------------------------------------- 1 | # Example: Globe 2 | 3 | This app reproduces Maplibre's [globe](https://maplibre.org/maplibre-gl-js/docs/examples/globe/) example. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/globe/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 33 | 34 | 35 |
36 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /examples/maplibre/globe/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "maplibre-gl": "^5.0.0-pre.1", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/globe/src/app.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {createRoot} from 'react-dom/client'; 3 | import {Map} from 'react-map-gl/maplibre'; 4 | 5 | import ControlPanel from './control-panel'; 6 | 7 | export default function App() { 8 | return ( 9 | <> 10 | 20 | 21 | 22 | ); 23 | } 24 | 25 | export function renderToDom(container) { 26 | createRoot(container).render(); 27 | } 28 | -------------------------------------------------------------------------------- /examples/maplibre/globe/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Globe

7 |

Use globe projection.

8 | 9 | 17 |
18 | ); 19 | } 20 | 21 | export default React.memo(ControlPanel); 22 | -------------------------------------------------------------------------------- /examples/maplibre/globe/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/heatmap/README.md: -------------------------------------------------------------------------------- 1 | # Example: Heatmap layer 2 | 3 | This app reproduces Maplibre's [Create a heatmap layer](https://maplibre.org/maplibre-gl-js/docs/examples/heatmap-layer/) example. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/heatmap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "maplibre-gl": "^5.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/heatmap/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/interaction/README.md: -------------------------------------------------------------------------------- 1 | # Example: Interaction 2 | 3 | This example showcases how to toggle/limit user interaction. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/interaction/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "maplibre-gl": "^5.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/interaction/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/layers/README.md: -------------------------------------------------------------------------------- 1 | # Example: Layers 2 | 3 | This example showcases how to dynamically change layer styles and show/hide layers. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/layers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "immutable": "^4.0.0", 9 | "maplibre-gl": "^5.0.0", 10 | "react": "^18.0.0", 11 | "react-dom": "^18.0.0", 12 | "react-map-gl": "^8.0.0" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.0.0", 16 | "vite": "^4.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/maplibre/layers/src/app.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useState} from 'react'; 3 | import {createRoot} from 'react-dom/client'; 4 | import {Map} from 'react-map-gl/maplibre'; 5 | import ControlPanel from './control-panel'; 6 | 7 | export default function App() { 8 | const [mapStyle, setMapStyle] = useState(null); 9 | 10 | return ( 11 | <> 12 | 21 | 22 | 23 | 24 | ); 25 | } 26 | 27 | export function renderToDom(container) { 28 | createRoot(container).render(); 29 | } 30 | -------------------------------------------------------------------------------- /examples/maplibre/layers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/side-by-side/README.md: -------------------------------------------------------------------------------- 1 | # Example: Side By Side 2 | 3 | Demonstrates how to synchronize two maps with react-maplibre. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/side-by-side/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 33 | 34 | 35 |
36 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /examples/maplibre/side-by-side/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "maplibre-gl": "^5.0.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/side-by-side/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/terrain/README.md: -------------------------------------------------------------------------------- 1 | # Example: 3D Terrain 2 | 3 | This app reproduces Maplibre's [3D terrain](https://maplibre.org/maplibre-gl-js/docs/examples/3d-terrain/) example. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/terrain/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 33 | 34 | 35 |
36 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /examples/maplibre/terrain/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "maplibre-gl": "^5.0.0", 9 | "react": "^18.0.0", 10 | "react-dom": "^18.0.0", 11 | "react-map-gl": "^8.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/terrain/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

3D Terrain

7 |

Add 3D terrain and sky to a map.

8 | 9 | 17 |
18 | ); 19 | } 20 | 21 | export default React.memo(ControlPanel); 22 | -------------------------------------------------------------------------------- /examples/maplibre/terrain/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/viewport-animation/README.md: -------------------------------------------------------------------------------- 1 | # Example: Viewport Animation 2 | 3 | This example showcases how to transition smoothly between one viewport to another. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/viewport-animation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 32 | 33 | 34 |
35 | 36 | 40 | 41 | -------------------------------------------------------------------------------- /examples/maplibre/viewport-animation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "react": "^18.0.0", 9 | "react-dom": "^18.0.0", 10 | "react-map-gl": "^8.0.0", 11 | "maplibre-gl": "^5.0.0" 12 | }, 13 | "devDependencies": { 14 | "typescript": "^5.0.0", 15 | "vite": "^4.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/maplibre/viewport-animation/src/app.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useRef, useCallback} from 'react'; 3 | import {createRoot} from 'react-dom/client'; 4 | import {Map, MapRef} from 'react-map-gl/maplibre'; 5 | 6 | import ControlPanel from './control-panel'; 7 | 8 | const initialViewState = { 9 | latitude: 37.7751, 10 | longitude: -122.4193, 11 | zoom: 11, 12 | bearing: 0, 13 | pitch: 0 14 | }; 15 | 16 | export default function App() { 17 | const mapRef = useRef(); 18 | 19 | const onSelectCity = useCallback(({longitude, latitude}) => { 20 | mapRef.current?.flyTo({center: [longitude, latitude], duration: 2000}); 21 | }, []); 22 | 23 | return ( 24 | <> 25 | 30 | 31 | 32 | ); 33 | } 34 | 35 | export function renderToDom(container) { 36 | createRoot(container).render(); 37 | } 38 | -------------------------------------------------------------------------------- /examples/maplibre/viewport-animation/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import CITIES from '../../../.data/cities.json'; 4 | 5 | function ControlPanel(props) { 6 | return ( 7 |
8 |

Camera Transition

9 |

Smooth animate of the viewport.

10 | 18 |
19 | 20 | {CITIES.filter(city => city.state === 'California').map((city, index) => ( 21 |
22 | props.onSelectCity(city)} 28 | /> 29 | 30 |
31 | ))} 32 |
33 | ); 34 | } 35 | 36 | export default React.memo(ControlPanel); 37 | -------------------------------------------------------------------------------- /examples/maplibre/viewport-animation/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/maplibre/zoom-to-bounds/README.md: -------------------------------------------------------------------------------- 1 | # Example: Zoom To Bounds 2 | 3 | Demonstrates how to zoom to a bounding box with react-maplibre. 4 | 5 | ## Usage 6 | 7 | ```bash 8 | npm i 9 | npm run start 10 | ``` 11 | -------------------------------------------------------------------------------- /examples/maplibre/zoom-to-bounds/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-maplibre Example 6 | 7 | 33 | 34 | 35 |
36 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /examples/maplibre/zoom-to-bounds/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../vite.config.local.js", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "@turf/bbox": "^6.5.0", 9 | "maplibre-gl": "^5.0.0", 10 | "react": "^18.0.0", 11 | "react-dom": "^18.0.0", 12 | "react-map-gl": "^8.0.0" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.0.0", 16 | "vite": "^4.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/maplibre/zoom-to-bounds/src/control-panel.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | function ControlPanel() { 4 | return ( 5 |
6 |

Zoom to Bounding Box

7 |

Click on a San Fransisco Neighborhood to zoom in.

8 | 16 |
17 | ); 18 | } 19 | 20 | export default React.memo(ControlPanel); 21 | -------------------------------------------------------------------------------- /examples/maplibre/zoom-to-bounds/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "resolveJsonModule": true, 7 | "moduleResolution": "node", 8 | "module": "ES2020", 9 | "sourceMap": true 10 | } 11 | } -------------------------------------------------------------------------------- /examples/vite.config.local.js: -------------------------------------------------------------------------------- 1 | import {defineConfig} from 'vite'; 2 | import {join} from 'path'; 3 | 4 | const rootDir = join(__dirname, '..'); 5 | 6 | /** https://vitejs.dev/config/ */ 7 | export default defineConfig(async () => { 8 | return { 9 | resolve: { 10 | alias: { 11 | // Use root dependencies 12 | 'react-map-gl/mapbox': join(rootDir, './modules/react-mapbox/src'), 13 | 'react-map-gl/maplibre': join(rootDir, './modules/react-maplibre/src'), 14 | react: join(rootDir, './node_modules/react'), 15 | 'react-dom': join(rootDir, './node_modules/react-dom') 16 | } 17 | }, 18 | define: { 19 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 20 | }, 21 | server: { 22 | open: true, 23 | port: 8080 24 | }, 25 | optimizeDeps: { 26 | esbuildOptions: {target: 'es2020'} 27 | } 28 | }; 29 | }); 30 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl unit tests 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "8.1.0-alpha.2", 3 | "npmClient": "yarn", 4 | "packages": [ 5 | "modules/*" 6 | ] 7 | } -------------------------------------------------------------------------------- /modules/main/README.md: -------------------------------------------------------------------------------- 1 | ../../README.md -------------------------------------------------------------------------------- /modules/main/src/mapbox-legacy/components/attribution-control.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useEffect, memo} from 'react'; 3 | import {applyReactStyle} from '../utils/apply-react-style'; 4 | import {useControl} from './use-control'; 5 | 6 | import type {ControlPosition, AttributionControlOptions} from '../types/lib'; 7 | 8 | export type AttributionControlProps = AttributionControlOptions & { 9 | /** Placement of the control relative to the map. */ 10 | position?: ControlPosition; 11 | /** CSS style override, applied to the control's container */ 12 | style?: React.CSSProperties; 13 | }; 14 | 15 | function _AttributionControl(props: AttributionControlProps) { 16 | const ctrl = useControl(({mapLib}) => new mapLib.AttributionControl(props), { 17 | position: props.position 18 | }); 19 | 20 | useEffect(() => { 21 | // @ts-expect-error accessing private member 22 | applyReactStyle(ctrl._container, props.style); 23 | }, [props.style]); 24 | 25 | return null; 26 | } 27 | 28 | export const AttributionControl = memo(_AttributionControl); 29 | -------------------------------------------------------------------------------- /modules/main/src/mapbox-legacy/components/navigation-control.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useEffect, memo} from 'react'; 3 | import {applyReactStyle} from '../utils/apply-react-style'; 4 | import {useControl} from './use-control'; 5 | 6 | import type {ControlPosition, NavigationControlOptions} from '../types/lib'; 7 | 8 | export type NavigationControlProps = NavigationControlOptions & { 9 | /** Placement of the control relative to the map. */ 10 | position?: ControlPosition; 11 | /** CSS style override, applied to the control's container */ 12 | style?: React.CSSProperties; 13 | }; 14 | 15 | function _NavigationControl(props: NavigationControlProps) { 16 | const ctrl = useControl(({mapLib}) => new mapLib.NavigationControl(props), { 17 | position: props.position 18 | }); 19 | 20 | useEffect(() => { 21 | // @ts-expect-error accessing private member 22 | applyReactStyle(ctrl._container, props.style); 23 | }, [props.style]); 24 | 25 | return null; 26 | } 27 | 28 | export const NavigationControl = memo(_NavigationControl); 29 | -------------------------------------------------------------------------------- /modules/main/src/mapbox-legacy/types/common.ts: -------------------------------------------------------------------------------- 1 | import type {PaddingOptions} from 'mapbox-gl'; 2 | 3 | export type { 4 | Point, 5 | PointLike, 6 | LngLat, 7 | LngLatLike, 8 | LngLatBounds, 9 | LngLatBoundsLike, 10 | PaddingOptions, 11 | MapboxGeoJSONFeature as MapGeoJSONFeature 12 | } from 'mapbox-gl'; 13 | 14 | /* Public */ 15 | 16 | /** Describes the camera's state */ 17 | export type ViewState = { 18 | /** Longitude at map center */ 19 | longitude: number; 20 | /** Latitude at map center */ 21 | latitude: number; 22 | /** Map zoom level */ 23 | zoom: number; 24 | /** Map rotation bearing in degrees counter-clockwise from north */ 25 | bearing: number; 26 | /** Map angle in degrees at which the camera is looking at the ground */ 27 | pitch: number; 28 | /** Dimensions in pixels applied on each side of the viewport for shifting the vanishing point. */ 29 | padding: PaddingOptions; 30 | }; 31 | 32 | export interface ImmutableLike { 33 | toJS: () => T; 34 | } 35 | -------------------------------------------------------------------------------- /modules/main/src/mapbox-legacy/utils/apply-react-style.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | // This is a simplified version of 3 | // https://github.com/facebook/react/blob/4131af3e4bf52f3a003537ec95a1655147c81270/src/renderers/dom/shared/CSSPropertyOperations.js#L62 4 | const unitlessNumber = /box|flex|grid|column|lineHeight|fontWeight|opacity|order|tabSize|zIndex/; 5 | 6 | export function applyReactStyle(element: HTMLElement, styles: React.CSSProperties) { 7 | if (!element || !styles) { 8 | return; 9 | } 10 | const style = element.style; 11 | 12 | for (const key in styles) { 13 | const value = styles[key]; 14 | if (Number.isFinite(value) && !unitlessNumber.test(key)) { 15 | style[key] = `${value}px`; 16 | } else { 17 | style[key] = value; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /modules/main/src/mapbox-legacy/utils/assert.ts: -------------------------------------------------------------------------------- 1 | export default function assert(condition: any, message: string) { 2 | if (!condition) { 3 | throw new Error(message); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /modules/main/src/mapbox-legacy/utils/use-isomorphic-layout-effect.ts: -------------------------------------------------------------------------------- 1 | // From https://github.com/streamich/react-use/blob/master/src/useIsomorphicLayoutEffect.ts 2 | // useLayoutEffect but does not trigger warning in server-side rendering 3 | import {useEffect, useLayoutEffect} from 'react'; 4 | 5 | const useIsomorphicLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect; 6 | 7 | export default useIsomorphicLayoutEffect; 8 | -------------------------------------------------------------------------------- /modules/main/src/mapbox.ts: -------------------------------------------------------------------------------- 1 | export * from '@vis.gl/react-mapbox'; 2 | 3 | export {Map as default} from '@vis.gl/react-mapbox'; 4 | -------------------------------------------------------------------------------- /modules/main/src/maplibre.ts: -------------------------------------------------------------------------------- 1 | export * from '@vis.gl/react-maplibre'; 2 | 3 | export {Map as default} from '@vis.gl/react-maplibre'; 4 | -------------------------------------------------------------------------------- /modules/main/test/components/index.js: -------------------------------------------------------------------------------- 1 | import './map.spec'; 2 | import './controls.spec'; 3 | import './source.spec'; 4 | import './layer.spec'; 5 | import './marker.spec'; 6 | import './popup.spec'; 7 | import './use-map.spec'; 8 | -------------------------------------------------------------------------------- /modules/main/test/utils/apply-react-style.spec.js: -------------------------------------------------------------------------------- 1 | import test from 'tape-promise/tape'; 2 | import {applyReactStyle} from 'react-map-gl/mapbox-legacy/utils/apply-react-style'; 3 | 4 | test('applyReactStyle', t => { 5 | /* global document */ 6 | if (typeof document === 'undefined') { 7 | t.end(); 8 | return; 9 | } 10 | 11 | const div = document.createElement('div'); 12 | 13 | t.doesNotThrow(() => applyReactStyle(null, {}), 'null element'); 14 | 15 | t.doesNotThrow(() => applyReactStyle(div, null), 'null style'); 16 | 17 | applyReactStyle(div, {marginLeft: 4, height: 24, lineHeight: 2, zIndex: 1, flexGrow: 0.5}); 18 | 19 | t.is(div.style.marginLeft, '4px', 'appended px to numeric value'); 20 | t.is(div.style.height, '24px', 'appended px to numeric value'); 21 | t.is(div.style.lineHeight, '2', 'unitless numeric property'); 22 | t.is(div.style.zIndex, '1', 'unitless numeric property'); 23 | t.is(div.style.flexGrow, '0.5', 'unitless numeric property'); 24 | 25 | t.end(); 26 | }); 27 | -------------------------------------------------------------------------------- /modules/main/test/utils/index.js: -------------------------------------------------------------------------------- 1 | import './deep-equal.spec'; 2 | import './transform.spec'; 3 | import './style-utils.spec'; 4 | import './apply-react-style.spec'; 5 | -------------------------------------------------------------------------------- /modules/main/test/utils/mapbox-gl-mock/util.js: -------------------------------------------------------------------------------- 1 | // Generated with 2 | // flow-remove-types ./node_modules/mapbox-gl/src/util/util.js 3 | 4 | export function clamp(n, min, max) { 5 | return Math.min(max, Math.max(min, n)); 6 | } 7 | 8 | export function wrap(n, min, max) { 9 | const d = max - min; 10 | const w = ((((n - min) % d) + d) % d) + min; 11 | return w === min ? max : w; 12 | } 13 | 14 | export function extend(dest, ...sources) { 15 | for (const src of sources) { 16 | for (const k in src) { 17 | dest[k] = src[k]; 18 | } 19 | } 20 | return dest; 21 | } 22 | 23 | export function number(a, b, t) { 24 | return a * (1 - t) + b * t; 25 | } 26 | -------------------------------------------------------------------------------- /modules/main/test/utils/test-utils.jsx: -------------------------------------------------------------------------------- 1 | /* global setTimeout */ 2 | export function sleep(milliseconds) { 3 | return new Promise(resolve => setTimeout(resolve, milliseconds)); 4 | } 5 | 6 | export function waitForMapLoad(mapRef) { 7 | return new Promise(resolve => { 8 | const check = () => { 9 | if (mapRef.current && mapRef.current.getMap().isStyleLoaded()) { 10 | resolve(); 11 | } else { 12 | setTimeout(check, 50); 13 | } 14 | }; 15 | check(); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /modules/main/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"], 4 | "exclude": ["node_modules"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "rootDir": "src", 8 | "outDir": "dist" 9 | }, 10 | "references": [ 11 | {"path": "../react-mapbox"}, 12 | {"path": "../react-maplibre"} 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /modules/react-mapbox/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vis.gl/react-mapbox", 3 | "description": "React components for Mapbox GL JS", 4 | "version": "8.1.0-alpha.2", 5 | "keywords": [ 6 | "mapbox", 7 | "mapbox-gl", 8 | "react", 9 | "react mapbox" 10 | ], 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/visgl/react-map-gl.git" 14 | }, 15 | "license": "MIT", 16 | "type": "module", 17 | "types": "dist/index.d.ts", 18 | "main": "dist/index.cjs", 19 | "module": "dist/index.js", 20 | "exports": { 21 | ".": { 22 | "import": "./dist/index.js", 23 | "require": "./dist/index.cjs", 24 | "types": "./dist/index.d.ts" 25 | } 26 | }, 27 | "files": [ 28 | "src", 29 | "dist", 30 | "README.md" 31 | ], 32 | "devDependencies": { 33 | "mapbox-gl": "^3.9.0" 34 | }, 35 | "peerDependencies": { 36 | "mapbox-gl": ">=3.5.0", 37 | "react": ">=16.3.0", 38 | "react-dom": ">=16.3.0" 39 | }, 40 | "peerDependenciesMeta": { 41 | "mapbox-gl": { 42 | "optional": true 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /modules/react-mapbox/src/components/attribution-control.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useEffect, memo} from 'react'; 3 | import {applyReactStyle} from '../utils/apply-react-style'; 4 | import {useControl} from './use-control'; 5 | 6 | import type {ControlPosition, AttributionControlOptions} from '../types/lib'; 7 | 8 | export type AttributionControlProps = AttributionControlOptions & { 9 | /** Placement of the control relative to the map. */ 10 | position?: ControlPosition; 11 | /** CSS style override, applied to the control's container */ 12 | style?: React.CSSProperties; 13 | }; 14 | 15 | function _AttributionControl(props: AttributionControlProps) { 16 | const ctrl = useControl(({mapLib}) => new mapLib.AttributionControl(props), { 17 | position: props.position 18 | }); 19 | 20 | useEffect(() => { 21 | applyReactStyle(ctrl._container, props.style); 22 | }, [props.style]); 23 | 24 | return null; 25 | } 26 | 27 | export const AttributionControl = memo(_AttributionControl); 28 | -------------------------------------------------------------------------------- /modules/react-mapbox/src/components/navigation-control.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useEffect, memo} from 'react'; 3 | import {applyReactStyle} from '../utils/apply-react-style'; 4 | import {useControl} from './use-control'; 5 | 6 | import type {ControlPosition, NavigationControlOptions} from '../types/lib'; 7 | 8 | export type NavigationControlProps = NavigationControlOptions & { 9 | /** Placement of the control relative to the map. */ 10 | position?: ControlPosition; 11 | /** CSS style override, applied to the control's container */ 12 | style?: React.CSSProperties; 13 | }; 14 | 15 | function _NavigationControl(props: NavigationControlProps) { 16 | const ctrl = useControl(({mapLib}) => new mapLib.NavigationControl(props), { 17 | position: props.position 18 | }); 19 | 20 | useEffect(() => { 21 | applyReactStyle(ctrl._container, props.style); 22 | }, [props.style]); 23 | 24 | return null; 25 | } 26 | 27 | export const NavigationControl = memo(_NavigationControl); 28 | -------------------------------------------------------------------------------- /modules/react-mapbox/src/types/common.ts: -------------------------------------------------------------------------------- 1 | import type {PaddingOptions} from 'mapbox-gl'; 2 | 3 | export type { 4 | Point, 5 | PointLike, 6 | LngLat, 7 | LngLatLike, 8 | LngLatBounds, 9 | LngLatBoundsLike, 10 | PaddingOptions, 11 | GeoJSONFeature as MapGeoJSONFeature 12 | } from 'mapbox-gl'; 13 | 14 | /* Public */ 15 | 16 | /** Describes the camera's state */ 17 | export type ViewState = { 18 | /** Longitude at map center */ 19 | longitude: number; 20 | /** Latitude at map center */ 21 | latitude: number; 22 | /** Map zoom level */ 23 | zoom: number; 24 | /** Map rotation bearing in degrees counter-clockwise from north */ 25 | bearing: number; 26 | /** Map angle in degrees at which the camera is looking at the ground */ 27 | pitch: number; 28 | /** Dimensions in pixels applied on each side of the viewport for shifting the vanishing point. */ 29 | padding: PaddingOptions; 30 | /** Center elevation on terrain */ 31 | elevation?: number; 32 | }; 33 | 34 | export interface ImmutableLike { 35 | toJS: () => T; 36 | } 37 | -------------------------------------------------------------------------------- /modules/react-mapbox/src/types/internal.ts: -------------------------------------------------------------------------------- 1 | // Internal types 2 | import type {Map} from 'mapbox-gl'; 3 | 4 | export type Transform = Map['transform']; 5 | 6 | export type { 7 | GeoJSONSource as GeoJSONSourceImplementation, 8 | ImageSource as ImageSourceImplementation, 9 | CanvasSource as CanvasSourceImplementation, 10 | VectorTileSource as VectorSourceImplementation, 11 | RasterTileSource as RasterSourceImplementation, 12 | RasterDemTileSource as RasterDemSourceImplementation, 13 | VideoSource as VideoSourceImplementation, 14 | Source as AnySourceImplementation 15 | } from 'mapbox-gl'; 16 | -------------------------------------------------------------------------------- /modules/react-mapbox/src/utils/apply-react-style.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | // This is a simplified version of 3 | // https://github.com/facebook/react/blob/4131af3e4bf52f3a003537ec95a1655147c81270/src/renderers/dom/shared/CSSPropertyOperations.js#L62 4 | const unitlessNumber = /box|flex|grid|column|lineHeight|fontWeight|opacity|order|tabSize|zIndex/; 5 | 6 | export function applyReactStyle(element: HTMLElement, styles: React.CSSProperties) { 7 | if (!element || !styles) { 8 | return; 9 | } 10 | const style = element.style; 11 | 12 | for (const key in styles) { 13 | const value = styles[key]; 14 | if (Number.isFinite(value) && !unitlessNumber.test(key)) { 15 | style[key] = `${value}px`; 16 | } else { 17 | style[key] = value; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /modules/react-mapbox/src/utils/assert.ts: -------------------------------------------------------------------------------- 1 | export default function assert(condition: any, message: string) { 2 | if (!condition) { 3 | throw new Error(message); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /modules/react-mapbox/src/utils/compare-class-names.ts: -------------------------------------------------------------------------------- 1 | /** Compare two classNames string and return the difference */ 2 | export function compareClassNames( 3 | prevClassName: string | undefined, 4 | nextClassName: string | undefined 5 | ): string[] | null { 6 | if (prevClassName === nextClassName) { 7 | return null; 8 | } 9 | 10 | const prevClassList = getClassList(prevClassName); 11 | const nextClassList = getClassList(nextClassName); 12 | const diff: string[] = []; 13 | 14 | for (const c of nextClassList) { 15 | if (!prevClassList.has(c)) { 16 | diff.push(c); 17 | } 18 | } 19 | for (const c of prevClassList) { 20 | if (!nextClassList.has(c)) { 21 | diff.push(c); 22 | } 23 | } 24 | return diff.length === 0 ? null : diff; 25 | } 26 | 27 | function getClassList(className: string | undefined) { 28 | return new Set(className ? className.trim().split(/\s+/) : []); 29 | } 30 | -------------------------------------------------------------------------------- /modules/react-mapbox/src/utils/use-isomorphic-layout-effect.ts: -------------------------------------------------------------------------------- 1 | // From https://github.com/streamich/react-use/blob/master/src/useIsomorphicLayoutEffect.ts 2 | // useLayoutEffect but does not trigger warning in server-side rendering 3 | import {useEffect, useLayoutEffect} from 'react'; 4 | 5 | const useIsomorphicLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect; 6 | 7 | export default useIsomorphicLayoutEffect; 8 | -------------------------------------------------------------------------------- /modules/react-mapbox/test/components/index.js: -------------------------------------------------------------------------------- 1 | import './map.spec'; 2 | import './controls.spec'; 3 | import './source.spec'; 4 | import './layer.spec'; 5 | import './marker.spec'; 6 | import './popup.spec'; 7 | import './use-map.spec'; 8 | -------------------------------------------------------------------------------- /modules/react-mapbox/test/utils/apply-react-style.spec.js: -------------------------------------------------------------------------------- 1 | import test from 'tape-promise/tape'; 2 | import {applyReactStyle} from '@vis.gl/react-mapbox/utils/apply-react-style'; 3 | 4 | test('applyReactStyle', t => { 5 | /* global document */ 6 | if (typeof document === 'undefined') { 7 | t.end(); 8 | return; 9 | } 10 | 11 | const div = document.createElement('div'); 12 | 13 | t.doesNotThrow(() => applyReactStyle(null, {}), 'null element'); 14 | 15 | t.doesNotThrow(() => applyReactStyle(div, null), 'null style'); 16 | 17 | applyReactStyle(div, {marginLeft: 4, height: 24, lineHeight: 2, zIndex: 1, flexGrow: 0.5}); 18 | 19 | t.is(div.style.marginLeft, '4px', 'appended px to numeric value'); 20 | t.is(div.style.height, '24px', 'appended px to numeric value'); 21 | t.is(div.style.lineHeight, '2', 'unitless numeric property'); 22 | t.is(div.style.zIndex, '1', 'unitless numeric property'); 23 | t.is(div.style.flexGrow, '0.5', 'unitless numeric property'); 24 | 25 | t.end(); 26 | }); 27 | -------------------------------------------------------------------------------- /modules/react-mapbox/test/utils/index.js: -------------------------------------------------------------------------------- 1 | import './deep-equal.spec'; 2 | import './transform.spec'; 3 | import './style-utils.spec'; 4 | import './apply-react-style.spec'; 5 | import './compare-class-names.spec'; 6 | -------------------------------------------------------------------------------- /modules/react-mapbox/test/utils/mapbox-gl-mock/util.js: -------------------------------------------------------------------------------- 1 | // Generated with 2 | // flow-remove-types ./node_modules/mapbox-gl/src/util/util.js 3 | 4 | export function clamp(n, min, max) { 5 | return Math.min(max, Math.max(min, n)); 6 | } 7 | 8 | export function wrap(n, min, max) { 9 | const d = max - min; 10 | const w = ((((n - min) % d) + d) % d) + min; 11 | return w === min ? max : w; 12 | } 13 | 14 | export function extend(dest, ...sources) { 15 | for (const src of sources) { 16 | for (const k in src) { 17 | dest[k] = src[k]; 18 | } 19 | } 20 | return dest; 21 | } 22 | 23 | export function number(a, b, t) { 24 | return a * (1 - t) + b * t; 25 | } 26 | -------------------------------------------------------------------------------- /modules/react-mapbox/test/utils/test-utils.jsx: -------------------------------------------------------------------------------- 1 | /* global setTimeout */ 2 | export function sleep(milliseconds) { 3 | return new Promise(resolve => setTimeout(resolve, milliseconds)); 4 | } 5 | 6 | export function waitForMapLoad(mapRef) { 7 | return new Promise(resolve => { 8 | const check = () => { 9 | if (mapRef.current && mapRef.current.getMap().isStyleLoaded()) { 10 | resolve(); 11 | } else { 12 | setTimeout(check, 50); 13 | } 14 | }; 15 | check(); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /modules/react-mapbox/test/utils/token.js: -------------------------------------------------------------------------------- 1 | export const MapboxAccessToken = import.meta.env.VITE_MAPBOX_TOKEN; 2 | -------------------------------------------------------------------------------- /modules/react-mapbox/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"], 4 | "exclude": ["node_modules"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "rootDir": "src", 8 | "outDir": "dist" 9 | }, 10 | "references": [ 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /modules/react-maplibre/src/components/attribution-control.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useEffect, memo} from 'react'; 3 | import {applyReactStyle} from '../utils/apply-react-style'; 4 | import {useControl} from './use-control'; 5 | 6 | import type {ControlPosition, AttributionControlOptions} from '../types/lib'; 7 | 8 | export type AttributionControlProps = AttributionControlOptions & { 9 | /** Placement of the control relative to the map. */ 10 | position?: ControlPosition; 11 | /** CSS style override, applied to the control's container */ 12 | style?: React.CSSProperties; 13 | }; 14 | 15 | function _AttributionControl(props: AttributionControlProps) { 16 | const ctrl = useControl(({mapLib}) => new mapLib.AttributionControl(props), { 17 | position: props.position 18 | }); 19 | 20 | useEffect(() => { 21 | applyReactStyle(ctrl._container, props.style); 22 | }, [props.style]); 23 | 24 | return null; 25 | } 26 | 27 | export const AttributionControl = memo(_AttributionControl); 28 | -------------------------------------------------------------------------------- /modules/react-maplibre/src/components/logo-control.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useEffect, memo} from 'react'; 3 | import {applyReactStyle} from '../utils/apply-react-style'; 4 | import {useControl} from './use-control'; 5 | 6 | import type {ControlPosition, LogoControlOptions} from '../types/lib'; 7 | 8 | export type LogoControlProps = LogoControlOptions & { 9 | /** Placement of the control relative to the map. */ 10 | position?: ControlPosition; 11 | /** CSS style override, applied to the control's container */ 12 | style?: React.CSSProperties; 13 | }; 14 | 15 | function _LogoControl(props: LogoControlProps) { 16 | const ctrl = useControl(({mapLib}) => new mapLib.LogoControl(props), {position: props.position}); 17 | 18 | useEffect(() => { 19 | applyReactStyle(ctrl._container, props.style); 20 | }, [props.style]); 21 | 22 | return null; 23 | } 24 | 25 | export const LogoControl = memo(_LogoControl); 26 | -------------------------------------------------------------------------------- /modules/react-maplibre/src/components/navigation-control.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useEffect, memo} from 'react'; 3 | import {applyReactStyle} from '../utils/apply-react-style'; 4 | import {useControl} from './use-control'; 5 | 6 | import type {ControlPosition, NavigationControlOptions} from '../types/lib'; 7 | 8 | export type NavigationControlProps = NavigationControlOptions & { 9 | /** Placement of the control relative to the map. */ 10 | position?: ControlPosition; 11 | /** CSS style override, applied to the control's container */ 12 | style?: React.CSSProperties; 13 | }; 14 | 15 | function _NavigationControl(props: NavigationControlProps) { 16 | const ctrl = useControl(({mapLib}) => new mapLib.NavigationControl(props), { 17 | position: props.position 18 | }); 19 | 20 | useEffect(() => { 21 | applyReactStyle(ctrl._container, props.style); 22 | }, [props.style]); 23 | 24 | return null; 25 | } 26 | 27 | export const NavigationControl = memo(_NavigationControl); 28 | -------------------------------------------------------------------------------- /modules/react-maplibre/src/components/terrain-control.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {useEffect, memo} from 'react'; 3 | import {applyReactStyle} from '../utils/apply-react-style'; 4 | import {useControl} from './use-control'; 5 | 6 | import type {ControlPosition} from '../types/lib'; 7 | import type {TerrainSpecification} from '../types/style-spec'; 8 | 9 | export type TerrainControlProps = TerrainSpecification & { 10 | /** Placement of the control relative to the map. */ 11 | position?: ControlPosition; 12 | /** CSS style override, applied to the control's container */ 13 | style?: React.CSSProperties; 14 | }; 15 | 16 | function _TerrainControl(props: TerrainControlProps) { 17 | const ctrl = useControl(({mapLib}) => new mapLib.TerrainControl(props), { 18 | position: props.position 19 | }); 20 | 21 | useEffect(() => { 22 | applyReactStyle(ctrl._container, props.style); 23 | }, [props.style]); 24 | 25 | return null; 26 | } 27 | 28 | export const TerrainControl = memo(_TerrainControl); 29 | -------------------------------------------------------------------------------- /modules/react-maplibre/src/types/common.ts: -------------------------------------------------------------------------------- 1 | import type {PaddingOptions} from 'maplibre-gl'; 2 | 3 | export type { 4 | Point, 5 | PointLike, 6 | LngLat, 7 | LngLatLike, 8 | LngLatBounds, 9 | LngLatBoundsLike, 10 | PaddingOptions, 11 | MapGeoJSONFeature 12 | } from 'maplibre-gl'; 13 | 14 | /* Public */ 15 | 16 | /** Describes the camera's state */ 17 | export type ViewState = { 18 | /** Longitude at map center */ 19 | longitude: number; 20 | /** Latitude at map center */ 21 | latitude: number; 22 | /** Map zoom level */ 23 | zoom: number; 24 | /** Map rotation bearing in degrees counter-clockwise from north */ 25 | bearing: number; 26 | /** Map angle in degrees at which the camera is looking at the ground */ 27 | pitch: number; 28 | /** Dimensions in pixels applied on each side of the viewport for shifting the vanishing point. */ 29 | padding: PaddingOptions; 30 | }; 31 | 32 | export interface ImmutableLike { 33 | toJS: () => T; 34 | } 35 | -------------------------------------------------------------------------------- /modules/react-maplibre/src/types/internal.ts: -------------------------------------------------------------------------------- 1 | // Internal types 2 | import type {LngLat, PaddingOptions} from 'maplibre-gl'; 3 | 4 | /** 5 | * maplibre's Transform interface / CameraUpdateTransformFunction argument 6 | */ 7 | export type TransformLike = { 8 | center: LngLat; 9 | zoom: number; 10 | roll?: number; 11 | pitch: number; 12 | bearing: number; 13 | elevation: number; 14 | padding?: PaddingOptions; 15 | }; 16 | 17 | export type { 18 | GeoJSONSource as GeoJSONSourceImplementation, 19 | ImageSource as ImageSourceImplementation, 20 | CanvasSource as CanvasSourceImplementation, 21 | VectorTileSource as VectorSourceImplementation, 22 | RasterTileSource as RasterSourceImplementation, 23 | RasterDEMTileSource as RasterDemSourceImplementation, 24 | VideoSource as VideoSourceImplementation, 25 | Source as AnySourceImplementation 26 | } from 'maplibre-gl'; 27 | -------------------------------------------------------------------------------- /modules/react-maplibre/src/types/style-spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Maplibre Style Specification types 3 | * Type names are aligned with mapbox 4 | */ 5 | export type { 6 | // Layers 7 | LayerSpecification, 8 | FillLayerSpecification, 9 | LineLayerSpecification, 10 | SymbolLayerSpecification, 11 | CircleLayerSpecification, 12 | HeatmapLayerSpecification, 13 | FillExtrusionLayerSpecification, 14 | RasterLayerSpecification, 15 | HillshadeLayerSpecification, 16 | BackgroundLayerSpecification, 17 | 18 | // Sources 19 | SourceSpecification, 20 | VectorSourceSpecification, 21 | RasterSourceSpecification, 22 | RasterDEMSourceSpecification, 23 | GeoJSONSourceSpecification, 24 | VideoSourceSpecification, 25 | ImageSourceSpecification, 26 | CanvasSourceSpecification, 27 | 28 | // Style 29 | StyleSpecification, 30 | SkySpecification, 31 | LightSpecification, 32 | TerrainSpecification, 33 | ProjectionSpecification 34 | } from 'maplibre-gl'; 35 | -------------------------------------------------------------------------------- /modules/react-maplibre/src/utils/apply-react-style.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | // This is a simplified version of 3 | // https://github.com/facebook/react/blob/4131af3e4bf52f3a003537ec95a1655147c81270/src/renderers/dom/shared/CSSPropertyOperations.js#L62 4 | const unitlessNumber = /box|flex|grid|column|lineHeight|fontWeight|opacity|order|tabSize|zIndex/; 5 | 6 | export function applyReactStyle(element: HTMLElement, styles: React.CSSProperties) { 7 | if (!element || !styles) { 8 | return; 9 | } 10 | const style = element.style; 11 | 12 | for (const key in styles) { 13 | const value = styles[key]; 14 | if (Number.isFinite(value) && !unitlessNumber.test(key)) { 15 | style[key] = `${value}px`; 16 | } else { 17 | style[key] = value; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /modules/react-maplibre/src/utils/assert.ts: -------------------------------------------------------------------------------- 1 | export default function assert(condition: any, message: string) { 2 | if (!condition) { 3 | throw new Error(message); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /modules/react-maplibre/src/utils/compare-class-names.ts: -------------------------------------------------------------------------------- 1 | /** Compare two classNames string and return the difference */ 2 | export function compareClassNames( 3 | prevClassName: string | undefined, 4 | nextClassName: string | undefined 5 | ): string[] | null { 6 | if (prevClassName === nextClassName) { 7 | return null; 8 | } 9 | 10 | const prevClassList = getClassList(prevClassName); 11 | const nextClassList = getClassList(nextClassName); 12 | const diff: string[] = []; 13 | 14 | for (const c of nextClassList) { 15 | if (!prevClassList.has(c)) { 16 | diff.push(c); 17 | } 18 | } 19 | for (const c of prevClassList) { 20 | if (!nextClassList.has(c)) { 21 | diff.push(c); 22 | } 23 | } 24 | return diff.length === 0 ? null : diff; 25 | } 26 | 27 | function getClassList(className: string | undefined) { 28 | return new Set(className ? className.trim().split(/\s+/) : []); 29 | } 30 | -------------------------------------------------------------------------------- /modules/react-maplibre/src/utils/use-isomorphic-layout-effect.ts: -------------------------------------------------------------------------------- 1 | // From https://github.com/streamich/react-use/blob/master/src/useIsomorphicLayoutEffect.ts 2 | // useLayoutEffect but does not trigger warning in server-side rendering 3 | import {useEffect, useLayoutEffect} from 'react'; 4 | 5 | const useIsomorphicLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect; 6 | 7 | export default useIsomorphicLayoutEffect; 8 | -------------------------------------------------------------------------------- /modules/react-maplibre/test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "import/no-unresolved": 0, 4 | "import/no-extraneous-dependencies": 0 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /modules/react-maplibre/test/components/index.js: -------------------------------------------------------------------------------- 1 | import './map.spec'; 2 | import './controls.spec'; 3 | import './source.spec'; 4 | import './layer.spec'; 5 | import './marker.spec'; 6 | import './popup.spec'; 7 | import './use-map.spec'; 8 | -------------------------------------------------------------------------------- /modules/react-maplibre/test/utils/apply-react-style.spec.js: -------------------------------------------------------------------------------- 1 | import test from 'tape-promise/tape'; 2 | import {applyReactStyle} from '@vis.gl/react-maplibre/utils/apply-react-style'; 3 | 4 | test('applyReactStyle', t => { 5 | /* global document */ 6 | if (typeof document === 'undefined') { 7 | t.end(); 8 | return; 9 | } 10 | 11 | const div = document.createElement('div'); 12 | 13 | t.doesNotThrow(() => applyReactStyle(null, {}), 'null element'); 14 | 15 | t.doesNotThrow(() => applyReactStyle(div, null), 'null style'); 16 | 17 | applyReactStyle(div, {marginLeft: 4, height: 24, lineHeight: 2, zIndex: 1, flexGrow: 0.5}); 18 | 19 | t.is(div.style.marginLeft, '4px', 'appended px to numeric value'); 20 | t.is(div.style.height, '24px', 'appended px to numeric value'); 21 | t.is(div.style.lineHeight, '2', 'unitless numeric property'); 22 | t.is(div.style.zIndex, '1', 'unitless numeric property'); 23 | t.is(div.style.flexGrow, '0.5', 'unitless numeric property'); 24 | 25 | t.end(); 26 | }); 27 | -------------------------------------------------------------------------------- /modules/react-maplibre/test/utils/index.js: -------------------------------------------------------------------------------- 1 | import './deep-equal.spec'; 2 | import './transform.spec'; 3 | import './style-utils.spec'; 4 | import './apply-react-style.spec'; 5 | import './compare-class-names.spec'; 6 | -------------------------------------------------------------------------------- /modules/react-maplibre/test/utils/test-utils.jsx: -------------------------------------------------------------------------------- 1 | /* global setTimeout */ 2 | export function sleep(milliseconds) { 3 | return new Promise(resolve => setTimeout(resolve, milliseconds)); 4 | } 5 | 6 | export function waitForMapLoad(mapRef) { 7 | return new Promise(resolve => { 8 | const check = () => { 9 | if (mapRef.current?.isStyleLoaded()) { 10 | resolve(); 11 | } else { 12 | setTimeout(check, 50); 13 | } 14 | }; 15 | check(); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /modules/react-maplibre/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src/**/*"], 4 | "exclude": ["node_modules"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "rootDir": "src", 8 | "outDir": "dist" 9 | }, 10 | "references": [ 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /scripts/update-release-branch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Example: 3 | # update-release-branch.sh 8.0 4 | 5 | set -e 6 | 7 | BRANCH=`echo "$1-release"` 8 | VERSION=`echo "$1.0"` 9 | 10 | echo "Updating branch to ${BRANCH}..." 11 | 12 | # Replace source links in docs and examples 13 | find docs -mindepth 2 -iname "*.md" -exec perl -i -pe "s/react-map-gl\/(tree|blob)\/(master|[0-9\.]+-release)/react-map-gl\/tree\/${BRANCH}/g" {} \; 14 | find examples \( -iname "*.js" -iname "*.jsx" -iname "*.ts" -o -iname "*.tsx" \) -type f -exec perl -i -pe "s/react-map-gl\/(tree|blob)\/(master|[0-9\.]+-release)/react-map-gl\/tree\/${BRANCH}/g" {} \; 15 | 16 | # Bump dependencies in examples 17 | update_dep() { 18 | local FILE=$1 19 | local VERSION=$2 20 | cat $FILE | jq ".dependencies |= . + \ 21 | with_entries(select(.key | match(\"react-map-gl\")) | .value |= \"^${VERSION}\")" > temp 22 | mv temp $FILE 23 | } 24 | 25 | # https://stackoverflow.com/questions/4321456/find-exec-a-shell-function-in-linux 26 | export -f update_dep 27 | find examples -type f -name "package.json" -exec bash -c 'update_dep "$0" $1' {} $VERSION \; 28 | -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "import/no-unresolved": 0, 4 | "import/no-extraneous-dependencies": 0 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /test/apps/reuse-maps/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | react-map-gl Example 6 | 7 | 24 | 25 | 26 |
27 | 28 | 32 | 33 | -------------------------------------------------------------------------------- /test/apps/reuse-maps/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start": "vite --open", 4 | "start-local": "vite --config ../../examples/vite.config.local.js" 5 | }, 6 | "dependencies": { 7 | "react": "^17.0.0", 8 | "react-dom": "^17.0.0", 9 | "react-map-gl": "^7.0.0", 10 | "mapbox-gl": "^2.0.0" 11 | }, 12 | "devDependencies": { 13 | "typescript": "^4.0.0", 14 | "vite": "^4.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /test/apps/reuse-maps/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "jsx": "react", 5 | "allowSyntheticDefaultImports": true, 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "module": "ES2020" 9 | } 10 | } -------------------------------------------------------------------------------- /test/apps/reuse-maps/vite.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | define: { 3 | 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /test/browser.js: -------------------------------------------------------------------------------- 1 | /* global window */ 2 | import test from 'tape'; 3 | 4 | test.onFinish(window.browserTestDriver_finish); 5 | test.onFailure(window.browserTestDriver_fail); 6 | 7 | import '../modules/main/test/components'; 8 | import '../modules/main/test/utils'; 9 | import '../modules/react-mapbox/test/components'; 10 | import '../modules/react-mapbox/test/utils'; 11 | import '../modules/react-maplibre/test/components'; 12 | import '../modules/react-maplibre/test/utils'; 13 | // import './render'; 14 | -------------------------------------------------------------------------------- /test/data/glyph/UberMove/0-255: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/data/glyph/UberMove/0-255 -------------------------------------------------------------------------------- /test/data/sprite/tools/14/sprites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/data/sprite/tools/14/sprites.png -------------------------------------------------------------------------------- /test/data/tile/v1/12/655/1582/COMPOSITE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/data/tile/v1/12/655/1582/COMPOSITE -------------------------------------------------------------------------------- /test/data/tile/v1/12/655/1582/POI: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/data/tile/v1/12/655/1582/POI -------------------------------------------------------------------------------- /test/data/tile/v1/12/655/1583/COMPOSITE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/data/tile/v1/12/655/1583/COMPOSITE -------------------------------------------------------------------------------- /test/data/tile/v1/12/655/1583/POI: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/data/tile/v1/12/655/1583/POI -------------------------------------------------------------------------------- /test/node.js: -------------------------------------------------------------------------------- 1 | import './src/exports'; 2 | import '../modules/main/test/utils'; 3 | import '../modules/react-mapbox/test/utils'; 4 | import '../modules/react-maplibre/test/utils'; 5 | -------------------------------------------------------------------------------- /test/render/golden-images/alt-empty-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/render/golden-images/alt-empty-map.png -------------------------------------------------------------------------------- /test/render/golden-images/basic-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/render/golden-images/basic-map.png -------------------------------------------------------------------------------- /test/render/golden-images/geolocate-control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/render/golden-images/geolocate-control.png -------------------------------------------------------------------------------- /test/render/golden-images/marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/render/golden-images/marker.png -------------------------------------------------------------------------------- /test/render/golden-images/navigation-control.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/render/golden-images/navigation-control.png -------------------------------------------------------------------------------- /test/render/golden-images/popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/render/golden-images/popup.png -------------------------------------------------------------------------------- /test/render/golden-images/source-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/render/golden-images/source-01.png -------------------------------------------------------------------------------- /test/render/golden-images/source-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/render/golden-images/source-02.png -------------------------------------------------------------------------------- /test/render/golden-images/uber-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/test/render/golden-images/uber-map.png -------------------------------------------------------------------------------- /test/size/mapbox-legacy.js: -------------------------------------------------------------------------------- 1 | import * as lib from 'react-map-gl/mapbox-legacy'; 2 | 3 | console.log(lib); // eslint-disable-line 4 | -------------------------------------------------------------------------------- /test/size/mapbox.js: -------------------------------------------------------------------------------- 1 | import * as lib from 'react-map-gl/mapbox'; 2 | 3 | console.log(lib); // eslint-disable-line 4 | -------------------------------------------------------------------------------- /test/size/maplibre.js: -------------------------------------------------------------------------------- 1 | import * as lib from 'react-map-gl/maplibre'; 2 | 3 | console.log(lib); // eslint-disable-line 4 | -------------------------------------------------------------------------------- /test/test-utils.js: -------------------------------------------------------------------------------- 1 | const EPSILON = 1e-9; 2 | 3 | // Discard precision errors for comparison 4 | export function toLowPrecision(input, precision = 11) { 5 | if (Number.isFinite(input)) { 6 | return Number(input.toPrecision(precision)); 7 | } else if (Array.isArray(input)) { 8 | return input.map(item => toLowPrecision(item, precision)); 9 | } else if (input) { 10 | const output = {}; 11 | for (const key in input) { 12 | output[key] = toLowPrecision(input[key], precision); 13 | } 14 | return output; 15 | } 16 | return input; 17 | } 18 | 19 | // Compare two [lng, lat] locations, account for longitude wrapping 20 | export function isSameLocation(lngLat1, lngLat2) { 21 | const lng1 = toLowPrecision(lngLat1[0]); 22 | const lat1 = toLowPrecision(lngLat1[1]); 23 | const lng2 = toLowPrecision(lngLat2[0]); 24 | const lat2 = toLowPrecision(lngLat2[1]); 25 | return (lng1 - lng2) % 360 === 0 && lat1 === lat2; 26 | } 27 | 28 | export function equals(a, b, epsilon = EPSILON) { 29 | return Math.abs(a - b) < epsilon; 30 | } 31 | -------------------------------------------------------------------------------- /website/.eslintignore: -------------------------------------------------------------------------------- 1 | ../dist 2 | ../examples 3 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | public/ 2 | .cache/ 3 | .docusaurus/ 4 | build/ 5 | -------------------------------------------------------------------------------- /website/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | plugins: ["styled-components"] 4 | }; 5 | -------------------------------------------------------------------------------- /website/src/examples/index.mdx: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | import {ExamplesIndex} from '@vis.gl/docusaurus-website/components'; 4 | 5 | { 6 | let id = item.docId || item.label.toLowerCase(); 7 | id = id.slice(id.indexOf('/')); 8 | return `/images/examples/${id}.jpg`; 9 | }} /> 10 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/clusters.mdx: -------------------------------------------------------------------------------- 1 | # Clusters 2 | 3 | import App from 'mapbox-examples/clusters/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/controls.mdx: -------------------------------------------------------------------------------- 1 | # Markers, Popups and Controls 2 | 3 | import App from 'mapbox-examples/controls/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/custom-cursor.mdx: -------------------------------------------------------------------------------- 1 | # Custom Cursor 2 | 3 | import App from 'mapbox-examples/custom-cursor/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/draggable-markers.mdx: -------------------------------------------------------------------------------- 1 | # Draggable Marker 2 | 3 | import App from 'mapbox-examples/draggable-markers/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/draw-polygon.mdx: -------------------------------------------------------------------------------- 1 | # Draw Polygon 2 | 3 | import App from 'mapbox-examples/draw-polygon/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/filter.mdx: -------------------------------------------------------------------------------- 1 | # Highlight By Filter 2 | 3 | import App from 'mapbox-examples/filter/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/geocoder.mdx: -------------------------------------------------------------------------------- 1 | # Geocoder 2 | 3 | import App from 'mapbox-examples/geocoder/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/geojson-animation.mdx: -------------------------------------------------------------------------------- 1 | # GeoJSON Animation 2 | 3 | import App from 'mapbox-examples/geojson-animation/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/geojson.mdx: -------------------------------------------------------------------------------- 1 | # GeoJSON 2 | 3 | import App from 'mapbox-examples/geojson/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/heatmap.mdx: -------------------------------------------------------------------------------- 1 | # Heatmap 2 | 3 | import App from 'mapbox-examples/heatmap/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/interaction.mdx: -------------------------------------------------------------------------------- 1 | # Limit Map Interaction 2 | 3 | import App from 'mapbox-examples/interaction/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/layers.mdx: -------------------------------------------------------------------------------- 1 | # Dynamic Styling 2 | 3 | import App from 'mapbox-examples/layers/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/side-by-side.mdx: -------------------------------------------------------------------------------- 1 | # Side by Side 2 | 3 | import App from 'mapbox-examples/side-by-side/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/terrain.mdx: -------------------------------------------------------------------------------- 1 | # Terrain 2 | 3 | import App from 'mapbox-examples/terrain/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/viewport-animation.mdx: -------------------------------------------------------------------------------- 1 | # Camera Transition 2 | 3 | import App from 'mapbox-examples/viewport-animation/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/mapbox/zoom-to-bounds.mdx: -------------------------------------------------------------------------------- 1 | # Zoom to Bounds 2 | 3 | import App from 'mapbox-examples/zoom-to-bounds/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/clusters.mdx: -------------------------------------------------------------------------------- 1 | # Clusters 2 | 3 | import App from 'maplibre-examples/clusters/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/controls.mdx: -------------------------------------------------------------------------------- 1 | # Markers, Popups and Controls 2 | 3 | import App from 'maplibre-examples/controls/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/custom-cursor.mdx: -------------------------------------------------------------------------------- 1 | # Custom Cursor 2 | 3 | import App from 'maplibre-examples/custom-cursor/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/draggable-markers.mdx: -------------------------------------------------------------------------------- 1 | # Draggable Marker 2 | 3 | import App from 'maplibre-examples/draggable-markers/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/draw-polygon.mdx: -------------------------------------------------------------------------------- 1 | # Draw Polygon 2 | 3 | import App from 'maplibre-examples/draw-polygon/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/filter.mdx: -------------------------------------------------------------------------------- 1 | # Highlight By Filter 2 | 3 | import App from 'maplibre-examples/filter/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/geocoder.mdx: -------------------------------------------------------------------------------- 1 | # Geocoder 2 | 3 | import App from 'maplibre-examples/geocoder/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/geojson-animation.mdx: -------------------------------------------------------------------------------- 1 | # GeoJSON Animation 2 | 3 | import App from 'maplibre-examples/geojson-animation/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/geojson.mdx: -------------------------------------------------------------------------------- 1 | # GeoJSON 2 | 3 | import App from 'maplibre-examples/geojson/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/heatmap.mdx: -------------------------------------------------------------------------------- 1 | # Heatmap 2 | 3 | import App from 'maplibre-examples/heatmap/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/interaction.mdx: -------------------------------------------------------------------------------- 1 | # Limit Map Interaction 2 | 3 | import App from 'maplibre-examples/interaction/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/layers.mdx: -------------------------------------------------------------------------------- 1 | # Dynamic Styling 2 | 3 | import App from 'maplibre-examples/layers/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/side-by-side.mdx: -------------------------------------------------------------------------------- 1 | # Side by Side 2 | 3 | import App from 'maplibre-examples/side-by-side/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/terrain.mdx: -------------------------------------------------------------------------------- 1 | # Terrain 2 | 3 | import App from 'maplibre-examples/terrain/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/viewport-animation.mdx: -------------------------------------------------------------------------------- 1 | # Camera Transition 2 | 3 | import App from 'maplibre-examples/viewport-animation/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/src/examples/maplibre/zoom-to-bounds.mdx: -------------------------------------------------------------------------------- 1 | # Zoom to Bounds 2 | 3 | import App from 'maplibre-examples/zoom-to-bounds/src/app'; 4 | 5 | 6 | -------------------------------------------------------------------------------- /website/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/favicon.ico -------------------------------------------------------------------------------- /website/static/images/examples/clusters.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/clusters.jpg -------------------------------------------------------------------------------- /website/static/images/examples/controls.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/controls.jpg -------------------------------------------------------------------------------- /website/static/images/examples/custom-cursor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/custom-cursor.jpg -------------------------------------------------------------------------------- /website/static/images/examples/draggable-markers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/draggable-markers.jpg -------------------------------------------------------------------------------- /website/static/images/examples/draw-polygon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/draw-polygon.jpg -------------------------------------------------------------------------------- /website/static/images/examples/filter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/filter.jpg -------------------------------------------------------------------------------- /website/static/images/examples/geocoder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/geocoder.jpg -------------------------------------------------------------------------------- /website/static/images/examples/geojson-animation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/geojson-animation.jpg -------------------------------------------------------------------------------- /website/static/images/examples/geojson.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/geojson.jpg -------------------------------------------------------------------------------- /website/static/images/examples/heatmap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/heatmap.jpg -------------------------------------------------------------------------------- /website/static/images/examples/interaction.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/interaction.jpg -------------------------------------------------------------------------------- /website/static/images/examples/layers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/layers.jpg -------------------------------------------------------------------------------- /website/static/images/examples/side-by-side.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/side-by-side.jpg -------------------------------------------------------------------------------- /website/static/images/examples/terrain.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/terrain.jpg -------------------------------------------------------------------------------- /website/static/images/examples/viewport-animation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/viewport-animation.jpg -------------------------------------------------------------------------------- /website/static/images/examples/zoom-to-bounds.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/examples/zoom-to-bounds.jpg -------------------------------------------------------------------------------- /website/static/images/hero-sm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/hero-sm.jpg -------------------------------------------------------------------------------- /website/static/images/hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/hero.jpg -------------------------------------------------------------------------------- /website/static/images/visgl-logo-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/visgl-logo-dark.png -------------------------------------------------------------------------------- /website/static/images/visgl-logo-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/visgl-logo-light.png -------------------------------------------------------------------------------- /website/static/images/visgl-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/visgl/react-map-gl/948fd2e4f4156756d2fcee8c2a900cfe55b43608/website/static/images/visgl-logo.png --------------------------------------------------------------------------------