diff --git a/examples/clusters/app.css b/examples/clusters/app.css deleted file mode 100644 index 72db167a..00000000 --- a/examples/clusters/app.css +++ /dev/null @@ -1,24 +0,0 @@ -body { - margin: 0; - background: #000; -} -#map { - width: 100vw; - height: 100vh; -} - -.control-panel { - position: absolute; - top: 0; - right: 0; - max-width: 320px; - background: #fff; - box-shadow: 0 2px 4px rgba(0,0,0,0.3); - padding: 12px 24px; - margin: 20px; - font-size: 13px; - line-height: 2; - color: #6b6b76; - text-transform: uppercase; - outline: none; -} diff --git a/examples/clusters/index.html b/examples/clusters/index.html index 7ccf392a..89f2a3b8 100644 --- a/examples/clusters/index.html +++ b/examples/clusters/index.html @@ -3,7 +3,32 @@ react-map-gl Example - + +
diff --git a/examples/clusters/package.json b/examples/clusters/package.json index 0ae73b96..59cbf0c5 100644 --- a/examples/clusters/package.json +++ b/examples/clusters/package.json @@ -1,21 +1,23 @@ { "scripts": { "start": "webpack-dev-server --progress --hot --open", - "start-local": "webpack-dev-server --env.local --progress --hot --open" + "start-local": "webpack-dev-server --env local --progress --hot --open" }, "dependencies": { - "react": "^16.3.0", - "react-dom": "^16.3.0", - "react-map-gl": "^6.0.0" + "react": "^17.0.0", + "react-dom": "^17.0.0", + "react-map-gl": "^7.0.0", + "mapbox-gl": "^2.0.0" }, "devDependencies": { "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.0", - "webpack": "^4.20.0", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.0" + "ts-loader": "^9.0.0", + "typescript": "^4.0.0", + "webpack": "^5.65.0", + "webpack-cli": "^4.9.0", + "webpack-dev-server": "^4.7.0" } } diff --git a/examples/clusters/src/app.js b/examples/clusters/src/app.tsx similarity index 64% rename from examples/clusters/src/app.js rename to examples/clusters/src/app.tsx index 7f75c23c..aa1368c3 100644 --- a/examples/clusters/src/app.js +++ b/examples/clusters/src/app.tsx @@ -1,53 +1,49 @@ import * as React from 'react'; -import {useState, useRef} from 'react'; +import {useRef} from 'react'; import {render} from 'react-dom'; -import MapGL, {Source, Layer} from 'react-map-gl'; +import {Map, Source, Layer} from 'react-map-gl'; import ControlPanel from './control-panel'; import {clusterLayer, clusterCountLayer, unclusteredPointLayer} from './layers'; +import type {MapRef} from 'react-map-gl'; +import type {GeoJSONSource} from 'react-map-gl'; + const MAPBOX_TOKEN = ''; // Set your mapbox token here export default function App() { - const [viewport, setViewport] = useState({ - latitude: 40.67, - longitude: -103.59, - zoom: 3, - bearing: 0, - pitch: 0 - }); - const mapRef = useRef(null); + const mapRef = useRef(null); const onClick = event => { const feature = event.features[0]; const clusterId = feature.properties.cluster_id; - const mapboxSource = mapRef.current.getMap().getSource('earthquakes'); + const map = mapRef.current.getMap(); + const mapboxSource = map.getSource('earthquakes') as GeoJSONSource; mapboxSource.getClusterExpansionZoom(clusterId, (err, zoom) => { if (err) { return; } - setViewport({ - ...viewport, - longitude: feature.geometry.coordinates[0], - latitude: feature.geometry.coordinates[1], + map.easeTo({ + center: feature.geometry.coordinates, zoom, - transitionDuration: 500 + duration: 500 }); }); }; return ( <> - - + ); diff --git a/examples/clusters/src/control-panel.js b/examples/clusters/src/control-panel.tsx similarity index 100% rename from examples/clusters/src/control-panel.js rename to examples/clusters/src/control-panel.tsx diff --git a/examples/clusters/src/layers.js b/examples/clusters/src/layers.ts similarity index 80% rename from examples/clusters/src/layers.js rename to examples/clusters/src/layers.ts index e13b3c2c..b4c060aa 100644 --- a/examples/clusters/src/layers.js +++ b/examples/clusters/src/layers.ts @@ -1,4 +1,6 @@ -export const clusterLayer = { +import type {LayerProps} from 'react-map-gl'; + +export const clusterLayer: LayerProps = { id: 'clusters', type: 'circle', source: 'earthquakes', @@ -9,7 +11,7 @@ export const clusterLayer = { } }; -export const clusterCountLayer = { +export const clusterCountLayer: LayerProps = { id: 'cluster-count', type: 'symbol', source: 'earthquakes', @@ -21,7 +23,7 @@ export const clusterCountLayer = { } }; -export const unclusteredPointLayer = { +export const unclusteredPointLayer: LayerProps = { id: 'unclustered-point', type: 'circle', source: 'earthquakes', diff --git a/examples/clusters/tsconfig.json b/examples/clusters/tsconfig.json new file mode 100644 index 00000000..ff49de04 --- /dev/null +++ b/examples/clusters/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2020", + "jsx": "react", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "sourceMap": true + } +} \ No newline at end of file diff --git a/examples/clusters/webpack.config.js b/examples/clusters/webpack.config.js index 78fe2a6a..ed4df0d5 100644 --- a/examples/clusters/webpack.config.js +++ b/examples/clusters/webpack.config.js @@ -5,33 +5,40 @@ const resolve = require('path').resolve; const webpack = require('webpack'); -const BABEL_CONFIG = { - presets: ['@babel/env', '@babel/react'], - plugins: ['@babel/proposal-class-properties'] -}; - const config = { mode: 'development', + devServer: { + static: '.' + }, + entry: { - app: resolve('./src/app.js') + app: resolve('./src/app') }, output: { library: 'App' }, + resolve: { + extensions: ['.ts', '.tsx', '.js', '.json'] + }, + module: { rules: [ { - // Compile ES2015 using babel - test: /\.js$/, + test: /\.(ts|js)x?$/, include: [resolve('.')], exclude: [/node_modules/], use: [ { loader: 'babel-loader', - options: BABEL_CONFIG + options: { + presets: ['@babel/env', '@babel/react'] + } + }, + { + loader: 'ts-loader' } ] } @@ -39,7 +46,7 @@ const config = { }, // Optional: Enables reading mapbox token from environment variable - plugins: [new webpack.EnvironmentPlugin(['MapboxAccessToken'])] + plugins: [new webpack.EnvironmentPlugin({MapboxAccessToken: ''})] }; // Enables bundling against src in this repo rather than the installed version diff --git a/examples/controls/src/pin.tsx b/examples/controls/src/pin.tsx index 50970dde..f315a2d4 100644 --- a/examples/controls/src/pin.tsx +++ b/examples/controls/src/pin.tsx @@ -1,22 +1,23 @@ import * as React from 'react'; -export default function Pin({onClick}) { - return ( - - + C20.1,15.8,20.2,15.8,20.2,15.7z`; + +const pinStyle = { + cursor: 'pointer', + fill: '#d00', + stroke: 'none' +}; + +function Pin(props) { + const {size = 20} = props; + + return ( + + ); } + +export default React.memo(Pin); diff --git a/examples/custom-cursor/src/app.tsx b/examples/custom-cursor/src/app.tsx index fbb4a06a..06362bf8 100644 --- a/examples/custom-cursor/src/app.tsx +++ b/examples/custom-cursor/src/app.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import {useState, useCallback} from 'react'; import {render} from 'react-dom'; -import Map, {Style} from 'react-map-gl'; +import Map, {MapboxStyle} from 'react-map-gl'; import ControlPanel from './control-panel'; import MAP_STYLE from '../../map-style-basic-v8.json'; @@ -39,7 +39,7 @@ export default function App() { <> react-map-gl Example - + +
diff --git a/examples/draggable-markers/package.json b/examples/draggable-markers/package.json index 0ae73b96..ca74eb45 100644 --- a/examples/draggable-markers/package.json +++ b/examples/draggable-markers/package.json @@ -1,21 +1,23 @@ { "scripts": { "start": "webpack-dev-server --progress --hot --open", - "start-local": "webpack-dev-server --env.local --progress --hot --open" + "start-local": "webpack-dev-server --env local --progress --hot --open" }, "dependencies": { - "react": "^16.3.0", - "react-dom": "^16.3.0", - "react-map-gl": "^6.0.0" + "mapbox-gl": "^2.0.0", + "react": "^17.0.0", + "react-dom": "^17.0.0", + "react-map-gl": "^7.0.0" }, "devDependencies": { "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.0", - "webpack": "^4.20.0", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.0" + "ts-loader": "^9.0.0", + "typescript": "^4.0.0", + "webpack": "^5.65.0", + "webpack-cli": "^4.9.0", + "webpack-dev-server": "^4.7.0" } } diff --git a/examples/draggable-markers/src/app.js b/examples/draggable-markers/src/app.tsx similarity index 56% rename from examples/draggable-markers/src/app.js rename to examples/draggable-markers/src/app.tsx index 1d3d08cc..f8b24737 100644 --- a/examples/draggable-markers/src/app.js +++ b/examples/draggable-markers/src/app.tsx @@ -1,65 +1,56 @@ import * as React from 'react'; import {useState, useCallback} from 'react'; import {render} from 'react-dom'; -import MapGL, {Marker, NavigationControl} from 'react-map-gl'; +import Map, {Marker, NavigationControl} from 'react-map-gl'; import ControlPanel from './control-panel'; import Pin from './pin'; +import type {MarkerDragEvent, LngLat} from 'react-map-gl'; + const TOKEN = ''; // Set your mapbox token here -const navStyle = { - position: 'absolute', - top: 0, - left: 0, - padding: '10px' +const initialViewState = { + latitude: 40, + longitude: -100, + zoom: 3.5 }; export default function App() { - const [viewport, setViewport] = useState({ - latitude: 40, - longitude: -100, - zoom: 3.5, - bearing: 0, - pitch: 0 - }); const [marker, setMarker] = useState({ latitude: 40, longitude: -100 }); - const [events, logEvents] = useState({}); + const [events, logEvents] = useState>({}); - const onMarkerDragStart = useCallback(event => { + const onMarkerDragStart = useCallback((event: MarkerDragEvent) => { logEvents(_events => ({..._events, onDragStart: event.lngLat})); }, []); - const onMarkerDrag = useCallback(event => { + const onMarkerDrag = useCallback((event: MarkerDragEvent) => { logEvents(_events => ({..._events, onDrag: event.lngLat})); + + setMarker({ + longitude: event.lngLat.lng, + latitude: event.lngLat.lat + }); }, []); - const onMarkerDragEnd = useCallback(event => { + const onMarkerDragEnd = useCallback((event: MarkerDragEvent) => { logEvents(_events => ({..._events, onDragEnd: event.lngLat})); - setMarker({ - longitude: event.lngLat[0], - latitude: event.lngLat[1] - }); }, []); return ( <> - -
- -
-
+ + ); diff --git a/examples/draggable-markers/src/control-panel.js b/examples/draggable-markers/src/control-panel.tsx similarity index 77% rename from examples/draggable-markers/src/control-panel.js rename to examples/draggable-markers/src/control-panel.tsx index 651f3e7f..81bf1295 100644 --- a/examples/draggable-markers/src/control-panel.js +++ b/examples/draggable-markers/src/control-panel.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import type {LngLat} from 'react-map-gl'; const eventNames = ['onDragStart', 'onDrag', 'onDragEnd']; @@ -6,7 +7,7 @@ function round5(value) { return (Math.round(value * 1e5) / 1e5).toFixed(5); } -function ControlPanel(props) { +function ControlPanel(props: {events: Record}) { return (

Draggable Marker

@@ -17,7 +18,8 @@ function ControlPanel(props) { const lngLat = events[eventName]; return (
- {eventName}: {lngLat ? lngLat.map(round5).join(', ') : null} + {eventName}:{' '} + {lngLat ? `${round5(lngLat.lng)}, ${round5(lngLat.lat)}` : null}
); })} diff --git a/examples/draggable-markers/src/pin.js b/examples/draggable-markers/src/pin.tsx similarity index 100% rename from examples/draggable-markers/src/pin.js rename to examples/draggable-markers/src/pin.tsx diff --git a/examples/draggable-markers/tsconfig.json b/examples/draggable-markers/tsconfig.json new file mode 100644 index 00000000..ff49de04 --- /dev/null +++ b/examples/draggable-markers/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2020", + "jsx": "react", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "sourceMap": true + } +} \ No newline at end of file diff --git a/examples/draggable-markers/webpack.config.js b/examples/draggable-markers/webpack.config.js index 78fe2a6a..ed4df0d5 100644 --- a/examples/draggable-markers/webpack.config.js +++ b/examples/draggable-markers/webpack.config.js @@ -5,33 +5,40 @@ const resolve = require('path').resolve; const webpack = require('webpack'); -const BABEL_CONFIG = { - presets: ['@babel/env', '@babel/react'], - plugins: ['@babel/proposal-class-properties'] -}; - const config = { mode: 'development', + devServer: { + static: '.' + }, + entry: { - app: resolve('./src/app.js') + app: resolve('./src/app') }, output: { library: 'App' }, + resolve: { + extensions: ['.ts', '.tsx', '.js', '.json'] + }, + module: { rules: [ { - // Compile ES2015 using babel - test: /\.js$/, + test: /\.(ts|js)x?$/, include: [resolve('.')], exclude: [/node_modules/], use: [ { loader: 'babel-loader', - options: BABEL_CONFIG + options: { + presets: ['@babel/env', '@babel/react'] + } + }, + { + loader: 'ts-loader' } ] } @@ -39,7 +46,7 @@ const config = { }, // Optional: Enables reading mapbox token from environment variable - plugins: [new webpack.EnvironmentPlugin(['MapboxAccessToken'])] + plugins: [new webpack.EnvironmentPlugin({MapboxAccessToken: ''})] }; // Enables bundling against src in this repo rather than the installed version diff --git a/examples/filter/app.css b/examples/filter/app.css deleted file mode 100644 index 27e3367c..00000000 --- a/examples/filter/app.css +++ /dev/null @@ -1,29 +0,0 @@ -body { - margin: 0; - font-family: Helvetica, Arial, sans-serif; -} -#map { - width: 100vw; - height: 100vh; -} - -.county-info { - font-size: 12px; - font-weight: 700; -} - -.control-panel { - position: absolute; - top: 0; - right: 0; - max-width: 320px; - background: #fff; - box-shadow: 0 2px 4px rgba(0,0,0,0.3); - padding: 12px 24px; - margin: 20px; - font-size: 13px; - line-height: 2; - color: #6b6b76; - text-transform: uppercase; - outline: none; -} diff --git a/examples/filter/index.html b/examples/filter/index.html index 7ccf392a..0455c88d 100644 --- a/examples/filter/index.html +++ b/examples/filter/index.html @@ -3,7 +3,38 @@ react-map-gl Example - + +
diff --git a/examples/filter/package.json b/examples/filter/package.json index 0ae73b96..ca74eb45 100644 --- a/examples/filter/package.json +++ b/examples/filter/package.json @@ -1,21 +1,23 @@ { "scripts": { "start": "webpack-dev-server --progress --hot --open", - "start-local": "webpack-dev-server --env.local --progress --hot --open" + "start-local": "webpack-dev-server --env local --progress --hot --open" }, "dependencies": { - "react": "^16.3.0", - "react-dom": "^16.3.0", - "react-map-gl": "^6.0.0" + "mapbox-gl": "^2.0.0", + "react": "^17.0.0", + "react-dom": "^17.0.0", + "react-map-gl": "^7.0.0" }, "devDependencies": { "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.0", - "webpack": "^4.20.0", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.0" + "ts-loader": "^9.0.0", + "typescript": "^4.0.0", + "webpack": "^5.65.0", + "webpack-cli": "^4.9.0", + "webpack-dev-server": "^4.7.0" } } diff --git a/examples/filter/src/app.js b/examples/filter/src/app.tsx similarity index 71% rename from examples/filter/src/app.js rename to examples/filter/src/app.tsx index f353e31f..1cc13510 100644 --- a/examples/filter/src/app.js +++ b/examples/filter/src/app.tsx @@ -1,29 +1,21 @@ import * as React from 'react'; import {useState, useMemo, useCallback} from 'react'; import {render} from 'react-dom'; -import MapGL, {Popup, Source, Layer} from 'react-map-gl'; +import Map, {Popup, Source, Layer} from 'react-map-gl'; import ControlPanel from './control-panel'; -import {countiesLayer, highlightLayer} from './map-style.js'; +import {countiesLayer, highlightLayer} from './map-style'; const MAPBOX_TOKEN = ''; // Set your mapbox token here export default function App() { - const [viewport, setViewport] = useState({ - latitude: 38.88, - longitude: -98, - zoom: 3, - minZoom: 2, - bearing: 0, - pitch: 0 - }); const [hoverInfo, setHoverInfo] = useState(null); const onHover = useCallback(event => { const county = event.features && event.features[0]; setHoverInfo({ - longitude: event.lngLat[0], - latitude: event.lngLat[1], + longitude: event.lngLat.lng, + latitude: event.lngLat.lat, countyName: county && county.properties.COUNTY }); }, []); @@ -33,14 +25,16 @@ export default function App() { return ( <> - @@ -51,13 +45,14 @@ export default function App() { {selectedCounty} )} - + ); diff --git a/examples/filter/src/control-panel.js b/examples/filter/src/control-panel.tsx similarity index 100% rename from examples/filter/src/control-panel.js rename to examples/filter/src/control-panel.tsx diff --git a/examples/filter/src/map-style.js b/examples/filter/src/map-style.ts similarity index 75% rename from examples/filter/src/map-style.js rename to examples/filter/src/map-style.ts index 4749f9fa..4a13db46 100644 --- a/examples/filter/src/map-style.js +++ b/examples/filter/src/map-style.ts @@ -1,4 +1,6 @@ -export const countiesLayer = { +import type {FillLayer} from 'react-map-gl'; + +export const countiesLayer: FillLayer = { id: 'counties', type: 'fill', 'source-layer': 'original', @@ -8,7 +10,7 @@ export const countiesLayer = { } }; // Highlighted county polygons -export const highlightLayer = { +export const highlightLayer: FillLayer = { id: 'counties-highlighted', type: 'fill', source: 'counties', diff --git a/examples/filter/tsconfig.json b/examples/filter/tsconfig.json new file mode 100644 index 00000000..ff49de04 --- /dev/null +++ b/examples/filter/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2020", + "jsx": "react", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "sourceMap": true + } +} \ No newline at end of file diff --git a/examples/filter/webpack.config.js b/examples/filter/webpack.config.js index 78fe2a6a..ed4df0d5 100644 --- a/examples/filter/webpack.config.js +++ b/examples/filter/webpack.config.js @@ -5,33 +5,40 @@ const resolve = require('path').resolve; const webpack = require('webpack'); -const BABEL_CONFIG = { - presets: ['@babel/env', '@babel/react'], - plugins: ['@babel/proposal-class-properties'] -}; - const config = { mode: 'development', + devServer: { + static: '.' + }, + entry: { - app: resolve('./src/app.js') + app: resolve('./src/app') }, output: { library: 'App' }, + resolve: { + extensions: ['.ts', '.tsx', '.js', '.json'] + }, + module: { rules: [ { - // Compile ES2015 using babel - test: /\.js$/, + test: /\.(ts|js)x?$/, include: [resolve('.')], exclude: [/node_modules/], use: [ { loader: 'babel-loader', - options: BABEL_CONFIG + options: { + presets: ['@babel/env', '@babel/react'] + } + }, + { + loader: 'ts-loader' } ] } @@ -39,7 +46,7 @@ const config = { }, // Optional: Enables reading mapbox token from environment variable - plugins: [new webpack.EnvironmentPlugin(['MapboxAccessToken'])] + plugins: [new webpack.EnvironmentPlugin({MapboxAccessToken: ''})] }; // Enables bundling against src in this repo rather than the installed version diff --git a/examples/geojson-animation/app.css b/examples/geojson-animation/app.css deleted file mode 100644 index 72db167a..00000000 --- a/examples/geojson-animation/app.css +++ /dev/null @@ -1,24 +0,0 @@ -body { - margin: 0; - background: #000; -} -#map { - width: 100vw; - height: 100vh; -} - -.control-panel { - position: absolute; - top: 0; - right: 0; - max-width: 320px; - background: #fff; - box-shadow: 0 2px 4px rgba(0,0,0,0.3); - padding: 12px 24px; - margin: 20px; - font-size: 13px; - line-height: 2; - color: #6b6b76; - text-transform: uppercase; - outline: none; -} diff --git a/examples/geojson-animation/index.html b/examples/geojson-animation/index.html index 7ccf392a..89f2a3b8 100644 --- a/examples/geojson-animation/index.html +++ b/examples/geojson-animation/index.html @@ -3,7 +3,32 @@ react-map-gl Example - + +
diff --git a/examples/geojson-animation/package.json b/examples/geojson-animation/package.json index 0ae73b96..59cbf0c5 100644 --- a/examples/geojson-animation/package.json +++ b/examples/geojson-animation/package.json @@ -1,21 +1,23 @@ { "scripts": { "start": "webpack-dev-server --progress --hot --open", - "start-local": "webpack-dev-server --env.local --progress --hot --open" + "start-local": "webpack-dev-server --env local --progress --hot --open" }, "dependencies": { - "react": "^16.3.0", - "react-dom": "^16.3.0", - "react-map-gl": "^6.0.0" + "react": "^17.0.0", + "react-dom": "^17.0.0", + "react-map-gl": "^7.0.0", + "mapbox-gl": "^2.0.0" }, "devDependencies": { "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.0", - "webpack": "^4.20.0", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.0" + "ts-loader": "^9.0.0", + "typescript": "^4.0.0", + "webpack": "^5.65.0", + "webpack-cli": "^4.9.0", + "webpack-dev-server": "^4.7.0" } } diff --git a/examples/geojson-animation/src/app.js b/examples/geojson-animation/src/app.tsx similarity index 75% rename from examples/geojson-animation/src/app.js rename to examples/geojson-animation/src/app.tsx index d24e06e4..c3cbdc27 100644 --- a/examples/geojson-animation/src/app.js +++ b/examples/geojson-animation/src/app.tsx @@ -2,13 +2,14 @@ import * as React from 'react'; import {useState, useEffect} from 'react'; import {render} from 'react-dom'; -import MapGL, {Source, Layer} from 'react-map-gl'; +import {Map, Source, Layer} from 'react-map-gl'; +import type {LayerProps} from 'react-map-gl'; import ControlPanel from './control-panel'; const MAPBOX_TOKEN = ''; // Set your mapbox token here -const pointLayer = { +const pointLayer: LayerProps = { type: 'circle', paint: { 'circle-radius': 10, @@ -24,13 +25,6 @@ function pointOnCircle({center, angle, radius}) { } export default function App() { - const [viewport, setViewport] = useState({ - latitude: 0, - longitude: -100, - zoom: 3, - bearing: 0, - pitch: 0 - }); const [pointData, setPointData] = useState(null); useEffect(() => { @@ -42,20 +36,21 @@ export default function App() { return ( <> - {pointData && ( )} - + ); diff --git a/examples/geojson-animation/src/control-panel.js b/examples/geojson-animation/src/control-panel.tsx similarity index 100% rename from examples/geojson-animation/src/control-panel.js rename to examples/geojson-animation/src/control-panel.tsx diff --git a/examples/geojson-animation/tsconfig.json b/examples/geojson-animation/tsconfig.json new file mode 100644 index 00000000..ff49de04 --- /dev/null +++ b/examples/geojson-animation/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2020", + "jsx": "react", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "sourceMap": true + } +} \ No newline at end of file diff --git a/examples/geojson-animation/webpack.config.js b/examples/geojson-animation/webpack.config.js index 78fe2a6a..ed4df0d5 100644 --- a/examples/geojson-animation/webpack.config.js +++ b/examples/geojson-animation/webpack.config.js @@ -5,33 +5,40 @@ const resolve = require('path').resolve; const webpack = require('webpack'); -const BABEL_CONFIG = { - presets: ['@babel/env', '@babel/react'], - plugins: ['@babel/proposal-class-properties'] -}; - const config = { mode: 'development', + devServer: { + static: '.' + }, + entry: { - app: resolve('./src/app.js') + app: resolve('./src/app') }, output: { library: 'App' }, + resolve: { + extensions: ['.ts', '.tsx', '.js', '.json'] + }, + module: { rules: [ { - // Compile ES2015 using babel - test: /\.js$/, + test: /\.(ts|js)x?$/, include: [resolve('.')], exclude: [/node_modules/], use: [ { loader: 'babel-loader', - options: BABEL_CONFIG + options: { + presets: ['@babel/env', '@babel/react'] + } + }, + { + loader: 'ts-loader' } ] } @@ -39,7 +46,7 @@ const config = { }, // Optional: Enables reading mapbox token from environment variable - plugins: [new webpack.EnvironmentPlugin(['MapboxAccessToken'])] + plugins: [new webpack.EnvironmentPlugin({MapboxAccessToken: ''})] }; // Enables bundling against src in this repo rather than the installed version diff --git a/examples/geojson/app.css b/examples/geojson/app.css deleted file mode 100644 index 86e21888..00000000 --- a/examples/geojson/app.css +++ /dev/null @@ -1,46 +0,0 @@ -body { - margin: 0; - font-family: Helvetica, Arial, sans-serif; -} -#map { - width: 100vw; - height: 100vh; -} - -.control-panel { - position: absolute; - top: 0; - right: 0; - max-width: 320px; - background: #fff; - box-shadow: 0 2px 4px rgba(0,0,0,0.3); - padding: 12px 24px; - margin: 20px; - font-size: 13px; - line-height: 2; - color: #6b6b76; - outline: none; - text-transform: uppercase; -} - -label { - display: inline-block; - width: 100px; -} - -input { - margin-left: 20px; - width: 160px; -} - -.tooltip { - position: absolute; - margin: 8px; - padding: 4px; - background: rgba(0, 0, 0, 0.8); - color: #fff; - max-width: 300px; - font-size: 10px; - z-index: 9; - pointer-events: none; -} diff --git a/examples/geojson/index.html b/examples/geojson/index.html index 7ccf392a..0b75dc1a 100644 --- a/examples/geojson/index.html +++ b/examples/geojson/index.html @@ -3,7 +3,55 @@ react-map-gl Example - + +
diff --git a/examples/geojson/package.json b/examples/geojson/package.json index e1cafa41..e11ee9c5 100644 --- a/examples/geojson/package.json +++ b/examples/geojson/package.json @@ -1,22 +1,25 @@ { "scripts": { "start": "webpack-dev-server --progress --hot --open", - "start-local": "webpack-dev-server --env.local --progress --hot --open" + "start-local": "webpack-dev-server --env local --progress --hot --open" }, "dependencies": { - "d3-scale": "^1.0.6", - "react": "^16.3.0", - "react-dom": "^16.3.0", - "react-map-gl": "^6.0.0" + "d3-array": "^3.1.1", + "d3-scale": "^4.0.2", + "mapbox-gl": "^2.0.0", + "react": "^17.0.0", + "react-dom": "^17.0.0", + "react-map-gl": "^7.0.0" }, "devDependencies": { "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.0", - "webpack": "^4.20.0", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.0" + "ts-loader": "^9.0.0", + "typescript": "^4.0.0", + "webpack": "^5.65.0", + "webpack-cli": "^4.9.0", + "webpack-dev-server": "^4.7.0" } } diff --git a/examples/geojson/src/app.js b/examples/geojson/src/app.tsx similarity index 78% rename from examples/geojson/src/app.js rename to examples/geojson/src/app.tsx index 4e97e242..dfceeb29 100644 --- a/examples/geojson/src/app.js +++ b/examples/geojson/src/app.tsx @@ -1,22 +1,15 @@ import * as React from 'react'; import {useState, useEffect, useMemo, useCallback} from 'react'; import {render} from 'react-dom'; -import MapGL, {Source, Layer} from 'react-map-gl'; +import Map, {Source, Layer} from 'react-map-gl'; import ControlPanel from './control-panel'; -import {dataLayer} from './map-style.js'; +import {dataLayer} from './map-style'; import {updatePercentiles} from './utils'; const MAPBOX_TOKEN = ''; // Set your mapbox token here export default function App() { - const [viewport, setViewport] = useState({ - latitude: 40, - longitude: -100, - zoom: 3, - bearing: 0, - pitch: 0 - }); const [year, setYear] = useState(2015); const [allData, setAllData] = useState(null); const [hoverInfo, setHoverInfo] = useState(null); @@ -33,7 +26,7 @@ export default function App() { const onHover = useCallback(event => { const { features, - srcEvent: {offsetX, offsetY} + point: {x, y} } = event; const hoveredFeature = features && features[0]; @@ -41,8 +34,8 @@ export default function App() { hoveredFeature ? { feature: hoveredFeature, - x: offsetX, - y: offsetY + x, + y } : null ); @@ -54,15 +47,16 @@ export default function App() { return ( <> - @@ -74,7 +68,7 @@ export default function App() {
Percentile: {(hoverInfo.feature.properties.percentile / 8) * 100}
)} - + setYear(value)} /> diff --git a/examples/geojson/src/control-panel.js b/examples/geojson/src/control-panel.tsx similarity index 100% rename from examples/geojson/src/control-panel.js rename to examples/geojson/src/control-panel.tsx diff --git a/examples/geojson/src/map-style.js b/examples/geojson/src/map-style.ts similarity index 84% rename from examples/geojson/src/map-style.js rename to examples/geojson/src/map-style.ts index 9fda04a6..c0976799 100644 --- a/examples/geojson/src/map-style.js +++ b/examples/geojson/src/map-style.ts @@ -1,5 +1,7 @@ +import type {FillLayer} from 'react-map-gl'; + // For more information on data-driven styles, see https://www.mapbox.com/help/gl-dds-ref/ -export const dataLayer = { +export const dataLayer: FillLayer = { id: 'data', type: 'fill', paint: { diff --git a/examples/geojson/src/utils.js b/examples/geojson/src/utils.ts similarity index 65% rename from examples/geojson/src/utils.js rename to examples/geojson/src/utils.ts index fafdd228..88d6a170 100644 --- a/examples/geojson/src/utils.js +++ b/examples/geojson/src/utils.ts @@ -1,7 +1,12 @@ import {range} from 'd3-array'; import {scaleQuantile} from 'd3-scale'; -export function updatePercentiles(featureCollection, accessor) { +import type GeoJSON from 'geojson'; + +export function updatePercentiles( + featureCollection: GeoJSON.FeatureCollection, + accessor: (f: GeoJSON.Feature) => number +): GeoJSON.FeatureCollection { const {features} = featureCollection; const scale = scaleQuantile().domain(features.map(accessor)).range(range(9)); return { diff --git a/examples/geojson/tsconfig.json b/examples/geojson/tsconfig.json new file mode 100644 index 00000000..ff49de04 --- /dev/null +++ b/examples/geojson/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2020", + "jsx": "react", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "sourceMap": true + } +} \ No newline at end of file diff --git a/examples/geojson/webpack.config.js b/examples/geojson/webpack.config.js index 78fe2a6a..ed4df0d5 100644 --- a/examples/geojson/webpack.config.js +++ b/examples/geojson/webpack.config.js @@ -5,33 +5,40 @@ const resolve = require('path').resolve; const webpack = require('webpack'); -const BABEL_CONFIG = { - presets: ['@babel/env', '@babel/react'], - plugins: ['@babel/proposal-class-properties'] -}; - const config = { mode: 'development', + devServer: { + static: '.' + }, + entry: { - app: resolve('./src/app.js') + app: resolve('./src/app') }, output: { library: 'App' }, + resolve: { + extensions: ['.ts', '.tsx', '.js', '.json'] + }, + module: { rules: [ { - // Compile ES2015 using babel - test: /\.js$/, + test: /\.(ts|js)x?$/, include: [resolve('.')], exclude: [/node_modules/], use: [ { loader: 'babel-loader', - options: BABEL_CONFIG + options: { + presets: ['@babel/env', '@babel/react'] + } + }, + { + loader: 'ts-loader' } ] } @@ -39,7 +46,7 @@ const config = { }, // Optional: Enables reading mapbox token from environment variable - plugins: [new webpack.EnvironmentPlugin(['MapboxAccessToken'])] + plugins: [new webpack.EnvironmentPlugin({MapboxAccessToken: ''})] }; // Enables bundling against src in this repo rather than the installed version diff --git a/examples/heatmap/app.css b/examples/heatmap/app.css deleted file mode 100644 index e6341e77..00000000 --- a/examples/heatmap/app.css +++ /dev/null @@ -1,38 +0,0 @@ -body { - margin: 0; - font-family: Helvetica, Arial, sans-serif; -} -#map { - width: 100vw; - height: 100vh; -} - -.control-panel { - position: absolute; - top: 0; - right: 0; - max-width: 320px; - background: #fff; - box-shadow: 0 2px 4px rgba(0,0,0,0.3); - padding: 12px 24px; - margin: 20px; - font-size: 13px; - line-height: 2; - color: #6b6b76; - outline: none; - text-transform: uppercase; -} - -label { - display: inline-block; - width: 150px; -} - -input { - margin-left: 20px; -} - -.input.disabled { - opacity: .5; - cursor: not-allowed; -} \ No newline at end of file diff --git a/examples/heatmap/index.html b/examples/heatmap/index.html index 7ccf392a..6441d8c0 100644 --- a/examples/heatmap/index.html +++ b/examples/heatmap/index.html @@ -3,7 +3,46 @@ react-map-gl Example - + +
diff --git a/examples/heatmap/package.json b/examples/heatmap/package.json index 0ae73b96..59cbf0c5 100644 --- a/examples/heatmap/package.json +++ b/examples/heatmap/package.json @@ -1,21 +1,23 @@ { "scripts": { "start": "webpack-dev-server --progress --hot --open", - "start-local": "webpack-dev-server --env.local --progress --hot --open" + "start-local": "webpack-dev-server --env local --progress --hot --open" }, "dependencies": { - "react": "^16.3.0", - "react-dom": "^16.3.0", - "react-map-gl": "^6.0.0" + "react": "^17.0.0", + "react-dom": "^17.0.0", + "react-map-gl": "^7.0.0", + "mapbox-gl": "^2.0.0" }, "devDependencies": { "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.0", - "webpack": "^4.20.0", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.0" + "ts-loader": "^9.0.0", + "typescript": "^4.0.0", + "webpack": "^5.65.0", + "webpack-cli": "^4.9.0", + "webpack-dev-server": "^4.7.0" } } diff --git a/examples/heatmap/src/app.js b/examples/heatmap/src/app.tsx similarity index 89% rename from examples/heatmap/src/app.js rename to examples/heatmap/src/app.tsx index e6d25eec..7deb8d22 100644 --- a/examples/heatmap/src/app.js +++ b/examples/heatmap/src/app.tsx @@ -24,13 +24,6 @@ function filterFeaturesByDay(featureCollection, time) { } export default function App() { - const [viewport, setViewport] = useState({ - latitude: 40, - longitude: -100, - zoom: 3, - bearing: 0, - pitch: 0 - }); const [allDays, useAllDays] = useState(true); const [timeRange, setTimeRange] = useState([0, 0]); const [selectedTime, selectTime] = useState(0); @@ -60,12 +53,13 @@ export default function App() { return ( <> {data && ( diff --git a/examples/heatmap/src/control-panel.js b/examples/heatmap/src/control-panel.tsx similarity index 100% rename from examples/heatmap/src/control-panel.js rename to examples/heatmap/src/control-panel.tsx diff --git a/examples/heatmap/src/map-style.js b/examples/heatmap/src/map-style.ts similarity index 91% rename from examples/heatmap/src/map-style.js rename to examples/heatmap/src/map-style.ts index 01a3325a..0e8dfad8 100644 --- a/examples/heatmap/src/map-style.js +++ b/examples/heatmap/src/map-style.ts @@ -1,6 +1,9 @@ +import type {HeatmapLayer} from 'react-map-gl'; + const MAX_ZOOM_LEVEL = 9; -export const heatmapLayer = { +export const heatmapLayer: HeatmapLayer = { + id: 'heatmap', maxzoom: MAX_ZOOM_LEVEL, type: 'heatmap', paint: { diff --git a/examples/heatmap/tsconfig.json b/examples/heatmap/tsconfig.json new file mode 100644 index 00000000..ff49de04 --- /dev/null +++ b/examples/heatmap/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2020", + "jsx": "react", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "sourceMap": true + } +} \ No newline at end of file diff --git a/examples/heatmap/webpack.config.js b/examples/heatmap/webpack.config.js index 78fe2a6a..ed4df0d5 100644 --- a/examples/heatmap/webpack.config.js +++ b/examples/heatmap/webpack.config.js @@ -5,33 +5,40 @@ const resolve = require('path').resolve; const webpack = require('webpack'); -const BABEL_CONFIG = { - presets: ['@babel/env', '@babel/react'], - plugins: ['@babel/proposal-class-properties'] -}; - const config = { mode: 'development', + devServer: { + static: '.' + }, + entry: { - app: resolve('./src/app.js') + app: resolve('./src/app') }, output: { library: 'App' }, + resolve: { + extensions: ['.ts', '.tsx', '.js', '.json'] + }, + module: { rules: [ { - // Compile ES2015 using babel - test: /\.js$/, + test: /\.(ts|js)x?$/, include: [resolve('.')], exclude: [/node_modules/], use: [ { loader: 'babel-loader', - options: BABEL_CONFIG + options: { + presets: ['@babel/env', '@babel/react'] + } + }, + { + loader: 'ts-loader' } ] } @@ -39,7 +46,7 @@ const config = { }, // Optional: Enables reading mapbox token from environment variable - plugins: [new webpack.EnvironmentPlugin(['MapboxAccessToken'])] + plugins: [new webpack.EnvironmentPlugin({MapboxAccessToken: ''})] }; // Enables bundling against src in this repo rather than the installed version diff --git a/examples/layers/app.css b/examples/layers/app.css deleted file mode 100644 index e3035e8c..00000000 --- a/examples/layers/app.css +++ /dev/null @@ -1,33 +0,0 @@ -body { - margin: 0; - font-family: Helvetica, Arial, sans-serif; -} -#map { - width: 100vw; - height: 100vh; -} - -.control-panel { - position: absolute; - top: 0; - right: 0; - max-width: 320px; - background: #fff; - box-shadow: 0 2px 4px rgba(0,0,0,0.3); - padding: 12px 24px; - margin: 20px; - font-size: 13px; - line-height: 2; - color: #6b6b76; - text-transform: uppercase; - outline: none; -} - -label { - display: inline-block; - width: 100px; -} - -input { - margin-left: 20px; -} diff --git a/examples/layers/index.html b/examples/layers/index.html index 7ccf392a..e28e7000 100644 --- a/examples/layers/index.html +++ b/examples/layers/index.html @@ -3,7 +3,41 @@ react-map-gl Example - + +
diff --git a/examples/layers/package.json b/examples/layers/package.json index c40381b8..1e36d11b 100644 --- a/examples/layers/package.json +++ b/examples/layers/package.json @@ -1,22 +1,24 @@ { "scripts": { "start": "webpack-dev-server --progress --hot --open", - "start-local": "webpack-dev-server --env.local --progress --hot --open" + "start-local": "webpack-dev-server --env local --progress --hot --open" }, "dependencies": { - "immutable": "^3.8.1", - "react": "^16.3.0", - "react-dom": "^16.3.0", - "react-map-gl": "^6.0.0" + "immutable": "^4.0.0", + "mapbox-gl": "^2.0.0", + "react": "^17.0.0", + "react-dom": "^17.0.0", + "react-map-gl": "^7.0.0" }, "devDependencies": { "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.0", - "webpack": "^4.20.0", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.0" + "ts-loader": "^9.0.0", + "typescript": "^4.0.0", + "webpack": "^5.65.0", + "webpack-cli": "^4.9.0", + "webpack-dev-server": "^4.7.0" } } diff --git a/examples/layers/src/app.js b/examples/layers/src/app.js deleted file mode 100644 index 44d8dfcd..00000000 --- a/examples/layers/src/app.js +++ /dev/null @@ -1,37 +0,0 @@ -import * as React from 'react'; -import {useState} from 'react'; -import {render} from 'react-dom'; -import MapGL from 'react-map-gl'; -import ControlPanel from './control-panel'; - -const MAPBOX_TOKEN = ''; // Set your mapbox token here - -export default function App() { - const [viewport, setViewport] = useState({ - latitude: 37.805, - longitude: -122.447, - zoom: 15.5, - bearing: 0, - pitch: 0 - }); - const [mapStyle, setMapStyle] = useState(''); - - return ( - <> - - - - - ); -} - -export function renderToDom(container) { - render(, container); -} diff --git a/examples/layers/src/app.tsx b/examples/layers/src/app.tsx new file mode 100644 index 00000000..63eb27cd --- /dev/null +++ b/examples/layers/src/app.tsx @@ -0,0 +1,32 @@ +import * as React from 'react'; +import {useState} from 'react'; +import {render} from 'react-dom'; +import Map from 'react-map-gl'; +import ControlPanel from './control-panel'; + +const MAPBOX_TOKEN = ''; // Set your mapbox token here + +export default function App() { + const [mapStyle, setMapStyle] = useState(null); + + return ( + <> + + + + + ); +} + +export function renderToDom(container) { + render(, container); +} diff --git a/examples/layers/src/control-panel.js b/examples/layers/src/control-panel.tsx similarity index 98% rename from examples/layers/src/control-panel.js rename to examples/layers/src/control-panel.tsx index 85a772f9..417fc4fa 100644 --- a/examples/layers/src/control-panel.js +++ b/examples/layers/src/control-panel.tsx @@ -3,7 +3,7 @@ import {useState, useEffect} from 'react'; import {fromJS} from 'immutable'; import MAP_STYLE from '../../map-style-basic-v8.json'; -const defaultMapStyle = fromJS(MAP_STYLE); +const defaultMapStyle: any = fromJS(MAP_STYLE); const defaultLayers = defaultMapStyle.get('layers'); const categories = ['labels', 'roads', 'buildings', 'parks', 'water', 'background']; diff --git a/examples/layers/tsconfig.json b/examples/layers/tsconfig.json new file mode 100644 index 00000000..ff49de04 --- /dev/null +++ b/examples/layers/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2020", + "jsx": "react", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "sourceMap": true + } +} \ No newline at end of file diff --git a/examples/layers/webpack.config.js b/examples/layers/webpack.config.js index 78fe2a6a..ed4df0d5 100644 --- a/examples/layers/webpack.config.js +++ b/examples/layers/webpack.config.js @@ -5,33 +5,40 @@ const resolve = require('path').resolve; const webpack = require('webpack'); -const BABEL_CONFIG = { - presets: ['@babel/env', '@babel/react'], - plugins: ['@babel/proposal-class-properties'] -}; - const config = { mode: 'development', + devServer: { + static: '.' + }, + entry: { - app: resolve('./src/app.js') + app: resolve('./src/app') }, output: { library: 'App' }, + resolve: { + extensions: ['.ts', '.tsx', '.js', '.json'] + }, + module: { rules: [ { - // Compile ES2015 using babel - test: /\.js$/, + test: /\.(ts|js)x?$/, include: [resolve('.')], exclude: [/node_modules/], use: [ { loader: 'babel-loader', - options: BABEL_CONFIG + options: { + presets: ['@babel/env', '@babel/react'] + } + }, + { + loader: 'ts-loader' } ] } @@ -39,7 +46,7 @@ const config = { }, // Optional: Enables reading mapbox token from environment variable - plugins: [new webpack.EnvironmentPlugin(['MapboxAccessToken'])] + plugins: [new webpack.EnvironmentPlugin({MapboxAccessToken: ''})] }; // Enables bundling against src in this repo rather than the installed version diff --git a/examples/locate-user/README.md b/examples/locate-user/README.md deleted file mode 100644 index 8a2fda34..00000000 --- a/examples/locate-user/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Example: Locate User - -Demonstrates how to automatically locate the user and track their current location with react-map-gl. - -## Usage - -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. - -```bash -npm i -npm run start -``` diff --git a/examples/locate-user/app.css b/examples/locate-user/app.css deleted file mode 100644 index f793592b..00000000 --- a/examples/locate-user/app.css +++ /dev/null @@ -1,8 +0,0 @@ -body { - margin: 0; - font-family: Helvetica, Arial, sans-serif; -} -#map { - width: 100vw; - height: 100vh; -} diff --git a/examples/locate-user/index.html b/examples/locate-user/index.html deleted file mode 100644 index f1e0df0c..00000000 --- a/examples/locate-user/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - react-map-gl Example - - - -
- - - - diff --git a/examples/locate-user/package.json b/examples/locate-user/package.json deleted file mode 100644 index c40381b8..00000000 --- a/examples/locate-user/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "scripts": { - "start": "webpack-dev-server --progress --hot --open", - "start-local": "webpack-dev-server --env.local --progress --hot --open" - }, - "dependencies": { - "immutable": "^3.8.1", - "react": "^16.3.0", - "react-dom": "^16.3.0", - "react-map-gl": "^6.0.0" - }, - "devDependencies": { - "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/preset-env": "^7.0.0", - "@babel/preset-react": "^7.0.0", - "babel-loader": "^8.0.0", - "webpack": "^4.20.0", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.0" - } -} diff --git a/examples/locate-user/src/app.js b/examples/locate-user/src/app.js deleted file mode 100644 index 0e20e0df..00000000 --- a/examples/locate-user/src/app.js +++ /dev/null @@ -1,45 +0,0 @@ -import * as React from 'react'; -import {useState} from 'react'; -import {render} from 'react-dom'; -import MapGL, {GeolocateControl} from 'react-map-gl'; - -const MAPBOX_TOKEN = ''; // Set your mapbox token here - -const geolocateStyle = { - top: 0, - left: 0, - margin: 10 -}; -const positionOptions = {enableHighAccuracy: true}; - -export default function App() { - const [viewport, setViewport] = useState({ - latitude: 37.8, - longitude: 96, - zoom: 3, - bearing: 0, - pitch: 0 - }); - - return ( - - - - ); -} - -export function renderToDom(container) { - render(, container); -} diff --git a/examples/locate-user/webpack.config.js b/examples/locate-user/webpack.config.js deleted file mode 100644 index 78fe2a6a..00000000 --- a/examples/locate-user/webpack.config.js +++ /dev/null @@ -1,47 +0,0 @@ -// NOTE: To use this example standalone (e.g. outside of repo) -// delete the local development overrides at the bottom of this file - -// avoid destructuring for older Node version support -const resolve = require('path').resolve; -const webpack = require('webpack'); - -const BABEL_CONFIG = { - presets: ['@babel/env', '@babel/react'], - plugins: ['@babel/proposal-class-properties'] -}; - -const config = { - mode: 'development', - - entry: { - app: resolve('./src/app.js') - }, - - output: { - library: 'App' - }, - - module: { - rules: [ - { - // Compile ES2015 using babel - test: /\.js$/, - include: [resolve('.')], - exclude: [/node_modules/], - use: [ - { - loader: 'babel-loader', - options: BABEL_CONFIG - } - ] - } - ] - }, - - // Optional: Enables reading mapbox token from environment variable - plugins: [new webpack.EnvironmentPlugin(['MapboxAccessToken'])] -}; - -// Enables bundling against src in this repo rather than the installed version -module.exports = env => - env && env.local ? require('../webpack.config.local')(config)(env) : config; diff --git a/examples/terrain/app.css b/examples/terrain/app.css deleted file mode 100644 index 2d44013b..00000000 --- a/examples/terrain/app.css +++ /dev/null @@ -1,24 +0,0 @@ -body { - margin: 0; - background: #000; -} -#map { - width: 100vw; - height: 100vh; -} - -.control-panel { - position: absolute; - top: 0; - right: 0; - max-width: 320px; - background: #fff; - box-shadow: 0 2px 4px rgba(0,0,0,0.3); - padding: 12px 24px; - margin: 20px; - font-size: 13px; - line-height: 2; - color: #6b6b76; - text-transform: uppercase; - outline: none; -} \ No newline at end of file diff --git a/examples/terrain/index.html b/examples/terrain/index.html index 7ccf392a..4e672b39 100644 --- a/examples/terrain/index.html +++ b/examples/terrain/index.html @@ -3,7 +3,33 @@ react-map-gl Example - + +
diff --git a/examples/terrain/package.json b/examples/terrain/package.json index aead06ce..0340a561 100644 --- a/examples/terrain/package.json +++ b/examples/terrain/package.json @@ -1,21 +1,24 @@ { "scripts": { "start": "webpack-dev-server --progress --hot --open", - "start-local": "webpack-dev-server --env.local --progress --hot --open" + "start-local": "webpack-dev-server --env local --progress --hot --open" }, "dependencies": { - "react": "^16.3.0", - "react-dom": "^16.3.0", - "react-map-gl": "^6.1.0" + "@turf/bbox": "^6.5.0", + "mapbox-gl": "^2.0.0", + "react": "^17.0.0", + "react-dom": "^17.0.0", + "react-map-gl": "^7.0.0" }, "devDependencies": { "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.0", - "webpack": "^4.20.0", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.0" + "ts-loader": "^9.0.0", + "typescript": "^4.0.0", + "webpack": "^5.65.0", + "webpack-cli": "^4.9.0", + "webpack-dev-server": "^4.7.0" } } diff --git a/examples/terrain/src/app.js b/examples/terrain/src/app.tsx similarity index 68% rename from examples/terrain/src/app.js rename to examples/terrain/src/app.tsx index f1ff7c62..d7e77c30 100644 --- a/examples/terrain/src/app.js +++ b/examples/terrain/src/app.tsx @@ -1,13 +1,15 @@ import * as React from 'react'; -import {useState, useCallback} from 'react'; +import {useCallback} from 'react'; import {render} from 'react-dom'; -import MapGL, {Source, Layer} from 'react-map-gl'; +import Map, {Source, Layer} from 'react-map-gl'; import ControlPanel from './control-panel'; +import type {SkyLayer} from 'react-map-gl'; + const TOKEN = ''; // Set your mapbox token here -const skyLayer = { +const skyLayer: SkyLayer = { id: 'sky', type: 'sky', paint: { @@ -18,14 +20,6 @@ const skyLayer = { }; export default function App() { - const [viewport, setViewport] = useState({ - latitude: 32.6141, - longitude: -114.34411, - zoom: 14, - bearing: 80, - pitch: 80 - }); - const onMapLoad = useCallback(evt => { const map = evt.target; map.setTerrain({source: 'mapbox-dem', exaggeration: 1.5}); @@ -33,13 +27,16 @@ export default function App() { return ( <> - - +
); diff --git a/examples/terrain/src/control-panel.js b/examples/terrain/src/control-panel.tsx similarity index 100% rename from examples/terrain/src/control-panel.js rename to examples/terrain/src/control-panel.tsx diff --git a/examples/terrain/tsconfig.json b/examples/terrain/tsconfig.json new file mode 100644 index 00000000..ff49de04 --- /dev/null +++ b/examples/terrain/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2020", + "jsx": "react", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "sourceMap": true + } +} \ No newline at end of file diff --git a/examples/terrain/webpack.config.js b/examples/terrain/webpack.config.js index 78fe2a6a..ed4df0d5 100644 --- a/examples/terrain/webpack.config.js +++ b/examples/terrain/webpack.config.js @@ -5,33 +5,40 @@ const resolve = require('path').resolve; const webpack = require('webpack'); -const BABEL_CONFIG = { - presets: ['@babel/env', '@babel/react'], - plugins: ['@babel/proposal-class-properties'] -}; - const config = { mode: 'development', + devServer: { + static: '.' + }, + entry: { - app: resolve('./src/app.js') + app: resolve('./src/app') }, output: { library: 'App' }, + resolve: { + extensions: ['.ts', '.tsx', '.js', '.json'] + }, + module: { rules: [ { - // Compile ES2015 using babel - test: /\.js$/, + test: /\.(ts|js)x?$/, include: [resolve('.')], exclude: [/node_modules/], use: [ { loader: 'babel-loader', - options: BABEL_CONFIG + options: { + presets: ['@babel/env', '@babel/react'] + } + }, + { + loader: 'ts-loader' } ] } @@ -39,7 +46,7 @@ const config = { }, // Optional: Enables reading mapbox token from environment variable - plugins: [new webpack.EnvironmentPlugin(['MapboxAccessToken'])] + plugins: [new webpack.EnvironmentPlugin({MapboxAccessToken: ''})] }; // Enables bundling against src in this repo rather than the installed version diff --git a/examples/zoom-to-bounds/app.css b/examples/zoom-to-bounds/app.css deleted file mode 100644 index 72db167a..00000000 --- a/examples/zoom-to-bounds/app.css +++ /dev/null @@ -1,24 +0,0 @@ -body { - margin: 0; - background: #000; -} -#map { - width: 100vw; - height: 100vh; -} - -.control-panel { - position: absolute; - top: 0; - right: 0; - max-width: 320px; - background: #fff; - box-shadow: 0 2px 4px rgba(0,0,0,0.3); - padding: 12px 24px; - margin: 20px; - font-size: 13px; - line-height: 2; - color: #6b6b76; - text-transform: uppercase; - outline: none; -} diff --git a/examples/zoom-to-bounds/index.html b/examples/zoom-to-bounds/index.html index 7ccf392a..4e672b39 100644 --- a/examples/zoom-to-bounds/index.html +++ b/examples/zoom-to-bounds/index.html @@ -3,7 +3,33 @@ react-map-gl Example - + +
diff --git a/examples/zoom-to-bounds/package.json b/examples/zoom-to-bounds/package.json index 04ec92ea..0340a561 100644 --- a/examples/zoom-to-bounds/package.json +++ b/examples/zoom-to-bounds/package.json @@ -1,22 +1,24 @@ { "scripts": { "start": "webpack-dev-server --progress --hot --open", - "start-local": "webpack-dev-server --env.local --progress --hot --open" + "start-local": "webpack-dev-server --env local --progress --hot --open" }, "dependencies": { - "@turf/bbox": "^6.0.1", - "react": "^16.3.0", - "react-dom": "^16.3.0", - "react-map-gl": "^6.0.0" + "@turf/bbox": "^6.5.0", + "mapbox-gl": "^2.0.0", + "react": "^17.0.0", + "react-dom": "^17.0.0", + "react-map-gl": "^7.0.0" }, "devDependencies": { "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/preset-env": "^7.0.0", "@babel/preset-react": "^7.0.0", "babel-loader": "^8.0.0", - "webpack": "^4.20.0", - "webpack-cli": "^3.1.2", - "webpack-dev-server": "^3.1.0" + "ts-loader": "^9.0.0", + "typescript": "^4.0.0", + "webpack": "^5.65.0", + "webpack-cli": "^4.9.0", + "webpack-dev-server": "^4.7.0" } } diff --git a/examples/zoom-to-bounds/src/app.js b/examples/zoom-to-bounds/src/app.js deleted file mode 100644 index 9bc10820..00000000 --- a/examples/zoom-to-bounds/src/app.js +++ /dev/null @@ -1,70 +0,0 @@ -import * as React from 'react'; -import {useState} from 'react'; -import {render} from 'react-dom'; -import MapGL, {LinearInterpolator, WebMercatorViewport} from 'react-map-gl'; -import bbox from '@turf/bbox'; - -import ControlPanel from './control-panel'; -import MAP_STYLE from './map-style'; - -const TOKEN = ''; // Set your mapbox token here - -export default function App() { - const [viewport, setViewport] = useState({ - latitude: 37.78, - longitude: -122.4, - zoom: 11, - bearing: 0, - pitch: 0 - }); - - const onClick = event => { - const feature = event.features[0]; - if (feature) { - // calculate the bounding box of the feature - const [minLng, minLat, maxLng, maxLat] = bbox(feature); - // construct a viewport instance from the current state - const vp = new WebMercatorViewport(viewport); - const {longitude, latitude, zoom} = vp.fitBounds( - [ - [minLng, minLat], - [maxLng, maxLat] - ], - { - padding: 40 - } - ); - - setViewport({ - ...viewport, - longitude, - latitude, - zoom, - transitionInterpolator: new LinearInterpolator({ - around: [event.offsetCenter.x, event.offsetCenter.y] - }), - transitionDuration: 1000 - }); - } - }; - - return ( - <> - setViewport(v)} - mapboxApiAccessToken={TOKEN} - /> - - - ); -} - -export function renderToDom(container) { - render(, container); -} diff --git a/examples/zoom-to-bounds/src/app.tsx b/examples/zoom-to-bounds/src/app.tsx new file mode 100644 index 00000000..c9887389 --- /dev/null +++ b/examples/zoom-to-bounds/src/app.tsx @@ -0,0 +1,56 @@ +import * as React from 'react'; +import {useRef} from 'react'; +import {render} from 'react-dom'; +import Map from 'react-map-gl'; +import bbox from '@turf/bbox'; + +import ControlPanel from './control-panel'; +import MAP_STYLE from './map-style'; + +import type {MapboxStyle, MapRef, MapLayerMouseEvent} from 'react-map-gl'; + +const TOKEN = ''; // Set your mapbox token here + +export default function App() { + const mapRef = useRef(); + + const onClick = (event: MapLayerMouseEvent) => { + const feature = event.features[0]; + if (feature) { + const map = mapRef.current.getMap(); + + // calculate the bounding box of the feature + const [minLng, minLat, maxLng, maxLat] = bbox(feature); + + map.fitBounds( + [ + [minLng, minLat], + [maxLng, maxLat] + ], + {padding: 40, duration: 1000} + ); + } + }; + + return ( + <> + + + + ); +} + +export function renderToDom(container) { + render(, container); +} diff --git a/examples/zoom-to-bounds/src/control-panel.js b/examples/zoom-to-bounds/src/control-panel.tsx similarity index 100% rename from examples/zoom-to-bounds/src/control-panel.js rename to examples/zoom-to-bounds/src/control-panel.tsx diff --git a/examples/zoom-to-bounds/src/map-style.js b/examples/zoom-to-bounds/src/map-style.js deleted file mode 100644 index 3c57310d..00000000 --- a/examples/zoom-to-bounds/src/map-style.js +++ /dev/null @@ -1,37 +0,0 @@ -import MAP_STYLE from '../../map-style-basic-v8.json'; - -// Make a copy of the map style -const mapStyle = { - ...MAP_STYLE, - sources: {...MAP_STYLE.sources}, - layers: MAP_STYLE.layers.slice() -}; - -mapStyle.sources['sf-neighborhoods'] = { - type: 'geojson', - data: 'https://raw.githubusercontent.com/uber/react-map-gl/master/examples/.data/feature-example-sf.json' -}; - -mapStyle.layers.push( - { - id: 'sf-neighborhoods-fill', - source: 'sf-neighborhoods', - type: 'fill', - paint: { - 'fill-outline-color': '#0040c8', - 'fill-color': '#fff', - 'fill-opacity': 0 - } - }, - { - id: 'sf-neighborhoods-outline', - source: 'sf-neighborhoods', - type: 'line', - paint: { - 'line-width': 2, - 'line-color': '#0080ef' - } - } -); - -export default mapStyle; diff --git a/examples/zoom-to-bounds/src/map-style.tsx b/examples/zoom-to-bounds/src/map-style.tsx new file mode 100644 index 00000000..bb47db3c --- /dev/null +++ b/examples/zoom-to-bounds/src/map-style.tsx @@ -0,0 +1,39 @@ +import type {GeoJSONSourceRaw, FillLayer, LineLayer} from 'react-map-gl'; + +import MAP_STYLE from '../../map-style-basic-v8.json'; + +const sfNeighborhoods: GeoJSONSourceRaw = { + type: 'geojson', + data: 'https://raw.githubusercontent.com/uber/react-map-gl/master/examples/.data/feature-example-sf.json' +}; + +const fillLayer: FillLayer = { + id: 'sf-neighborhoods-fill', + source: 'sf-neighborhoods', + type: 'fill', + paint: { + 'fill-outline-color': '#0040c8', + 'fill-color': '#fff', + 'fill-opacity': 0 + } +}; + +const lineLayer: LineLayer = { + id: 'sf-neighborhoods-outline', + source: 'sf-neighborhoods', + type: 'line', + paint: { + 'line-width': 2, + 'line-color': '#0080ef' + } +}; + +// Make a copy of the map style +export default { + ...MAP_STYLE, + sources: { + ...MAP_STYLE.sources, + ['sf-neighborhoods']: sfNeighborhoods + }, + layers: [...MAP_STYLE.layers, fillLayer, lineLayer] +}; diff --git a/examples/zoom-to-bounds/tsconfig.json b/examples/zoom-to-bounds/tsconfig.json new file mode 100644 index 00000000..ff49de04 --- /dev/null +++ b/examples/zoom-to-bounds/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "es2020", + "jsx": "react", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "moduleResolution": "node", + "sourceMap": true + } +} \ No newline at end of file diff --git a/examples/zoom-to-bounds/webpack.config.js b/examples/zoom-to-bounds/webpack.config.js index 78fe2a6a..ed4df0d5 100644 --- a/examples/zoom-to-bounds/webpack.config.js +++ b/examples/zoom-to-bounds/webpack.config.js @@ -5,33 +5,40 @@ const resolve = require('path').resolve; const webpack = require('webpack'); -const BABEL_CONFIG = { - presets: ['@babel/env', '@babel/react'], - plugins: ['@babel/proposal-class-properties'] -}; - const config = { mode: 'development', + devServer: { + static: '.' + }, + entry: { - app: resolve('./src/app.js') + app: resolve('./src/app') }, output: { library: 'App' }, + resolve: { + extensions: ['.ts', '.tsx', '.js', '.json'] + }, + module: { rules: [ { - // Compile ES2015 using babel - test: /\.js$/, + test: /\.(ts|js)x?$/, include: [resolve('.')], exclude: [/node_modules/], use: [ { loader: 'babel-loader', - options: BABEL_CONFIG + options: { + presets: ['@babel/env', '@babel/react'] + } + }, + { + loader: 'ts-loader' } ] } @@ -39,7 +46,7 @@ const config = { }, // Optional: Enables reading mapbox token from environment variable - plugins: [new webpack.EnvironmentPlugin(['MapboxAccessToken'])] + plugins: [new webpack.EnvironmentPlugin({MapboxAccessToken: ''})] }; // Enables bundling against src in this repo rather than the installed version diff --git a/package.json b/package.json index 7e78c5c4..57affb7d 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "README.md" ], "scripts": { - "typecheck": "tsc src/**/*.* --jsx react --noEmit", + "typecheck": "tsc -p tsconfig.esm.json --noEmit", "bootstrap": "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true yarn && ocular-bootstrap", "build": "ocular-clean && tsc -b tsconfig.esm.json && tsc -b tsconfig.es5.json && npm run flowgen", "flowgen": "for i in $(find dist -type f -name \"*.d.ts\"); do sh -c \"flowgen $i -o ${i%.*.*}.js.flow\"; done;", diff --git a/src/mapbox/mapbox.ts b/src/mapbox/mapbox.ts index 0238338f..dc3166d7 100644 --- a/src/mapbox/mapbox.ts +++ b/src/mapbox/mapbox.ts @@ -8,7 +8,7 @@ import type { ViewState, ViewStateChangeEvent, MapboxOptions, - Style, + MapboxStyle, ImmutableLike, LngLatBoundsLike, FitBoundsOptions, @@ -42,7 +42,7 @@ export type MapboxProps = Omit< viewState?: ViewState; /** Mapbox style */ - mapStyle?: string | Style | ImmutableLike; + mapStyle?: string | MapboxStyle | ImmutableLike; /** Enable diffing when the map style changes */ styleDiffing?: boolean; /** Default layers to query on pointer events */ @@ -516,13 +516,20 @@ export default class Mapbox { this._updateHover(event); break; } - if (typeof event === 'object' && event.type in cameraEvents) { - (event as ViewStateChangeEvent).viewState = transformToViewState(tr); + if (eventType in cameraEvents) { + if (typeof event === 'object') { + (event as ViewStateChangeEvent).viewState = transformToViewState(tr); + } + if (this._map.isMoving()) { + // Replace map.transform with ours during the callbacks + map.transform = this._renderTransform; + baseFire.call(map, event, properties); + map.transform = tr; + + return map; + } } - // Replace map.transform with ours during the callbacks - map.transform = this._renderTransform; baseFire.call(map, event, properties); - map.transform = tr; return map; } diff --git a/src/utils/style-utils.ts b/src/utils/style-utils.ts index f948b657..c2748937 100644 --- a/src/utils/style-utils.ts +++ b/src/utils/style-utils.ts @@ -1,11 +1,11 @@ -import {ImmutableLike, Style} from './types'; +import {ImmutableLike, MapboxStyle} from './types'; const refProps = ['type', 'source', 'source-layer', 'minzoom', 'maxzoom', 'filter', 'layout']; // Prepare a map style object for diffing // If immutable - convert to plain object // Work around some issues in older styles that would fail Mapbox's diffing -export function normalizeStyle(style: string | Style | ImmutableLike): string | Style { +export function normalizeStyle(style: string | MapboxStyle | ImmutableLike): string | MapboxStyle { if (!style) { return null; } @@ -13,7 +13,7 @@ export function normalizeStyle(style: string | Style | ImmutableLike): string | return style; } if ('toJS' in style) { - style = style.toJS() as Style; + style = style.toJS() as MapboxStyle; } const layerIndex = {}; diff --git a/src/utils/types.ts b/src/utils/types.ts index f3636d21..eeeba700 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -1,4 +1,4 @@ -import type {PaddingOptions, MapboxEvent, LngLatLike} from 'mapbox-gl'; +import type {PaddingOptions, MapboxEvent, LngLat} from 'mapbox-gl'; /** Defines the projection that the map should be rendered in */ export type ProjectionSpecification = { @@ -35,7 +35,7 @@ export type ViewStateChangeEvent = MapboxEvent & { }; export type MarkerDragEvent = MapboxEvent & { - lngLat: LngLatLike; + lngLat: LngLat; }; export type GeolocateEvent = MapboxEvent & GeolocationPosition; @@ -50,8 +50,11 @@ export interface ImmutableLike { // re-export mapbox types export type { + Point, PointLike, + LngLat, LngLatLike, + LngLatBounds, LngLatBoundsLike, MapboxOptions, MarkerOptions, @@ -59,7 +62,7 @@ export type { PaddingOptions, PositionOptions, FitBoundsOptions, - Style, + Style as MapboxStyle, AnyLayer, BackgroundLayer, CircleLayer, diff --git a/tsconfig.es5.json b/tsconfig.es5.json index 094edd99..6584f827 100644 --- a/tsconfig.es5.json +++ b/tsconfig.es5.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "build": true, "target": "es5", "jsx": "react", "moduleResolution": "node", diff --git a/tsconfig.esm.json b/tsconfig.esm.json index 6cb64416..108ba6b6 100644 --- a/tsconfig.esm.json +++ b/tsconfig.esm.json @@ -1,6 +1,5 @@ { "compilerOptions": { - "build": true, "target": "es2020", "jsx": "react", "moduleResolution": "node",