├── .babelrc ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── README.md ├── app ├── App.js ├── Sample.js ├── build.js ├── index.js ├── mapbox-gl.css ├── mapbox-gl.js ├── redux │ ├── actions.js │ ├── reducers.js │ ├── sample.actions.js │ └── sample.reducer.js └── style.css ├── bundle ├── Circle.js ├── Layer.js ├── Line.js ├── Map.js ├── Source.js ├── Symbol.js ├── helper.js └── index.js ├── examples ├── CenterOnSymbol.js ├── Cluster.js ├── ColorSwitcher.js ├── DisplayMap.js ├── FitBounds.js ├── SetStyle.js ├── SlowlyFly.js ├── ToggleLayer.js ├── VectorSource.js └── index.js ├── index.html ├── lib ├── Circle.js ├── Layer.js ├── Line.js ├── Map.js ├── Source.js ├── Symbol.js ├── helper.js └── index.js ├── package.json ├── tests ├── .setup.js ├── Sample.test.js └── gol.test.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0", "react", "survivejs-kanban"], 3 | "env": { 4 | "start": { 5 | "presets": [ 6 | "react-hmre" 7 | ] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/ 2 | coverage/ 3 | bundle/ 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /*eslint-disable*/ 2 | module.exports = { 3 | 'extends': 'airbnb', 4 | 'parser': 'babel-eslint', 5 | 'globals': { 6 | 'it': true, 7 | 'describe': true, 8 | 'mapboxgl': true 9 | }, 10 | rules: { 11 | 'max-len': [ 12 | 1, 13 | 240, 14 | 2, { 15 | ignoreComments: true 16 | } 17 | ], 18 | 'no-underscore-dangle': 0 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | npm-debug.log 4 | */.DS_Store 5 | .DS_Store 6 | .DS_Store? 7 | app/token.js 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ReactJS bindings for mapbox-gl 2 | 3 | _*mapboxgl must be passed as prop to component as of now :/. *_ 4 | _* This is work in progress, some features might not work as expected, use with caution.*_ 5 | 6 | # Usage 7 | 8 | ```bash 9 | npm install -S maps-react 10 | ``` 11 | 12 | ### Example: Setting up Map 13 | 14 | ```Javascript 15 | import React from 'react'; 16 | import mapboxgl from 'mapbox-gl'; // Causes problems with webpack, temp fix is to use a global dependency 17 | import { Map } from 'maps-react'; 18 | 19 | mapboxgl.accessToken = GL_TOKEN; // your access token 20 | 21 | export default () => 22 | 28 | ; 29 | ``` 30 | 31 | ### Example: Toggling a layer 32 | 33 | ```Javascript 34 | import React from 'react'; 35 | import { Map, Source, Circle, Line} from 'maps-react'; 36 | 37 | mapboxgl.accessToken = GL_TOKEN; // your access token 38 | 39 | export default class ToggleLayer extends React.Component { 40 | 41 | state = { 42 | contours: 'visible', 43 | museums: 'visible', 44 | } 45 | 46 | render() { 47 | return ( 48 |
49 |
50 | this.setState({ contours: this.state.contours === 'visible' ? 'none' : 'visible' })}>Contour 51 | this.setState({ museums: this.state.museums === 'visible' ? 'none' : 'visible' })}> Museums 52 |
53 | 59 | 64 | 73 | 74 | 79 | 92 | 93 | 94 |
95 | ); 96 | } 97 | 98 | 99 | } 100 | 101 | ``` 102 | # Examples 103 | These examples are inspired from mapbox-gl's official [examples](https://www.mapbox.com/mapbox-gl-js/examples/). 104 | 105 | - Center on a symbol [Demo](http://kushanjoshi.com/maps-react/#/CenterOnSymbol), [Src Code](https://github.com/kepta/maps-react/blob/master/examples/CenterOnSymbol.js) 106 | - Cluster [Demo](http://kushanjoshi.com/maps-react/#/Cluster), [Src Code](https://github.com/kepta/maps-react/blob/master/examples/Cluster.js) 107 | - Display Map [Demo](http://kushanjoshi.com/maps-react/#/DisplayMap), [Src Code](https://github.com/kepta/maps-react/blob/master/examples/DisplayMap.js) 108 | - Fit Bounds [Demo](http://kushanjoshi.com/maps-react/#/FitBounds?_k=4jj3wk), [Src Code](https://github.com/kepta/maps-react/blob/master/examples/FitBounds.js) 109 | - Set Style [Demo](http://kushanjoshi.com/maps-react/#/SetStyle?_k=4jj3wk), [Src Code](https://github.com/kepta/maps-react/blob/master/examples/SetStyle.js) 110 | - Slowly Fly [Demo](http://kushanjoshi.com/maps-react/#/SlowlyFly?_k=4jj3wk), [Src Code](https://github.com/kepta/maps-react/blob/master/examples/SlowlyFly.js) 111 | - Toggle Layer [Demo](http://kushanjoshi.com/maps-react/#/ToggleLayer?_k=4jj3wk), [Src Code](https://github.com/kepta/maps-react/blob/master/examples/ToggleLayer.js) 112 | - Vector Source [Demo](http://kushanjoshi.com/maps-react/#/VectorSource?_k=4jj3wk), [Src Code](https://github.com/kepta/maps-react/blob/master/examples/VectorSource.js) 113 | - Color Switcher [Demo](), [Src Code]() -------------------------------------------------------------------------------- /app/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { bindActionCreators } from 'redux'; 4 | import { actions } from './redux/actions'; 5 | import {Map} from './index'; 6 | // function mapStateToProps(state) { 7 | // return { ...state.reducer }; 8 | // } 9 | 10 | // function mapDispatchToProps(dispatch) { 11 | // return { 12 | // actions: bindActionCreators(actions, dispatch), 13 | // }; 14 | // } 15 | 16 | // const Foo = () => { 17 | // return

hola

; 18 | // }; 19 | // @connect(mapStateToProps, mapDispatchToProps) 20 | export default class App extends React.Component { 21 | static propTypes = { 22 | sample: React.PropTypes.object, 23 | actions: React.PropTypes.object, 24 | children: React.PropTypes.element.isRequired, 25 | } 26 | state = { 27 | kuch: null, 28 | } 29 | render() { 30 | console.log(this.props); 31 | return ( 32 |
33 | {this.props.children} 34 |
35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Sample.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default class Sample extends React.Component { 4 | state = { 5 | magic: false, 6 | } 7 | 8 | render() { 9 | return ( 10 |
11 |

hola

12 |
13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/build.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } 4 | 5 | var React = _interopDefault(require('react')); 6 | 7 | function clean(argObj) { 8 | var obj = argObj; 9 | Object.keys(obj).forEach(function (key) { 10 | if (typeof obj[key] === 'undefined') { 11 | delete obj[key]; 12 | } 13 | }); 14 | return obj; 15 | } 16 | 17 | var classCallCheck = function (instance, Constructor) { 18 | if (!(instance instanceof Constructor)) { 19 | throw new TypeError("Cannot call a class as a function"); 20 | } 21 | }; 22 | 23 | var createClass = function () { 24 | function defineProperties(target, props) { 25 | for (var i = 0; i < props.length; i++) { 26 | var descriptor = props[i]; 27 | descriptor.enumerable = descriptor.enumerable || false; 28 | descriptor.configurable = true; 29 | if ("value" in descriptor) descriptor.writable = true; 30 | Object.defineProperty(target, descriptor.key, descriptor); 31 | } 32 | } 33 | 34 | return function (Constructor, protoProps, staticProps) { 35 | if (protoProps) defineProperties(Constructor.prototype, protoProps); 36 | if (staticProps) defineProperties(Constructor, staticProps); 37 | return Constructor; 38 | }; 39 | }(); 40 | 41 | var extends = Object.assign || function (target) { 42 | for (var i = 1; i < arguments.length; i++) { 43 | var source = arguments[i]; 44 | 45 | for (var key in source) { 46 | if (Object.prototype.hasOwnProperty.call(source, key)) { 47 | target[key] = source[key]; 48 | } 49 | } 50 | } 51 | 52 | return target; 53 | }; 54 | 55 | var inherits = function (subClass, superClass) { 56 | if (typeof superClass !== "function" && superClass !== null) { 57 | throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); 58 | } 59 | 60 | subClass.prototype = Object.create(superClass && superClass.prototype, { 61 | constructor: { 62 | value: subClass, 63 | enumerable: false, 64 | writable: true, 65 | configurable: true 66 | } 67 | }); 68 | if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; 69 | }; 70 | 71 | var possibleConstructorReturn = function (self, call) { 72 | if (!self) { 73 | throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 74 | } 75 | 76 | return call && (typeof call === "object" || typeof call === "function") ? call : self; 77 | }; 78 | 79 | var GL_TOKEN = 'pk.eyJ1Ijoia3VzaGFuMjAyMCIsImEiOiJjaWw5dG56enEwMGV6dWVsemxwMWw5NnM5In0.BbEUL1-qRFSHt7yHMorwew'; 80 | 81 | var Map = function (_React$Component) { 82 | inherits(Map, _React$Component); 83 | 84 | function Map() { 85 | var _Object$getPrototypeO; 86 | 87 | var _temp, _this, _ret; 88 | 89 | classCallCheck(this, Map); 90 | 91 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 92 | args[_key] = arguments[_key]; 93 | } 94 | 95 | return _ret = (_temp = (_this = possibleConstructorReturn(this, (_Object$getPrototypeO = Object.getPrototypeOf(Map)).call.apply(_Object$getPrototypeO, [this].concat(args))), _this), _this.state = { 96 | map: null 97 | }, _this.sendProps = function () { 98 | return React.Children.map(_this.props.children, function (child) { 99 | return React.cloneElement(child, { 100 | map: _this.state.map 101 | }); 102 | }); 103 | }, _temp), possibleConstructorReturn(_this, _ret); 104 | } 105 | 106 | createClass(Map, [{ 107 | key: 'componentDidMount', 108 | value: function componentDidMount() { 109 | var _this2 = this; 110 | 111 | mapboxgl.accessToken = GL_TOKEN; 112 | var map = new mapboxgl.Map({ 113 | container: 'map', 114 | style: this.props.style, // stylesheet location 115 | center: this.props.center, 116 | zoom: this.props.zoom, 117 | pitch: this.props.pitch 118 | }); 119 | map.on('load', function () { 120 | _this2.setState({ 121 | map: map 122 | }); 123 | _this2.props.onLoad(map); 124 | }); 125 | } 126 | }, { 127 | key: 'componentWillUpdate', 128 | value: function componentWillUpdate(nextProps, nextState) { 129 | if (nextState.map) { 130 | if (nextProps.style !== this.props.style) { 131 | this.state.map.setStyle(nextProps.style); 132 | } 133 | } 134 | } 135 | }, { 136 | key: 'render', 137 | value: function render() { 138 | // console.log(this.state.map); 139 | return React.createElement( 140 | 'div', 141 | null, 142 | React.createElement('div', { id: 'map' }), 143 | this.state.map ? this.sendProps() : null 144 | ); 145 | } 146 | }]); 147 | return Map; 148 | }(React.Component); 149 | 150 | Map.propTypes = { 151 | children: React.PropTypes.element, 152 | center: React.PropTypes.array, 153 | onLoad: React.PropTypes.func, 154 | style: React.PropTypes.string, 155 | zoom: React.PropTypes.number, 156 | pitch: React.PropTypes.number, 157 | bearing: React.PropTypes.number 158 | }; 159 | Map.defaultProps = { 160 | center: [-77.0152, 38.8937], 161 | zoom: 16, 162 | pitch: 0, 163 | style: 'mapbox://styles/mapbox/satellite-streets-v9', 164 | onLoad: function onLoad() {} 165 | }; 166 | 167 | var Layer = function (_React$Component) { 168 | inherits(Layer, _React$Component); 169 | 170 | function Layer(props) { 171 | classCallCheck(this, Layer); 172 | 173 | var _this = possibleConstructorReturn(this, Object.getPrototypeOf(Layer).call(this, props)); 174 | 175 | _initialiseProps.call(_this); 176 | 177 | _this.layer = _this.addLayer(props); 178 | return _this; 179 | } 180 | 181 | createClass(Layer, [{ 182 | key: 'componentWillUpdate', 183 | value: function componentWillUpdate(nextProps) { 184 | if (nextProps.name !== this.props.name && nextProps._source) { 185 | console.debug('removing layer', this.props.name); 186 | nextProps.map.removeLayer(this.props.name); 187 | this.layer = this.addLayer(nextProps); 188 | } 189 | if (this.props.visibility !== nextProps.visibility) { 190 | console.debug('changing visibility'); 191 | nextProps.map.setLayoutProperty(nextProps.name, 'visibility', nextProps.visibility); 192 | } 193 | } 194 | }, { 195 | key: 'componentWillUnmount', 196 | value: function componentWillUnmount() { 197 | this.props.map.removeLayer(this.props.name); 198 | } 199 | }, { 200 | key: 'render', 201 | value: function render() { 202 | if (this.layer && this.props.filter) { 203 | this.props.map.setFilter(this.props.name, this.props.filter); 204 | } 205 | return null; 206 | } 207 | }]); 208 | return Layer; 209 | }(React.Component); 210 | 211 | Layer.propTypes = { 212 | name: React.PropTypes.string.isRequired, 213 | _source: React.PropTypes.string, 214 | map: React.PropTypes.object, 215 | style: React.PropTypes.object.isRequired, 216 | filter: React.PropTypes.array, 217 | type: React.PropTypes.string.isRequired, 218 | sourceLayer: React.PropTypes.string, 219 | visibility: React.PropTypes.string 220 | }; 221 | 222 | var _initialiseProps = function _initialiseProps() { 223 | this.addLayer = function (props) { 224 | var obj = extends({}, props.style, { 225 | id: props.name, 226 | source: props._source, 227 | type: props.type, 228 | 'source-layer': props.sourceLayer 229 | }); 230 | if (props.visibility) { 231 | if (!obj.layout) obj.layout = {}; 232 | obj.layout.visibility = props.visibility; 233 | } 234 | return props.map.addLayer(clean(obj)); 235 | }; 236 | }; 237 | 238 | var Circle = function Circle(_ref) { 239 | var name = _ref.name; 240 | var _source = _ref._source; 241 | var filter = _ref.filter; 242 | var paint = _ref.paint; 243 | var map = _ref.map; 244 | var sourceLayer = _ref.sourceLayer; 245 | var visibility = _ref.visibility; 246 | return React.createElement(Layer, { 247 | type: 'circle', 248 | name: name, 249 | _source: _source, 250 | map: map, 251 | visibility: visibility, 252 | style: { 253 | paint: paint 254 | }, 255 | filter: filter, 256 | sourceLayer: sourceLayer 257 | }); 258 | }; 259 | 260 | Circle.propTypes = { 261 | name: React.PropTypes.string, 262 | _source: React.PropTypes.string, 263 | sourceLayer: React.PropTypes.string, 264 | visibility: React.PropTypes.string, 265 | map: React.PropTypes.object, 266 | filter: React.PropTypes.array, 267 | paint: React.PropTypes.object.isRequired 268 | }; 269 | 270 | var Source = function (_React$Component) { 271 | inherits(Source, _React$Component); 272 | 273 | function Source(props) { 274 | classCallCheck(this, Source); 275 | 276 | var _this = possibleConstructorReturn(this, Object.getPrototypeOf(Source).call(this, props)); 277 | 278 | _this.onClick = function (e) { 279 | _this.props.onClick(e, _this.queryRenderedFeatures, _this.props.map); 280 | }; 281 | 282 | _this.queryRenderedFeatures = function (e) { 283 | console.log(React.Children.map(_this.props.children, function (child) { 284 | return child.props.name; 285 | })); 286 | return _this.props.map.queryRenderedFeatures(e, { 287 | layers: React.Children.map(_this.props.children, function (child) { 288 | return child.props.name; 289 | }) 290 | }); 291 | }; 292 | 293 | _this.cloneChildren = function () { 294 | return React.Children.map(_this.props.children, function (child) { 295 | return React.cloneElement(child, { 296 | _source: _this.props.name, 297 | map: _this.props.map 298 | }); 299 | }); 300 | }; 301 | 302 | _this.state = { 303 | name: _this.props.name 304 | }; 305 | _this.addSource(props); 306 | if (props.onClick) { 307 | props.map.on('click', _this.onClick); 308 | } 309 | return _this; 310 | } 311 | 312 | createClass(Source, [{ 313 | key: 'componentWillUpdate', 314 | value: function componentWillUpdate(nextProps) { 315 | if (this.props.name !== nextProps.name) { 316 | console.debug('removing', this.props.name); 317 | nextProps.map.removeSource(this.props.name); 318 | this.addSource(nextProps); 319 | return this.setState({ 320 | name: nextProps.name 321 | }); 322 | } 323 | if (this.props.data !== nextProps.data) { 324 | return nextProps.map.getSource(nextProps.name).setData(nextProps.data); 325 | } 326 | } 327 | }, { 328 | key: 'componentWillUnmount', 329 | value: function componentWillUnmount() { 330 | console.debug('removing', this.props.name); 331 | if (this.props.onClick) { 332 | this.props.map.off('click', this.onClick); 333 | } 334 | this.props.map.removeSource(this.state.name); 335 | } 336 | }, { 337 | key: 'addSource', 338 | value: function addSource(props) { 339 | var obj = { 340 | type: props.type, 341 | url: props.url, 342 | data: props.data, 343 | cluster: props.cluster, 344 | clusterMaxZoom: props.clusterMaxZoom, 345 | clusterRadius: props.clusterRadius 346 | }; 347 | props.map.addSource(props.name, clean(obj)); 348 | } 349 | }, { 350 | key: 'render', 351 | value: function render() { 352 | return React.createElement( 353 | 'div', 354 | null, 355 | this.props.name ? this.cloneChildren() : null 356 | ); 357 | } 358 | }]); 359 | return Source; 360 | }(React.Component); 361 | 362 | Source.propTypes = { 363 | name: React.PropTypes.string.isRequired, 364 | children: React.PropTypes.element.isRequired, 365 | map: React.PropTypes.object, 366 | data: React.PropTypes.object, 367 | url: React.PropTypes.string, 368 | type: React.PropTypes.string.isRequired, 369 | cluster: React.PropTypes.bool, 370 | clusterMaxZoom: React.PropTypes.number, 371 | clusterRadius: React.PropTypes.number, 372 | onClick: React.PropTypes.func 373 | }; 374 | 375 | var _Symbol = function _Symbol(_ref) { 376 | var name = _ref.name; 377 | var _source = _ref._source; 378 | var filter = _ref.filter; 379 | var layout = _ref.layout; 380 | var map = _ref.map; 381 | var sourceLayer = _ref.sourceLayer; 382 | var visibility = _ref.visibility; 383 | 384 | return React.createElement(Layer, { 385 | name: name, 386 | _source: _source, 387 | type: 'symbol', 388 | map: map, 389 | style: { 390 | layout: layout 391 | }, 392 | filter: filter, 393 | sourceLayer: sourceLayer, 394 | visibility: visibility 395 | }); 396 | }; 397 | 398 | _Symbol.propTypes = { 399 | name: React.PropTypes.string, 400 | _source: React.PropTypes.string, 401 | map: React.PropTypes.object, 402 | filter: React.PropTypes.array, 403 | layout: React.PropTypes.object.isRequired, 404 | visibility: React.PropTypes.string, 405 | sourceLayer: React.PropTypes.string 406 | }; 407 | 408 | var Line = function Line(_ref) { 409 | var name = _ref.name; 410 | var _source = _ref._source; 411 | var filter = _ref.filter; 412 | var paint = _ref.paint; 413 | var map = _ref.map; 414 | var sourceLayer = _ref.sourceLayer; 415 | var visibility = _ref.visibility; 416 | var layout = _ref.layout; 417 | return React.createElement(Layer, { 418 | type: 'line', 419 | name: name, 420 | _source: _source, 421 | map: map, 422 | visibility: visibility, 423 | style: { 424 | layout: layout, 425 | paint: paint 426 | }, 427 | filter: filter, 428 | sourceLayer: sourceLayer 429 | }); 430 | }; 431 | 432 | Line.propTypes = { 433 | name: React.PropTypes.string, 434 | _source: React.PropTypes.string, 435 | sourceLayer: React.PropTypes.string, 436 | visibility: React.PropTypes.string, 437 | map: React.PropTypes.object, 438 | filter: React.PropTypes.array, 439 | paint: React.PropTypes.object.isRequired, 440 | layout: React.PropTypes.object.isRequired 441 | }; 442 | 443 | exports.Map = Map; 444 | exports.Circle = Circle; 445 | exports.Layer = Layer; 446 | exports.Line = Line; 447 | exports.Source = Source; 448 | exports.Symbol = _Symbol; -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | import { render } from 'react-dom'; 2 | import React from 'react'; 3 | import App from './App'; 4 | import './mapbox-gl.css'; 5 | import './style.css'; 6 | import { createStore, combineReducers, applyMiddleware, compose } from 'redux'; 7 | import reducer from './redux/reducers'; 8 | import reduxLogger from 'redux-logger'; 9 | import { Provider } from 'react-redux'; 10 | import thunkMiddleware from 'redux-thunk'; 11 | import Sample from './Sample'; 12 | import { Router, Route, hashHistory, IndexRoute } from 'react-router'; 13 | import { syncHistoryWithStore, routerReducer } from 'react-router-redux'; 14 | 15 | import DisplayMap from '../examples/DisplayMap'; 16 | import Cluster from '../examples/Cluster'; 17 | import SetStyle from '../examples/SetStyle'; 18 | import ToggleLayer from '../examples/ToggleLayer'; 19 | import VectorSource from '../examples/VectorSource'; 20 | import FitBounds from '../examples/FitBounds'; 21 | import SlowlyFly from '../examples/SlowlyFly'; 22 | import CenterOnSymbol from '../examples/CenterOnSymbol'; 23 | 24 | const examples = { 25 | DisplayMap, 26 | Cluster, 27 | SetStyle, 28 | ToggleLayer, 29 | VectorSource, 30 | FitBounds, 31 | SlowlyFly, 32 | CenterOnSymbol, 33 | }; 34 | 35 | const node = document.getElementById('app'); 36 | 37 | let middleware = [thunkMiddleware]; 38 | if (process.env.NODE_ENV !== 'production') { 39 | const loggerMiddleware = reduxLogger(); 40 | middleware = [...middleware, loggerMiddleware]; 41 | } 42 | 43 | const store = createStore( 44 | combineReducers({ 45 | ...reducer, 46 | routing: routerReducer, 47 | }), undefined, 48 | compose( 49 | applyMiddleware( 50 | ...middleware 51 | ), 52 | window.devToolsExtension ? window.devToolsExtension() : f => f 53 | ) 54 | ); 55 | 56 | const history = syncHistoryWithStore(hashHistory, store); 57 | 58 | render( 59 | 60 | 61 | 62 | 63 | {Object.keys(examples).map((e, k) => )} 64 | 65 | 66 | , 67 | node 68 | ); 69 | -------------------------------------------------------------------------------- /app/mapbox-gl.css: -------------------------------------------------------------------------------- 1 | .mapboxgl-map { 2 | font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif; 3 | overflow: hidden; 4 | position: relative; 5 | -webkit-tap-highlight-color: rgba(0,0,0,0); 6 | } 7 | 8 | .mapboxgl-canvas-container.mapboxgl-interactive, 9 | .mapboxgl-ctrl-nav-compass { 10 | cursor: -webkit-grab; 11 | cursor: -moz-grab; 12 | cursor: grab; 13 | } 14 | .mapboxgl-canvas-container.mapboxgl-interactive:active, 15 | .mapboxgl-ctrl-nav-compass:active { 16 | cursor: -webkit-grabbing; 17 | cursor: -moz-grabbing; 18 | cursor: grabbing; 19 | } 20 | 21 | .mapboxgl-ctrl-top-left, 22 | .mapboxgl-ctrl-top-right, 23 | .mapboxgl-ctrl-bottom-left, 24 | .mapboxgl-ctrl-bottom-right { position:absolute; } 25 | .mapboxgl-ctrl-top-left { top:0; left:0; } 26 | .mapboxgl-ctrl-top-right { top:0; right:0; } 27 | .mapboxgl-ctrl-bottom-left { bottom:0; left:0; } 28 | .mapboxgl-ctrl-bottom-right { right:0; bottom:0; } 29 | 30 | .mapboxgl-ctrl { clear:both; } 31 | .mapboxgl-ctrl-top-left .mapboxgl-ctrl { margin:10px 0 0 10px; float:left; } 32 | .mapboxgl-ctrl-top-right .mapboxgl-ctrl{ margin:10px 10px 0 0; float:right; } 33 | .mapboxgl-ctrl-bottom-left .mapboxgl-ctrl { margin:0 0 10px 10px; float:left; } 34 | .mapboxgl-ctrl-bottom-right .mapboxgl-ctrl { margin:0 10px 10px 0; float:right; } 35 | 36 | .mapboxgl-ctrl-group { 37 | border-radius: 4px; 38 | -moz-box-shadow: 0px 0px 2px rgba(0,0,0,0.1); 39 | -webkit-box-shadow: 0px 0px 2px rgba(0,0,0,0.1); 40 | box-shadow: 0px 0px 0px 2px rgba(0,0,0,0.1); 41 | overflow: hidden; 42 | background: #fff; 43 | } 44 | .mapboxgl-ctrl-group > button { 45 | width: 30px; 46 | height: 30px; 47 | display: block; 48 | padding: 0; 49 | outline: none; 50 | border: none; 51 | border-bottom: 1px solid #ddd; 52 | box-sizing: border-box; 53 | background-color: rgba(0,0,0,0); 54 | cursor: pointer; 55 | } 56 | /* https://bugzilla.mozilla.org/show_bug.cgi?id=140562 */ 57 | .mapboxgl-ctrl > button::-moz-focus-inner { 58 | border: 0; 59 | padding: 0; 60 | } 61 | .mapboxgl-ctrl > button:last-child { 62 | border-bottom: 0; 63 | } 64 | .mapboxgl-ctrl > button:hover { 65 | background-color: rgba(0,0,0,0.05); 66 | } 67 | .mapboxgl-ctrl-icon, 68 | .mapboxgl-ctrl-icon > div.arrow { 69 | speak: none; 70 | -webkit-font-smoothing: antialiased; 71 | -moz-osx-font-smoothing: grayscale; 72 | } 73 | .mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-out { 74 | padding: 5px; 75 | background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27m%207%2C9%20c%20-0.554%2C0%20-1%2C0.446%20-1%2C1%200%2C0.554%200.446%2C1%201%2C1%20l%206%2C0%20c%200.554%2C0%201%2C-0.446%201%2C-1%200%2C-0.554%20-0.446%2C-1%20-1%2C-1%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A"); 76 | } 77 | .mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-in { 78 | padding: 5px; 79 | background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27M%2010%206%20C%209.446%206%209%206.4459904%209%207%20L%209%209%20L%207%209%20C%206.446%209%206%209.446%206%2010%20C%206%2010.554%206.446%2011%207%2011%20L%209%2011%20L%209%2013%20C%209%2013.55401%209.446%2014%2010%2014%20C%2010.554%2014%2011%2013.55401%2011%2013%20L%2011%2011%20L%2013%2011%20C%2013.554%2011%2014%2010.554%2014%2010%20C%2014%209.446%2013.554%209%2013%209%20L%2011%209%20L%2011%207%20C%2011%206.4459904%2010.554%206%2010%206%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A"); 80 | } 81 | .mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate { 82 | padding: 5px; 83 | background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27M13%2C7%20L10.5%2C11.75%20L10.25%2C10%20z%20M13.888%2C6.112%20C13.615%2C5.84%2013.382%2C6.076%2012.5%2C6.5%20C10.14%2C7.634%206%2C10%206%2C10%20L9.5%2C10.5%20L10%2C14%20C10%2C14%2012.366%2C9.86%2013.5%2C7.5%20C13.924%2C6.617%2014.16%2C6.385%2013.888%2C6.112%27%2F%3E%3C%2Fsvg%3E"); 84 | } 85 | 86 | .mapboxgl-ctrl-icon.mapboxgl-ctrl-compass > div.arrow { 87 | width: 20px; 88 | height: 20px; 89 | margin: 5px; 90 | background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%0A%09%3Cpolygon%20fill%3D%27%23333333%27%20points%3D%276%2C9%2010%2C1%2014%2C9%27%2F%3E%0A%09%3Cpolygon%20fill%3D%27%23CCCCCC%27%20points%3D%276%2C11%2010%2C19%2014%2C11%20%27%2F%3E%0A%3C%2Fsvg%3E"); 91 | background-repeat: no-repeat; 92 | } 93 | 94 | .mapboxgl-ctrl.mapboxgl-ctrl-attrib { 95 | padding: 0 5px; 96 | background-color: rgba(255,255,255,0.5); 97 | margin: 0; 98 | } 99 | .mapboxgl-ctrl-attrib a { 100 | color: rgba(0,0,0,0.75); 101 | text-decoration: none; 102 | } 103 | .mapboxgl-ctrl-attrib a:hover { 104 | color: inherit; 105 | text-decoration: underline; 106 | } 107 | .mapboxgl-ctrl-attrib .mapbox-improve-map { 108 | font-weight: bold; 109 | margin-left: 2px; 110 | } 111 | 112 | .mapboxgl-popup { 113 | position: absolute; 114 | top: 0; 115 | left: 0; 116 | display: -webkit-flex; 117 | display: flex; 118 | will-change: transform; 119 | pointer-events: none; 120 | } 121 | .mapboxgl-popup-anchor-top, 122 | .mapboxgl-popup-anchor-top-left, 123 | .mapboxgl-popup-anchor-top-right { 124 | -webkit-flex-direction: column; 125 | flex-direction: column; 126 | } 127 | .mapboxgl-popup-anchor-bottom, 128 | .mapboxgl-popup-anchor-bottom-left, 129 | .mapboxgl-popup-anchor-bottom-right { 130 | -webkit-flex-direction: column-reverse; 131 | flex-direction: column-reverse; 132 | } 133 | .mapboxgl-popup-anchor-left { 134 | -webkit-flex-direction: row; 135 | flex-direction: row; 136 | } 137 | .mapboxgl-popup-anchor-right { 138 | -webkit-flex-direction: row-reverse; 139 | flex-direction: row-reverse; 140 | } 141 | .mapboxgl-popup-tip { 142 | width: 0; 143 | height: 0; 144 | border: 10px solid transparent; 145 | z-index: 1; 146 | } 147 | .mapboxgl-popup-anchor-top .mapboxgl-popup-tip { 148 | -webkit-align-self: center; 149 | align-self: center; 150 | border-top: none; 151 | border-bottom-color: #fff; 152 | } 153 | .mapboxgl-popup-anchor-top-left .mapboxgl-popup-tip { 154 | -webkit-align-self: flex-start; 155 | align-self: flex-start; 156 | border-top: none; 157 | border-left: none; 158 | border-bottom-color: #fff; 159 | } 160 | .mapboxgl-popup-anchor-top-right .mapboxgl-popup-tip { 161 | -webkit-align-self: flex-end; 162 | align-self: flex-end; 163 | border-top: none; 164 | border-right: none; 165 | border-bottom-color: #fff; 166 | } 167 | .mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip { 168 | -webkit-align-self: center; 169 | align-self: center; 170 | border-bottom: none; 171 | border-top-color: #fff; 172 | } 173 | .mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-tip { 174 | -webkit-align-self: flex-start; 175 | align-self: flex-start; 176 | border-bottom: none; 177 | border-left: none; 178 | border-top-color: #fff; 179 | } 180 | .mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-tip { 181 | -webkit-align-self: flex-end; 182 | align-self: flex-end; 183 | border-bottom: none; 184 | border-right: none; 185 | border-top-color: #fff; 186 | } 187 | .mapboxgl-popup-anchor-left .mapboxgl-popup-tip { 188 | -webkit-align-self: center; 189 | align-self: center; 190 | border-left: none; 191 | border-right-color: #fff; 192 | } 193 | .mapboxgl-popup-anchor-right .mapboxgl-popup-tip { 194 | -webkit-align-self: center; 195 | align-self: center; 196 | border-right: none; 197 | border-left-color: #fff; 198 | } 199 | .mapboxgl-popup-close-button { 200 | position: absolute; 201 | right: 0; 202 | top: 0; 203 | border: none; 204 | border-radius: 0 3px 0 0; 205 | cursor: pointer; 206 | background-color: rgba(0,0,0,0); 207 | } 208 | .mapboxgl-popup-close-button:hover { 209 | background-color: rgba(0,0,0,0.05); 210 | } 211 | .mapboxgl-popup-content { 212 | position: relative; 213 | background: #fff; 214 | border-radius: 3px; 215 | box-shadow: 0 1px 2px rgba(0,0,0,0.10); 216 | padding: 10px 10px 15px; 217 | pointer-events: auto; 218 | } 219 | .mapboxgl-popup-anchor-top-left .mapboxgl-popup-content { 220 | border-top-left-radius: 0; 221 | } 222 | .mapboxgl-popup-anchor-top-right .mapboxgl-popup-content { 223 | border-top-right-radius: 0; 224 | } 225 | .mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-content { 226 | border-bottom-left-radius: 0; 227 | } 228 | .mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-content { 229 | border-bottom-right-radius: 0; 230 | } 231 | 232 | .mapboxgl-crosshair, 233 | .mapboxgl-crosshair .mapboxgl-interactive, 234 | .mapboxgl-crosshair .mapboxgl-interactive:active { 235 | cursor: crosshair; 236 | } 237 | .mapboxgl-boxzoom { 238 | position: absolute; 239 | top: 0; 240 | left: 0; 241 | width: 0; 242 | height: 0; 243 | background: #fff; 244 | border: 2px dotted #202020; 245 | opacity: 0.5; 246 | } 247 | @media print { 248 | .mapbox-improve-map { 249 | display:none; 250 | } 251 | } 252 | -------------------------------------------------------------------------------- /app/redux/actions.js: -------------------------------------------------------------------------------- 1 | import { 2 | setHello, 3 | } from './sample.actions'; 4 | 5 | export const actions = { 6 | setHello, 7 | }; 8 | -------------------------------------------------------------------------------- /app/redux/reducers.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import sample from './sample.reducer'; 3 | 4 | export default combineReducers({ sample }); 5 | -------------------------------------------------------------------------------- /app/redux/sample.actions.js: -------------------------------------------------------------------------------- 1 | export const SET_HELLO= 'SET_HELLO'; 2 | 3 | export function setHello(data) { 4 | return { 5 | type: SET_HELLO, 6 | data, 7 | }; 8 | } 9 | -------------------------------------------------------------------------------- /app/redux/sample.reducer.js: -------------------------------------------------------------------------------- 1 | import { SET_HELLO } from './sample.actions'; 2 | 3 | const initialState = { 4 | data: 'initially', 5 | }; 6 | 7 | export default function sample(state = initialState, action) { 8 | switch (action.type) { 9 | case SET_HELLO: 10 | return Object.assign({}, state, { 11 | data: action.data, 12 | }); 13 | default: 14 | return state; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: pink; 3 | } 4 | #map { 5 | width: 50%; 6 | height: 400px; 7 | } 8 | #mapSat { 9 | position:absolute; 10 | top:0; 11 | bottom:0; 12 | width:100%; 13 | } -------------------------------------------------------------------------------- /bundle/Circle.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _react = require('react'); 8 | 9 | var _react2 = _interopRequireDefault(_react); 10 | 11 | var _Layer = require('./Layer'); 12 | 13 | var _Layer2 = _interopRequireDefault(_Layer); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | var Circle = function Circle(_ref) { 18 | var name = _ref.name; 19 | var _source = _ref._source; 20 | var filter = _ref.filter; 21 | var paint = _ref.paint; 22 | var map = _ref.map; 23 | var sourceLayer = _ref.sourceLayer; 24 | var visibility = _ref.visibility; 25 | return _react2.default.createElement(_Layer2.default, { 26 | type: 'circle', 27 | name: name, 28 | _source: _source, 29 | map: map, 30 | visibility: visibility, 31 | style: { 32 | paint: paint 33 | }, 34 | filter: filter, 35 | sourceLayer: sourceLayer 36 | }); 37 | }; 38 | 39 | Circle.propTypes = { 40 | name: _react2.default.PropTypes.string, 41 | _source: _react2.default.PropTypes.string, 42 | sourceLayer: _react2.default.PropTypes.string, 43 | visibility: _react2.default.PropTypes.string, 44 | map: _react2.default.PropTypes.object, 45 | filter: _react2.default.PropTypes.array, 46 | paint: _react2.default.PropTypes.object.isRequired 47 | }; 48 | 49 | exports.default = Circle; 50 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9DaXJjbGUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7Ozs7QUFDQTs7Ozs7O0FBQ0EsSUFBTSxTQUFTLFNBQVQsTUFBUztBQUFBLE1BQUcsSUFBSCxRQUFHLElBQUg7QUFBQSxNQUFTLE9BQVQsUUFBUyxPQUFUO0FBQUEsTUFBa0IsTUFBbEIsUUFBa0IsTUFBbEI7QUFBQSxNQUEwQixLQUExQixRQUEwQixLQUExQjtBQUFBLE1BQWlDLEdBQWpDLFFBQWlDLEdBQWpDO0FBQUEsTUFBc0MsV0FBdEMsUUFBc0MsV0FBdEM7QUFBQSxNQUFtRCxVQUFuRCxRQUFtRCxVQUFuRDtBQUFBLFNBQ2I7QUFDRSxVQUFLLFFBRFA7QUFFRSxVQUFNLElBRlI7QUFHRSxhQUFTLE9BSFg7QUFJRSxTQUFLLEdBSlA7QUFLRSxnQkFBWSxVQUxkO0FBTUUsV0FBTztBQUNMO0FBREssS0FOVDtBQVNFLFlBQVEsTUFUVjtBQVVFLGlCQUFhO0FBVmYsSUFEYTtBQUFBLENBQWY7O0FBY0EsT0FBTyxTQUFQLEdBQW1CO0FBQ2pCLFFBQU0sZ0JBQU0sU0FBTixDQUFnQixNQURMO0FBRWpCLFdBQVMsZ0JBQU0sU0FBTixDQUFnQixNQUZSO0FBR2pCLGVBQWEsZ0JBQU0sU0FBTixDQUFnQixNQUhaO0FBSWpCLGNBQVksZ0JBQU0sU0FBTixDQUFnQixNQUpYO0FBS2pCLE9BQUssZ0JBQU0sU0FBTixDQUFnQixNQUxKO0FBTWpCLFVBQVEsZ0JBQU0sU0FBTixDQUFnQixLQU5QO0FBT2pCLFNBQU8sZ0JBQU0sU0FBTixDQUFnQixNQUFoQixDQUF1QjtBQVBiLENBQW5COztrQkFVZSxNIiwiZmlsZSI6IkNpcmNsZS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgTGF5ZXIgZnJvbSAnLi9MYXllcic7XG5jb25zdCBDaXJjbGUgPSAoeyBuYW1lLCBfc291cmNlLCBmaWx0ZXIsIHBhaW50LCBtYXAsIHNvdXJjZUxheWVyLCB2aXNpYmlsaXR5IH0pID0+XG4gIDxMYXllclxuICAgIHR5cGU9XCJjaXJjbGVcIlxuICAgIG5hbWU9e25hbWV9XG4gICAgX3NvdXJjZT17X3NvdXJjZX1cbiAgICBtYXA9e21hcH1cbiAgICB2aXNpYmlsaXR5PXt2aXNpYmlsaXR5fVxuICAgIHN0eWxlPXt7XG4gICAgICBwYWludCxcbiAgICB9fVxuICAgIGZpbHRlcj17ZmlsdGVyfVxuICAgIHNvdXJjZUxheWVyPXtzb3VyY2VMYXllcn1cbiAgLz47XG5cbkNpcmNsZS5wcm9wVHlwZXMgPSB7XG4gIG5hbWU6IFJlYWN0LlByb3BUeXBlcy5zdHJpbmcsXG4gIF9zb3VyY2U6IFJlYWN0LlByb3BUeXBlcy5zdHJpbmcsXG4gIHNvdXJjZUxheWVyOiBSZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuICB2aXNpYmlsaXR5OiBSZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuICBtYXA6IFJlYWN0LlByb3BUeXBlcy5vYmplY3QsXG4gIGZpbHRlcjogUmVhY3QuUHJvcFR5cGVzLmFycmF5LFxuICBwYWludDogUmVhY3QuUHJvcFR5cGVzLm9iamVjdC5pc1JlcXVpcmVkLFxufTtcblxuZXhwb3J0IGRlZmF1bHQgQ2lyY2xlO1xuXG4iXX0= -------------------------------------------------------------------------------- /bundle/Layer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 8 | 9 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 10 | 11 | var _react = require('react'); 12 | 13 | var _react2 = _interopRequireDefault(_react); 14 | 15 | var _helper = require('./helper'); 16 | 17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 18 | 19 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 20 | 21 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 22 | 23 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 24 | 25 | var Layer = function (_React$Component) { 26 | _inherits(Layer, _React$Component); 27 | 28 | function Layer(props) { 29 | _classCallCheck(this, Layer); 30 | 31 | var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Layer).call(this, props)); 32 | 33 | _initialiseProps.call(_this); 34 | 35 | _this.layer = _this.addLayer(props); 36 | return _this; 37 | } 38 | 39 | _createClass(Layer, [{ 40 | key: 'componentWillUpdate', 41 | value: function componentWillUpdate(nextProps) { 42 | if (nextProps.name !== this.props.name && nextProps._source) { 43 | console.debug('removing layer', this.props.name); 44 | nextProps.map.removeLayer(this.props.name); 45 | this.layer = this.addLayer(nextProps); 46 | } 47 | if (this.props.visibility !== nextProps.visibility) { 48 | console.debug('changing visibility'); 49 | nextProps.map.setLayoutProperty(nextProps.name, 'visibility', nextProps.visibility); 50 | } 51 | } 52 | }, { 53 | key: 'componentWillUnmount', 54 | value: function componentWillUnmount() { 55 | console.debug('removing layer', this.props.name); 56 | this.props.map.removeLayer(this.props.name); 57 | } 58 | }, { 59 | key: 'render', 60 | value: function render() { 61 | if (this.layer && this.props.filter) { 62 | this.props.map.setFilter(this.props.name, this.props.filter); 63 | } 64 | return null; 65 | } 66 | }]); 67 | 68 | return Layer; 69 | }(_react2.default.Component); 70 | 71 | Layer.propTypes = { 72 | name: _react2.default.PropTypes.string.isRequired, 73 | _source: _react2.default.PropTypes.string, 74 | map: _react2.default.PropTypes.object, 75 | style: _react2.default.PropTypes.object.isRequired, 76 | filter: _react2.default.PropTypes.array, 77 | type: _react2.default.PropTypes.string.isRequired, 78 | sourceLayer: _react2.default.PropTypes.string, 79 | visibility: _react2.default.PropTypes.string 80 | }; 81 | 82 | var _initialiseProps = function _initialiseProps() { 83 | this.addLayer = function (props) { 84 | var obj = _extends({}, (0, _helper.clean)(props.style), { 85 | id: props.name, 86 | source: props._source, 87 | type: props.type, 88 | 'source-layer': props.sourceLayer 89 | }); 90 | if (props.visibility) { 91 | if (!obj.layout) obj.layout = {}; 92 | obj.layout.visibility = props.visibility; 93 | } 94 | return props.map.addLayer((0, _helper.clean)(obj)); 95 | }; 96 | }; 97 | 98 | exports.default = Layer; 99 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9MYXllci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUE7Ozs7QUFDQTs7Ozs7Ozs7OztJQUVxQixLOzs7QUFZbkIsaUJBQVksS0FBWixFQUFtQjtBQUFBOztBQUFBLHlGQUNYLEtBRFc7O0FBQUE7O0FBRWpCLFVBQUssS0FBTCxHQUFhLE1BQUssUUFBTCxDQUFjLEtBQWQsQ0FBYjtBQUZpQjtBQUdsQjs7Ozt3Q0FDbUIsUyxFQUFXO0FBQzdCLFVBQUksVUFBVSxJQUFWLEtBQW1CLEtBQUssS0FBTCxDQUFXLElBQTlCLElBQXNDLFVBQVUsT0FBcEQsRUFBNkQ7QUFDM0QsZ0JBQVEsS0FBUixDQUFjLGdCQUFkLEVBQWdDLEtBQUssS0FBTCxDQUFXLElBQTNDO0FBQ0Esa0JBQVUsR0FBVixDQUFjLFdBQWQsQ0FBMEIsS0FBSyxLQUFMLENBQVcsSUFBckM7QUFDQSxhQUFLLEtBQUwsR0FBYSxLQUFLLFFBQUwsQ0FBYyxTQUFkLENBQWI7QUFDRDtBQUNELFVBQUksS0FBSyxLQUFMLENBQVcsVUFBWCxLQUEwQixVQUFVLFVBQXhDLEVBQW9EO0FBQ2xELGdCQUFRLEtBQVIsQ0FBYyxxQkFBZDtBQUNBLGtCQUFVLEdBQVYsQ0FBYyxpQkFBZCxDQUFnQyxVQUFVLElBQTFDLEVBQWdELFlBQWhELEVBQThELFVBQVUsVUFBeEU7QUFDRDtBQUNGOzs7MkNBQ3NCO0FBQ3JCLGNBQVEsS0FBUixDQUFjLGdCQUFkLEVBQWdDLEtBQUssS0FBTCxDQUFXLElBQTNDO0FBQ0EsV0FBSyxLQUFMLENBQVcsR0FBWCxDQUFlLFdBQWYsQ0FBMkIsS0FBSyxLQUFMLENBQVcsSUFBdEM7QUFDRDs7OzZCQWVRO0FBQ1AsVUFBSSxLQUFLLEtBQUwsSUFBYyxLQUFLLEtBQUwsQ0FBVyxNQUE3QixFQUFxQztBQUNuQyxhQUFLLEtBQUwsQ0FBVyxHQUFYLENBQWUsU0FBZixDQUF5QixLQUFLLEtBQUwsQ0FBVyxJQUFwQyxFQUEwQyxLQUFLLEtBQUwsQ0FBVyxNQUFyRDtBQUNEO0FBQ0QsYUFDRSxJQURGO0FBR0Q7Ozs7RUFwRGdDLGdCQUFNLFM7O0FBQXBCLEssQ0FDWixTLEdBQVk7QUFDakIsUUFBTSxnQkFBTSxTQUFOLENBQWdCLE1BQWhCLENBQXVCLFVBRFo7QUFFakIsV0FBUyxnQkFBTSxTQUFOLENBQWdCLE1BRlI7QUFHakIsT0FBSyxnQkFBTSxTQUFOLENBQWdCLE1BSEo7QUFJakIsU0FBTyxnQkFBTSxTQUFOLENBQWdCLE1BQWhCLENBQXVCLFVBSmI7QUFLakIsVUFBUSxnQkFBTSxTQUFOLENBQWdCLEtBTFA7QUFNakIsUUFBTSxnQkFBTSxTQUFOLENBQWdCLE1BQWhCLENBQXVCLFVBTlo7QUFPakIsZUFBYSxnQkFBTSxTQUFOLENBQWdCLE1BUFo7QUFRakIsY0FBWSxnQkFBTSxTQUFOLENBQWdCO0FBUlgsQzs7O09BOEJuQixRLEdBQVcsVUFBQyxLQUFELEVBQVc7QUFDcEIsUUFBTSxtQkFDRCxtQkFBTSxNQUFNLEtBQVosQ0FEQztBQUVKLFVBQUksTUFBTSxJQUZOO0FBR0osY0FBUSxNQUFNLE9BSFY7QUFJSixZQUFNLE1BQU0sSUFKUjtBQUtKLHNCQUFnQixNQUFNO0FBTGxCLE1BQU47QUFPQSxRQUFJLE1BQU0sVUFBVixFQUFzQjtBQUNwQixVQUFJLENBQUMsSUFBSSxNQUFULEVBQWlCLElBQUksTUFBSixHQUFhLEVBQWI7QUFDakIsVUFBSSxNQUFKLENBQVcsVUFBWCxHQUF3QixNQUFNLFVBQTlCO0FBQ0Q7QUFDRCxXQUFPLE1BQU0sR0FBTixDQUFVLFFBQVYsQ0FBbUIsbUJBQU0sR0FBTixDQUFuQixDQUFQO0FBQ0QsRzs7O2tCQTVDa0IsSyIsImZpbGUiOiJMYXllci5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBjbGVhbiB9IGZyb20gJy4vaGVscGVyJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGF5ZXIgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQge1xuICBzdGF0aWMgcHJvcFR5cGVzID0ge1xuICAgIG5hbWU6IFJlYWN0LlByb3BUeXBlcy5zdHJpbmcuaXNSZXF1aXJlZCxcbiAgICBfc291cmNlOiBSZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuICAgIG1hcDogUmVhY3QuUHJvcFR5cGVzLm9iamVjdCxcbiAgICBzdHlsZTogUmVhY3QuUHJvcFR5cGVzLm9iamVjdC5pc1JlcXVpcmVkLFxuICAgIGZpbHRlcjogUmVhY3QuUHJvcFR5cGVzLmFycmF5LFxuICAgIHR5cGU6IFJlYWN0LlByb3BUeXBlcy5zdHJpbmcuaXNSZXF1aXJlZCxcbiAgICBzb3VyY2VMYXllcjogUmVhY3QuUHJvcFR5cGVzLnN0cmluZyxcbiAgICB2aXNpYmlsaXR5OiBSZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuICB9XG5cbiAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICBzdXBlcihwcm9wcyk7XG4gICAgdGhpcy5sYXllciA9IHRoaXMuYWRkTGF5ZXIocHJvcHMpO1xuICB9XG4gIGNvbXBvbmVudFdpbGxVcGRhdGUobmV4dFByb3BzKSB7XG4gICAgaWYgKG5leHRQcm9wcy5uYW1lICE9PSB0aGlzLnByb3BzLm5hbWUgJiYgbmV4dFByb3BzLl9zb3VyY2UpIHtcbiAgICAgIGNvbnNvbGUuZGVidWcoJ3JlbW92aW5nIGxheWVyJywgdGhpcy5wcm9wcy5uYW1lKTtcbiAgICAgIG5leHRQcm9wcy5tYXAucmVtb3ZlTGF5ZXIodGhpcy5wcm9wcy5uYW1lKTtcbiAgICAgIHRoaXMubGF5ZXIgPSB0aGlzLmFkZExheWVyKG5leHRQcm9wcyk7XG4gICAgfVxuICAgIGlmICh0aGlzLnByb3BzLnZpc2liaWxpdHkgIT09IG5leHRQcm9wcy52aXNpYmlsaXR5KSB7XG4gICAgICBjb25zb2xlLmRlYnVnKCdjaGFuZ2luZyB2aXNpYmlsaXR5Jyk7XG4gICAgICBuZXh0UHJvcHMubWFwLnNldExheW91dFByb3BlcnR5KG5leHRQcm9wcy5uYW1lLCAndmlzaWJpbGl0eScsIG5leHRQcm9wcy52aXNpYmlsaXR5KTtcbiAgICB9XG4gIH1cbiAgY29tcG9uZW50V2lsbFVubW91bnQoKSB7XG4gICAgY29uc29sZS5kZWJ1ZygncmVtb3ZpbmcgbGF5ZXInLCB0aGlzLnByb3BzLm5hbWUpO1xuICAgIHRoaXMucHJvcHMubWFwLnJlbW92ZUxheWVyKHRoaXMucHJvcHMubmFtZSk7XG4gIH1cbiAgYWRkTGF5ZXIgPSAocHJvcHMpID0+IHtcbiAgICBjb25zdCBvYmogPSB7XG4gICAgICAuLi5jbGVhbihwcm9wcy5zdHlsZSksXG4gICAgICBpZDogcHJvcHMubmFtZSxcbiAgICAgIHNvdXJjZTogcHJvcHMuX3NvdXJjZSxcbiAgICAgIHR5cGU6IHByb3BzLnR5cGUsXG4gICAgICAnc291cmNlLWxheWVyJzogcHJvcHMuc291cmNlTGF5ZXIsXG4gICAgfTtcbiAgICBpZiAocHJvcHMudmlzaWJpbGl0eSkge1xuICAgICAgaWYgKCFvYmoubGF5b3V0KSBvYmoubGF5b3V0ID0ge307XG4gICAgICBvYmoubGF5b3V0LnZpc2liaWxpdHkgPSBwcm9wcy52aXNpYmlsaXR5O1xuICAgIH1cbiAgICByZXR1cm4gcHJvcHMubWFwLmFkZExheWVyKGNsZWFuKG9iaikpO1xuICB9XG4gIHJlbmRlcigpIHtcbiAgICBpZiAodGhpcy5sYXllciAmJiB0aGlzLnByb3BzLmZpbHRlcikge1xuICAgICAgdGhpcy5wcm9wcy5tYXAuc2V0RmlsdGVyKHRoaXMucHJvcHMubmFtZSwgdGhpcy5wcm9wcy5maWx0ZXIpO1xuICAgIH1cbiAgICByZXR1cm4gKFxuICAgICAgbnVsbFxuICAgICk7XG4gIH1cbn1cbiJdfQ== -------------------------------------------------------------------------------- /bundle/Line.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _react = require('react'); 8 | 9 | var _react2 = _interopRequireDefault(_react); 10 | 11 | var _Layer = require('./Layer'); 12 | 13 | var _Layer2 = _interopRequireDefault(_Layer); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | var Line = function Line(_ref) { 18 | var name = _ref.name; 19 | var _source = _ref._source; 20 | var filter = _ref.filter; 21 | var paint = _ref.paint; 22 | var map = _ref.map; 23 | var sourceLayer = _ref.sourceLayer; 24 | var visibility = _ref.visibility; 25 | var layout = _ref.layout; 26 | return _react2.default.createElement(_Layer2.default, { 27 | type: 'line', 28 | name: name, 29 | _source: _source, 30 | map: map, 31 | visibility: visibility, 32 | style: { 33 | layout: layout, 34 | paint: paint 35 | }, 36 | filter: filter, 37 | sourceLayer: sourceLayer 38 | }); 39 | }; 40 | 41 | Line.propTypes = { 42 | name: _react2.default.PropTypes.string, 43 | _source: _react2.default.PropTypes.string, 44 | sourceLayer: _react2.default.PropTypes.string, 45 | visibility: _react2.default.PropTypes.string, 46 | map: _react2.default.PropTypes.object, 47 | filter: _react2.default.PropTypes.array, 48 | paint: _react2.default.PropTypes.object.isRequired, 49 | layout: _react2.default.PropTypes.object.isRequired 50 | }; 51 | 52 | exports.default = Line; 53 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9MaW5lLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUNBOzs7O0FBQ0E7Ozs7OztBQUNBLElBQU0sT0FBTyxTQUFQLElBQU87QUFBQSxNQUFHLElBQUgsUUFBRyxJQUFIO0FBQUEsTUFBUyxPQUFULFFBQVMsT0FBVDtBQUFBLE1BQWtCLE1BQWxCLFFBQWtCLE1BQWxCO0FBQUEsTUFBMEIsS0FBMUIsUUFBMEIsS0FBMUI7QUFBQSxNQUFpQyxHQUFqQyxRQUFpQyxHQUFqQztBQUFBLE1BQXNDLFdBQXRDLFFBQXNDLFdBQXRDO0FBQUEsTUFBbUQsVUFBbkQsUUFBbUQsVUFBbkQ7QUFBQSxNQUErRCxNQUEvRCxRQUErRCxNQUEvRDtBQUFBLFNBQ1g7QUFDRSxVQUFLLE1BRFA7QUFFRSxVQUFNLElBRlI7QUFHRSxhQUFTLE9BSFg7QUFJRSxTQUFLLEdBSlA7QUFLRSxnQkFBWSxVQUxkO0FBTUUsV0FBTztBQUNMLG9CQURLO0FBRUw7QUFGSyxLQU5UO0FBVUUsWUFBUSxNQVZWO0FBV0UsaUJBQWE7QUFYZixJQURXO0FBQUEsQ0FBYjs7QUFlQSxLQUFLLFNBQUwsR0FBaUI7QUFDZixRQUFNLGdCQUFNLFNBQU4sQ0FBZ0IsTUFEUDtBQUVmLFdBQVMsZ0JBQU0sU0FBTixDQUFnQixNQUZWO0FBR2YsZUFBYSxnQkFBTSxTQUFOLENBQWdCLE1BSGQ7QUFJZixjQUFZLGdCQUFNLFNBQU4sQ0FBZ0IsTUFKYjtBQUtmLE9BQUssZ0JBQU0sU0FBTixDQUFnQixNQUxOO0FBTWYsVUFBUSxnQkFBTSxTQUFOLENBQWdCLEtBTlQ7QUFPZixTQUFPLGdCQUFNLFNBQU4sQ0FBZ0IsTUFBaEIsQ0FBdUIsVUFQZjtBQVFmLFVBQVEsZ0JBQU0sU0FBTixDQUFnQixNQUFoQixDQUF1QjtBQVJoQixDQUFqQjs7a0JBV2UsSSIsImZpbGUiOiJMaW5lLmpzIiwic291cmNlc0NvbnRlbnQiOlsiXG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IExheWVyIGZyb20gJy4vTGF5ZXInO1xuY29uc3QgTGluZSA9ICh7IG5hbWUsIF9zb3VyY2UsIGZpbHRlciwgcGFpbnQsIG1hcCwgc291cmNlTGF5ZXIsIHZpc2liaWxpdHksIGxheW91dCB9KSA9PlxuICA8TGF5ZXJcbiAgICB0eXBlPVwibGluZVwiXG4gICAgbmFtZT17bmFtZX1cbiAgICBfc291cmNlPXtfc291cmNlfVxuICAgIG1hcD17bWFwfVxuICAgIHZpc2liaWxpdHk9e3Zpc2liaWxpdHl9XG4gICAgc3R5bGU9e3tcbiAgICAgIGxheW91dCxcbiAgICAgIHBhaW50LFxuICAgIH19XG4gICAgZmlsdGVyPXtmaWx0ZXJ9XG4gICAgc291cmNlTGF5ZXI9e3NvdXJjZUxheWVyfVxuICAvPjtcblxuTGluZS5wcm9wVHlwZXMgPSB7XG4gIG5hbWU6IFJlYWN0LlByb3BUeXBlcy5zdHJpbmcsXG4gIF9zb3VyY2U6IFJlYWN0LlByb3BUeXBlcy5zdHJpbmcsXG4gIHNvdXJjZUxheWVyOiBSZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuICB2aXNpYmlsaXR5OiBSZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuICBtYXA6IFJlYWN0LlByb3BUeXBlcy5vYmplY3QsXG4gIGZpbHRlcjogUmVhY3QuUHJvcFR5cGVzLmFycmF5LFxuICBwYWludDogUmVhY3QuUHJvcFR5cGVzLm9iamVjdC5pc1JlcXVpcmVkLFxuICBsYXlvdXQ6IFJlYWN0LlByb3BUeXBlcy5vYmplY3QuaXNSZXF1aXJlZCxcbn07XG5cbmV4cG9ydCBkZWZhdWx0IExpbmU7XG5cbiJdfQ== -------------------------------------------------------------------------------- /bundle/Map.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 8 | 9 | var _react = require('react'); 10 | 11 | var _react2 = _interopRequireDefault(_react); 12 | 13 | var _helper = require('./helper'); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 18 | 19 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 20 | 21 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 22 | 23 | var Map = function (_React$Component) { 24 | _inherits(Map, _React$Component); 25 | 26 | function Map() { 27 | var _Object$getPrototypeO; 28 | 29 | var _temp, _this, _ret; 30 | 31 | _classCallCheck(this, Map); 32 | 33 | for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { 34 | args[_key] = arguments[_key]; 35 | } 36 | 37 | return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_Object$getPrototypeO = Object.getPrototypeOf(Map)).call.apply(_Object$getPrototypeO, [this].concat(args))), _this), _this.state = { 38 | map: null 39 | }, _this.sendProps = function () { 40 | return _react2.default.Children.map(_this.props.children, function (child) { 41 | return _react2.default.cloneElement(child, { 42 | map: _this.state.map 43 | }); 44 | }); 45 | }, _temp), _possibleConstructorReturn(_this, _ret); 46 | } 47 | 48 | _createClass(Map, [{ 49 | key: 'componentDidMount', 50 | value: function componentDidMount() { 51 | var _this2 = this; 52 | 53 | var map = new this.props.mapboxgl.Map({ 54 | container: 'map', 55 | style: this.props.style, // stylesheet location 56 | center: this.props.center, 57 | zoom: this.props.zoom, 58 | pitch: this.props.pitch 59 | }); 60 | map.on('load', function () { 61 | _this2.setState({ 62 | map: map 63 | }); 64 | _this2.props.onLoad(map); 65 | }); 66 | } 67 | }, { 68 | key: 'componentWillUpdate', 69 | value: function componentWillUpdate(nextProps, nextState) { 70 | if (nextState.map) { 71 | if (nextProps.style !== this.props.style) { 72 | this.state.map.setStyle(nextProps.style); 73 | } 74 | } 75 | } 76 | }, { 77 | key: 'render', 78 | value: function render() { 79 | // console.log(this.state.map); 80 | return _react2.default.createElement( 81 | 'div', 82 | null, 83 | _react2.default.createElement('div', { id: 'map' }), 84 | this.state.map ? this.sendProps() : null 85 | ); 86 | } 87 | }]); 88 | 89 | return Map; 90 | }(_react2.default.Component); 91 | 92 | Map.propTypes = { 93 | children: _react2.default.PropTypes.element, 94 | center: _react2.default.PropTypes.array, 95 | onLoad: _react2.default.PropTypes.func, 96 | style: _react2.default.PropTypes.string, 97 | zoom: _react2.default.PropTypes.number, 98 | pitch: _react2.default.PropTypes.number, 99 | bearing: _react2.default.PropTypes.number, 100 | mapboxgl: _react2.default.PropTypes.object.isRequired 101 | }; 102 | Map.defaultProps = { 103 | center: [-77.0152, 38.8937], 104 | zoom: 16, 105 | pitch: 0, 106 | style: 'mapbox://styles/mapbox/satellite-streets-v9', 107 | onLoad: function onLoad() {} 108 | }; 109 | exports.default = Map; 110 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9NYXAuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7Ozs7Ozs7O0lBRXFCLEc7Ozs7Ozs7Ozs7Ozs7O2lNQW1CbkIsSyxHQUFRO0FBQ04sV0FBSztBQURDLEssUUF5QlIsUyxHQUFZLFlBQU07QUFDaEIsYUFBTyxnQkFBTSxRQUFOLENBQWUsR0FBZixDQUFtQixNQUFLLEtBQUwsQ0FBVyxRQUE5QixFQUNOLFVBQUMsS0FBRDtBQUFBLGVBQVcsZ0JBQU0sWUFBTixDQUFtQixLQUFuQixFQUEwQjtBQUNuQyxlQUFLLE1BQUssS0FBTCxDQUFXO0FBRG1CLFNBQTFCLENBQVg7QUFBQSxPQURNLENBQVA7QUFLRCxLOzs7Ozt3Q0E1Qm1CO0FBQUE7O0FBQ2xCLFVBQU0sTUFBTSxJQUFJLEtBQUssS0FBTCxDQUFXLFFBQVgsQ0FBb0IsR0FBeEIsQ0FBNEI7QUFDdEMsbUJBQVcsS0FEMkI7QUFFdEMsZUFBTyxLQUFLLEtBQUwsQ0FBVyxLQUZvQixFO0FBR3RDLGdCQUFRLEtBQUssS0FBTCxDQUFXLE1BSG1CO0FBSXRDLGNBQU0sS0FBSyxLQUFMLENBQVcsSUFKcUI7QUFLdEMsZUFBTyxLQUFLLEtBQUwsQ0FBVztBQUxvQixPQUE1QixDQUFaO0FBT0EsVUFBSSxFQUFKLENBQU8sTUFBUCxFQUFlLFlBQU07QUFDbkIsZUFBSyxRQUFMLENBQWM7QUFDWjtBQURZLFNBQWQ7QUFHQSxlQUFLLEtBQUwsQ0FBVyxNQUFYLENBQWtCLEdBQWxCO0FBQ0QsT0FMRDtBQU1EOzs7d0NBQ21CLFMsRUFBVyxTLEVBQVc7QUFDeEMsVUFBSSxVQUFVLEdBQWQsRUFBbUI7QUFDakIsWUFBSSxVQUFVLEtBQVYsS0FBb0IsS0FBSyxLQUFMLENBQVcsS0FBbkMsRUFBMEM7QUFDeEMsZUFBSyxLQUFMLENBQVcsR0FBWCxDQUFlLFFBQWYsQ0FBd0IsVUFBVSxLQUFsQztBQUNEO0FBQ0Y7QUFDRjs7OzZCQVFROztBQUVQLGFBQ0U7QUFBQTtRQUFBO1FBQ0UsdUNBQUssSUFBRyxLQUFSLEdBREY7UUFHSSxLQUFLLEtBQUwsQ0FBVyxHQUFYLEdBQ0EsS0FBSyxTQUFMLEVBREEsR0FFQTtBQUxKLE9BREY7QUFVRDs7OztFQS9EOEIsZ0JBQU0sUzs7QUFBbEIsRyxDQUNaLFMsR0FBWTtBQUNqQixZQUFVLGdCQUFNLFNBQU4sQ0FBZ0IsT0FEVDtBQUVqQixVQUFRLGdCQUFNLFNBQU4sQ0FBZ0IsS0FGUDtBQUdqQixVQUFRLGdCQUFNLFNBQU4sQ0FBZ0IsSUFIUDtBQUlqQixTQUFPLGdCQUFNLFNBQU4sQ0FBZ0IsTUFKTjtBQUtqQixRQUFNLGdCQUFNLFNBQU4sQ0FBZ0IsTUFMTDtBQU1qQixTQUFPLGdCQUFNLFNBQU4sQ0FBZ0IsTUFOTjtBQU9qQixXQUFTLGdCQUFNLFNBQU4sQ0FBZ0IsTUFQUjtBQVFqQixZQUFVLGdCQUFNLFNBQU4sQ0FBZ0IsTUFBaEIsQ0FBdUI7QUFSaEIsQztBQURBLEcsQ0FZWixZLEdBQWU7QUFDcEIsVUFBUSxDQUFDLENBQUMsT0FBRixFQUFXLE9BQVgsQ0FEWTtBQUVwQixRQUFNLEVBRmM7QUFHcEIsU0FBTyxDQUhhO0FBSXBCLFNBQU8sNkNBSmE7QUFLcEIsVUFBUSxrQkFBTSxDQUFFO0FBTEksQztrQkFaSCxHIiwiZmlsZSI6Ik1hcC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBjbGVhbiB9IGZyb20gJy4vaGVscGVyJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTWFwIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50IHtcbiAgc3RhdGljIHByb3BUeXBlcyA9IHtcbiAgICBjaGlsZHJlbjogUmVhY3QuUHJvcFR5cGVzLmVsZW1lbnQsXG4gICAgY2VudGVyOiBSZWFjdC5Qcm9wVHlwZXMuYXJyYXksXG4gICAgb25Mb2FkOiBSZWFjdC5Qcm9wVHlwZXMuZnVuYyxcbiAgICBzdHlsZTogUmVhY3QuUHJvcFR5cGVzLnN0cmluZyxcbiAgICB6b29tOiBSZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuICAgIHBpdGNoOiBSZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuICAgIGJlYXJpbmc6IFJlYWN0LlByb3BUeXBlcy5udW1iZXIsXG4gICAgbWFwYm94Z2w6IFJlYWN0LlByb3BUeXBlcy5vYmplY3QuaXNSZXF1aXJlZCxcbiAgfVxuXG4gIHN0YXRpYyBkZWZhdWx0UHJvcHMgPSB7XG4gICAgY2VudGVyOiBbLTc3LjAxNTIsIDM4Ljg5MzddLFxuICAgIHpvb206IDE2LFxuICAgIHBpdGNoOiAwLFxuICAgIHN0eWxlOiAnbWFwYm94Oi8vc3R5bGVzL21hcGJveC9zYXRlbGxpdGUtc3RyZWV0cy12OScsXG4gICAgb25Mb2FkOiAoKSA9PiB7fSxcbiAgfVxuICBzdGF0ZSA9IHtcbiAgICBtYXA6IG51bGwsXG4gIH1cbiAgY29tcG9uZW50RGlkTW91bnQoKSB7XG4gICAgY29uc3QgbWFwID0gbmV3IHRoaXMucHJvcHMubWFwYm94Z2wuTWFwKHtcbiAgICAgIGNvbnRhaW5lcjogJ21hcCcsXG4gICAgICBzdHlsZTogdGhpcy5wcm9wcy5zdHlsZSwgLy8gc3R5bGVzaGVldCBsb2NhdGlvblxuICAgICAgY2VudGVyOiB0aGlzLnByb3BzLmNlbnRlcixcbiAgICAgIHpvb206IHRoaXMucHJvcHMuem9vbSxcbiAgICAgIHBpdGNoOiB0aGlzLnByb3BzLnBpdGNoLFxuICAgIH0pO1xuICAgIG1hcC5vbignbG9hZCcsICgpID0+IHtcbiAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICBtYXAsXG4gICAgICB9KTtcbiAgICAgIHRoaXMucHJvcHMub25Mb2FkKG1hcCk7XG4gICAgfSk7XG4gIH1cbiAgY29tcG9uZW50V2lsbFVwZGF0ZShuZXh0UHJvcHMsIG5leHRTdGF0ZSkge1xuICAgIGlmIChuZXh0U3RhdGUubWFwKSB7XG4gICAgICBpZiAobmV4dFByb3BzLnN0eWxlICE9PSB0aGlzLnByb3BzLnN0eWxlKSB7XG4gICAgICAgIHRoaXMuc3RhdGUubWFwLnNldFN0eWxlKG5leHRQcm9wcy5zdHlsZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHNlbmRQcm9wcyA9ICgpID0+IHtcbiAgICByZXR1cm4gUmVhY3QuQ2hpbGRyZW4ubWFwKHRoaXMucHJvcHMuY2hpbGRyZW4sXG4gICAgIChjaGlsZCkgPT4gUmVhY3QuY2xvbmVFbGVtZW50KGNoaWxkLCB7XG4gICAgICAgbWFwOiB0aGlzLnN0YXRlLm1hcCxcbiAgICAgfSlcbiAgICApO1xuICB9XG4gIHJlbmRlcigpIHtcbiAgICAvLyBjb25zb2xlLmxvZyh0aGlzLnN0YXRlLm1hcCk7XG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXY+XG4gICAgICAgIDxkaXYgaWQ9XCJtYXBcIiAvPlxuICAgICAgICB7XG4gICAgICAgICAgdGhpcy5zdGF0ZS5tYXAgP1xuICAgICAgICAgIHRoaXMuc2VuZFByb3BzKClcbiAgICAgICAgOiBudWxsXG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgICk7XG4gIH1cbn1cbiJdfQ== -------------------------------------------------------------------------------- /bundle/Source.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 8 | 9 | var _react = require('react'); 10 | 11 | var _react2 = _interopRequireDefault(_react); 12 | 13 | var _helper = require('./helper'); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 18 | 19 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 20 | 21 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 22 | 23 | var Source = function (_React$Component) { 24 | _inherits(Source, _React$Component); 25 | 26 | function Source(props) { 27 | _classCallCheck(this, Source); 28 | 29 | var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Source).call(this, props)); 30 | 31 | _this.onClick = function (e) { 32 | _this.props.onClick(e, _this.queryRenderedFeatures, _this.props.map); 33 | }; 34 | 35 | _this.queryRenderedFeatures = function (e) { 36 | console.log(_react2.default.Children.map(_this.props.children, function (child) { 37 | return child.props.name; 38 | })); 39 | return _this.props.map.queryRenderedFeatures(e, { 40 | layers: _react2.default.Children.map(_this.props.children, function (child) { 41 | return child.props.name; 42 | }) 43 | }); 44 | }; 45 | 46 | _this.cloneChildren = function () { 47 | return _react2.default.Children.map(_this.props.children, function (child) { 48 | return _react2.default.cloneElement(child, { 49 | _source: _this.props.name, 50 | map: _this.props.map 51 | }); 52 | }); 53 | }; 54 | 55 | _this.state = { 56 | name: _this.props.name 57 | }; 58 | _this.addSource(props); 59 | if (props.onClick) { 60 | props.map.on('click', _this.onClick); 61 | } 62 | return _this; 63 | } 64 | 65 | _createClass(Source, [{ 66 | key: 'componentWillUpdate', 67 | value: function componentWillUpdate(nextProps) { 68 | if (this.props.name !== nextProps.name) { 69 | console.debug('removing', this.props.name); 70 | nextProps.map.removeSource(this.props.name); 71 | this.addSource(nextProps); 72 | return this.setState({ 73 | name: nextProps.name 74 | }); 75 | } 76 | if (this.props.data !== nextProps.data) { 77 | return nextProps.map.getSource(nextProps.name).setData(nextProps.data); 78 | } 79 | } 80 | }, { 81 | key: 'componentWillUnmount', 82 | value: function componentWillUnmount() { 83 | console.debug('removing', this.props.name); 84 | if (this.props.onClick) { 85 | this.props.map.off('click', this.onClick); 86 | } 87 | this.props.map.removeSource(this.state.name); 88 | } 89 | }, { 90 | key: 'addSource', 91 | value: function addSource(props) { 92 | var obj = { 93 | type: props.type, 94 | url: props.url, 95 | data: props.data, 96 | cluster: props.cluster, 97 | clusterMaxZoom: props.clusterMaxZoom, 98 | clusterRadius: props.clusterRadius, 99 | tiles: props.tiles, 100 | maxZoom: props.maxZoom, 101 | minZoom: props.minZoom 102 | }; 103 | props.map.addSource(props.name, (0, _helper.clean)(obj)); 104 | } 105 | }, { 106 | key: 'render', 107 | value: function render() { 108 | return _react2.default.createElement( 109 | 'div', 110 | null, 111 | this.props.name ? this.cloneChildren() : null 112 | ); 113 | } 114 | }]); 115 | 116 | return Source; 117 | }(_react2.default.Component); 118 | 119 | Source.propTypes = { 120 | name: _react2.default.PropTypes.string.isRequired, 121 | children: _react2.default.PropTypes.node.isRequired, 122 | map: _react2.default.PropTypes.object.isRequired, 123 | data: _react2.default.PropTypes.object, 124 | url: _react2.default.PropTypes.string, 125 | type: _react2.default.PropTypes.string.isRequired, 126 | cluster: _react2.default.PropTypes.bool, 127 | clusterMaxZoom: _react2.default.PropTypes.number, 128 | clusterRadius: _react2.default.PropTypes.number, 129 | onClick: _react2.default.PropTypes.func, 130 | tiles: _react2.default.PropTypes.array, 131 | maxZoom: _react2.default.PropTypes.number, 132 | minZoom: _react2.default.PropTypes.number 133 | 134 | }; 135 | exports.default = Source; 136 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9Tb3VyY2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7Ozs7Ozs7O0lBQ3FCLE07OztBQWtCbkIsa0JBQVksS0FBWixFQUFtQjtBQUFBOztBQUFBLDBGQUNYLEtBRFc7O0FBQUEsVUFXbkIsT0FYbUIsR0FXVCxVQUFDLENBQUQsRUFBTztBQUNmLFlBQUssS0FBTCxDQUFXLE9BQVgsQ0FBbUIsQ0FBbkIsRUFBc0IsTUFBSyxxQkFBM0IsRUFBa0QsTUFBSyxLQUFMLENBQVcsR0FBN0Q7QUFDRCxLQWJrQjs7QUFBQSxVQWVuQixxQkFmbUIsR0FlSyxVQUFDLENBQUQsRUFBTztBQUM3QixjQUFRLEdBQVIsQ0FBWSxnQkFBTSxRQUFOLENBQWUsR0FBZixDQUFtQixNQUFLLEtBQUwsQ0FBVyxRQUE5QixFQUF3QztBQUFBLGVBQVMsTUFBTSxLQUFOLENBQVksSUFBckI7QUFBQSxPQUF4QyxDQUFaO0FBQ0EsYUFBTyxNQUFLLEtBQUwsQ0FBVyxHQUFYLENBQWUscUJBQWYsQ0FBcUMsQ0FBckMsRUFBd0M7QUFDN0MsZ0JBQVEsZ0JBQU0sUUFBTixDQUFlLEdBQWYsQ0FBbUIsTUFBSyxLQUFMLENBQVcsUUFBOUIsRUFBd0M7QUFBQSxpQkFBUyxNQUFNLEtBQU4sQ0FBWSxJQUFyQjtBQUFBLFNBQXhDO0FBRHFDLE9BQXhDLENBQVA7QUFHRCxLQXBCa0I7O0FBQUEsVUF5Q25CLGFBekNtQixHQXlDSDtBQUFBLGFBQU0sZ0JBQU0sUUFBTixDQUFlLEdBQWYsQ0FBbUIsTUFBSyxLQUFMLENBQVcsUUFBOUIsRUFDckIsVUFBQyxLQUFEO0FBQUEsZUFBVyxnQkFBTSxZQUFOLENBQW1CLEtBQW5CLEVBQTBCO0FBQ25DLG1CQUFTLE1BQUssS0FBTCxDQUFXLElBRGU7QUFFbkMsZUFBSyxNQUFLLEtBQUwsQ0FBVztBQUZtQixTQUExQixDQUFYO0FBQUEsT0FEcUIsQ0FBTjtBQUFBLEtBekNHOztBQUVqQixVQUFLLEtBQUwsR0FBYTtBQUNYLFlBQU0sTUFBSyxLQUFMLENBQVc7QUFETixLQUFiO0FBR0EsVUFBSyxTQUFMLENBQWUsS0FBZjtBQUNBLFFBQUksTUFBTSxPQUFWLEVBQW1CO0FBQ2pCLFlBQU0sR0FBTixDQUFVLEVBQVYsQ0FBYSxPQUFiLEVBQXNCLE1BQUssT0FBM0I7QUFDRDtBQVJnQjtBQVNsQjs7Ozt3Q0FZbUIsUyxFQUFXO0FBQzdCLFVBQUksS0FBSyxLQUFMLENBQVcsSUFBWCxLQUFvQixVQUFVLElBQWxDLEVBQXdDO0FBQ3RDLGdCQUFRLEtBQVIsQ0FBYyxVQUFkLEVBQTBCLEtBQUssS0FBTCxDQUFXLElBQXJDO0FBQ0Esa0JBQVUsR0FBVixDQUFjLFlBQWQsQ0FBMkIsS0FBSyxLQUFMLENBQVcsSUFBdEM7QUFDQSxhQUFLLFNBQUwsQ0FBZSxTQUFmO0FBQ0EsZUFBTyxLQUFLLFFBQUwsQ0FBYztBQUNuQixnQkFBTSxVQUFVO0FBREcsU0FBZCxDQUFQO0FBR0Q7QUFDRCxVQUFJLEtBQUssS0FBTCxDQUFXLElBQVgsS0FBb0IsVUFBVSxJQUFsQyxFQUF3QztBQUN0QyxlQUFPLFVBQVUsR0FBVixDQUFjLFNBQWQsQ0FBd0IsVUFBVSxJQUFsQyxFQUF3QyxPQUF4QyxDQUFnRCxVQUFVLElBQTFELENBQVA7QUFDRDtBQUNGOzs7MkNBRXNCO0FBQ3JCLGNBQVEsS0FBUixDQUFjLFVBQWQsRUFBMEIsS0FBSyxLQUFMLENBQVcsSUFBckM7QUFDQSxVQUFJLEtBQUssS0FBTCxDQUFXLE9BQWYsRUFBd0I7QUFBRSxhQUFLLEtBQUwsQ0FBVyxHQUFYLENBQWUsR0FBZixDQUFtQixPQUFuQixFQUE0QixLQUFLLE9BQWpDO0FBQTRDO0FBQ3RFLFdBQUssS0FBTCxDQUFXLEdBQVgsQ0FBZSxZQUFmLENBQTRCLEtBQUssS0FBTCxDQUFXLElBQXZDO0FBQ0Q7Ozs4QkFTUyxLLEVBQU87QUFDZixVQUFNLE1BQU07QUFDVixjQUFNLE1BQU0sSUFERjtBQUVWLGFBQUssTUFBTSxHQUZEO0FBR1YsY0FBTSxNQUFNLElBSEY7QUFJVixpQkFBUyxNQUFNLE9BSkw7QUFLVix3QkFBZ0IsTUFBTSxjQUxaO0FBTVYsdUJBQWUsTUFBTSxhQU5YO0FBT1YsZUFBTyxNQUFNLEtBUEg7QUFRVixpQkFBUyxNQUFNLE9BUkw7QUFTVixpQkFBUyxNQUFNO0FBVEwsT0FBWjtBQVdBLFlBQU0sR0FBTixDQUFVLFNBQVYsQ0FBb0IsTUFBTSxJQUExQixFQUFnQyxtQkFBTSxHQUFOLENBQWhDO0FBQ0Q7Ozs2QkFDUTtBQUNQLGFBQ0U7QUFBQTtRQUFBO1FBQ0csS0FBSyxLQUFMLENBQVcsSUFBWCxHQUFrQixLQUFLLGFBQUwsRUFBbEIsR0FBeUM7QUFENUMsT0FERjtBQUtEOzs7O0VBdEZpQyxnQkFBTSxTOztBQUFyQixNLENBQ1osUyxHQUFZO0FBQ2pCLFFBQU0sZ0JBQU0sU0FBTixDQUFnQixNQUFoQixDQUF1QixVQURaO0FBRWpCLFlBQVUsZ0JBQU0sU0FBTixDQUFnQixJQUFoQixDQUFxQixVQUZkO0FBR2pCLE9BQUssZ0JBQU0sU0FBTixDQUFnQixNQUFoQixDQUF1QixVQUhYO0FBSWpCLFFBQU0sZ0JBQU0sU0FBTixDQUFnQixNQUpMO0FBS2pCLE9BQUssZ0JBQU0sU0FBTixDQUFnQixNQUxKO0FBTWpCLFFBQU0sZ0JBQU0sU0FBTixDQUFnQixNQUFoQixDQUF1QixVQU5aO0FBT2pCLFdBQVMsZ0JBQU0sU0FBTixDQUFnQixJQVBSO0FBUWpCLGtCQUFnQixnQkFBTSxTQUFOLENBQWdCLE1BUmY7QUFTakIsaUJBQWUsZ0JBQU0sU0FBTixDQUFnQixNQVRkO0FBVWpCLFdBQVMsZ0JBQU0sU0FBTixDQUFnQixJQVZSO0FBV2pCLFNBQU8sZ0JBQU0sU0FBTixDQUFnQixLQVhOO0FBWWpCLFdBQVMsZ0JBQU0sU0FBTixDQUFnQixNQVpSO0FBYWpCLFdBQVMsZ0JBQU0sU0FBTixDQUFnQjs7QUFiUixDO2tCQURBLE0iLCJmaWxlIjoiU291cmNlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7IGNsZWFuIH0gZnJvbSAnLi9oZWxwZXInO1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU291cmNlIGV4dGVuZHMgUmVhY3QuQ29tcG9uZW50IHtcbiAgc3RhdGljIHByb3BUeXBlcyA9IHtcbiAgICBuYW1lOiBSZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLmlzUmVxdWlyZWQsXG4gICAgY2hpbGRyZW46IFJlYWN0LlByb3BUeXBlcy5ub2RlLmlzUmVxdWlyZWQsXG4gICAgbWFwOiBSZWFjdC5Qcm9wVHlwZXMub2JqZWN0LmlzUmVxdWlyZWQsXG4gICAgZGF0YTogUmVhY3QuUHJvcFR5cGVzLm9iamVjdCxcbiAgICB1cmw6IFJlYWN0LlByb3BUeXBlcy5zdHJpbmcsXG4gICAgdHlwZTogUmVhY3QuUHJvcFR5cGVzLnN0cmluZy5pc1JlcXVpcmVkLFxuICAgIGNsdXN0ZXI6IFJlYWN0LlByb3BUeXBlcy5ib29sLFxuICAgIGNsdXN0ZXJNYXhab29tOiBSZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuICAgIGNsdXN0ZXJSYWRpdXM6IFJlYWN0LlByb3BUeXBlcy5udW1iZXIsXG4gICAgb25DbGljazogUmVhY3QuUHJvcFR5cGVzLmZ1bmMsXG4gICAgdGlsZXM6IFJlYWN0LlByb3BUeXBlcy5hcnJheSxcbiAgICBtYXhab29tOiBSZWFjdC5Qcm9wVHlwZXMubnVtYmVyLFxuICAgIG1pblpvb206IFJlYWN0LlByb3BUeXBlcy5udW1iZXIsXG5cbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpO1xuICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICBuYW1lOiB0aGlzLnByb3BzLm5hbWUsXG4gICAgfTtcbiAgICB0aGlzLmFkZFNvdXJjZShwcm9wcyk7XG4gICAgaWYgKHByb3BzLm9uQ2xpY2spIHtcbiAgICAgIHByb3BzLm1hcC5vbignY2xpY2snLCB0aGlzLm9uQ2xpY2spO1xuICAgIH1cbiAgfVxuXG4gIG9uQ2xpY2sgPSAoZSkgPT4ge1xuICAgIHRoaXMucHJvcHMub25DbGljayhlLCB0aGlzLnF1ZXJ5UmVuZGVyZWRGZWF0dXJlcywgdGhpcy5wcm9wcy5tYXApO1xuICB9XG5cbiAgcXVlcnlSZW5kZXJlZEZlYXR1cmVzID0gKGUpID0+IHtcbiAgICBjb25zb2xlLmxvZyhSZWFjdC5DaGlsZHJlbi5tYXAodGhpcy5wcm9wcy5jaGlsZHJlbiwgY2hpbGQgPT4gY2hpbGQucHJvcHMubmFtZSkpXG4gICAgcmV0dXJuIHRoaXMucHJvcHMubWFwLnF1ZXJ5UmVuZGVyZWRGZWF0dXJlcyhlLCB7XG4gICAgICBsYXllcnM6IFJlYWN0LkNoaWxkcmVuLm1hcCh0aGlzLnByb3BzLmNoaWxkcmVuLCBjaGlsZCA9PiBjaGlsZC5wcm9wcy5uYW1lKSxcbiAgICB9KTtcbiAgfVxuICBjb21wb25lbnRXaWxsVXBkYXRlKG5leHRQcm9wcykge1xuICAgIGlmICh0aGlzLnByb3BzLm5hbWUgIT09IG5leHRQcm9wcy5uYW1lKSB7XG4gICAgICBjb25zb2xlLmRlYnVnKCdyZW1vdmluZycsIHRoaXMucHJvcHMubmFtZSk7XG4gICAgICBuZXh0UHJvcHMubWFwLnJlbW92ZVNvdXJjZSh0aGlzLnByb3BzLm5hbWUpO1xuICAgICAgdGhpcy5hZGRTb3VyY2UobmV4dFByb3BzKTtcbiAgICAgIHJldHVybiB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgbmFtZTogbmV4dFByb3BzLm5hbWUsXG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHRoaXMucHJvcHMuZGF0YSAhPT0gbmV4dFByb3BzLmRhdGEpIHtcbiAgICAgIHJldHVybiBuZXh0UHJvcHMubWFwLmdldFNvdXJjZShuZXh0UHJvcHMubmFtZSkuc2V0RGF0YShuZXh0UHJvcHMuZGF0YSk7XG4gICAgfVxuICB9XG5cbiAgY29tcG9uZW50V2lsbFVubW91bnQoKSB7XG4gICAgY29uc29sZS5kZWJ1ZygncmVtb3ZpbmcnLCB0aGlzLnByb3BzLm5hbWUpO1xuICAgIGlmICh0aGlzLnByb3BzLm9uQ2xpY2spIHsgdGhpcy5wcm9wcy5tYXAub2ZmKCdjbGljaycsIHRoaXMub25DbGljayk7IH1cbiAgICB0aGlzLnByb3BzLm1hcC5yZW1vdmVTb3VyY2UodGhpcy5zdGF0ZS5uYW1lKTtcbiAgfVxuXG4gIGNsb25lQ2hpbGRyZW4gPSAoKSA9PiBSZWFjdC5DaGlsZHJlbi5tYXAodGhpcy5wcm9wcy5jaGlsZHJlbixcbiAgIChjaGlsZCkgPT4gUmVhY3QuY2xvbmVFbGVtZW50KGNoaWxkLCB7XG4gICAgIF9zb3VyY2U6IHRoaXMucHJvcHMubmFtZSxcbiAgICAgbWFwOiB0aGlzLnByb3BzLm1hcCxcbiAgIH0pXG4gICk7XG5cbiAgYWRkU291cmNlKHByb3BzKSB7XG4gICAgY29uc3Qgb2JqID0ge1xuICAgICAgdHlwZTogcHJvcHMudHlwZSxcbiAgICAgIHVybDogcHJvcHMudXJsLFxuICAgICAgZGF0YTogcHJvcHMuZGF0YSxcbiAgICAgIGNsdXN0ZXI6IHByb3BzLmNsdXN0ZXIsXG4gICAgICBjbHVzdGVyTWF4Wm9vbTogcHJvcHMuY2x1c3Rlck1heFpvb20sXG4gICAgICBjbHVzdGVyUmFkaXVzOiBwcm9wcy5jbHVzdGVyUmFkaXVzLFxuICAgICAgdGlsZXM6IHByb3BzLnRpbGVzLFxuICAgICAgbWF4Wm9vbTogcHJvcHMubWF4Wm9vbSxcbiAgICAgIG1pblpvb206IHByb3BzLm1pblpvb20sXG4gICAgfTtcbiAgICBwcm9wcy5tYXAuYWRkU291cmNlKHByb3BzLm5hbWUsIGNsZWFuKG9iaikpO1xuICB9XG4gIHJlbmRlcigpIHtcbiAgICByZXR1cm4gKFxuICAgICAgPGRpdj5cbiAgICAgICAge3RoaXMucHJvcHMubmFtZSA/IHRoaXMuY2xvbmVDaGlsZHJlbigpIDogbnVsbH1cbiAgICAgIDwvZGl2PlxuICAgICk7XG4gIH1cbn1cbiJdfQ== -------------------------------------------------------------------------------- /bundle/Symbol.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 8 | 9 | var _react = require('react'); 10 | 11 | var _react2 = _interopRequireDefault(_react); 12 | 13 | var _Layer = require('./Layer'); 14 | 15 | var _Layer2 = _interopRequireDefault(_Layer); 16 | 17 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 18 | 19 | var _Symbol = function _Symbol(_ref) { 20 | var name = _ref.name; 21 | var _source = _ref._source; 22 | var filter = _ref.filter; 23 | var layout = _ref.layout; 24 | var map = _ref.map; 25 | var sourceLayer = _ref.sourceLayer; 26 | var visibility = _ref.visibility; 27 | var style = _ref.style; 28 | var paint = _ref.paint; 29 | 30 | return _react2.default.createElement(_Layer2.default, { 31 | name: name, 32 | _source: _source, 33 | type: 'symbol', 34 | map: map, 35 | style: _extends({}, style, { 36 | layout: layout, 37 | paint: paint 38 | }), 39 | filter: filter, 40 | sourceLayer: sourceLayer, 41 | visibility: visibility 42 | }); 43 | }; 44 | 45 | _Symbol.propTypes = { 46 | name: _react2.default.PropTypes.string, 47 | _source: _react2.default.PropTypes.string, 48 | map: _react2.default.PropTypes.object, 49 | filter: _react2.default.PropTypes.array, 50 | layout: _react2.default.PropTypes.object, 51 | visibility: _react2.default.PropTypes.string, 52 | sourceLayer: _react2.default.PropTypes.string, 53 | style: _react2.default.PropTypes.object, 54 | paint: _react2.default.PropTypes.object 55 | }; 56 | 57 | exports.default = _Symbol; 58 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9TeW1ib2wuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFBQTs7OztBQUNBOzs7Ozs7QUFDQSxJQUFNLFVBQVMsU0FBVCxPQUFTLE9BQW1GO0FBQUEsTUFBaEYsSUFBZ0YsUUFBaEYsSUFBZ0Y7QUFBQSxNQUExRSxPQUEwRSxRQUExRSxPQUEwRTtBQUFBLE1BQWpFLE1BQWlFLFFBQWpFLE1BQWlFO0FBQUEsTUFBekQsTUFBeUQsUUFBekQsTUFBeUQ7QUFBQSxNQUFqRCxHQUFpRCxRQUFqRCxHQUFpRDtBQUFBLE1BQTVDLFdBQTRDLFFBQTVDLFdBQTRDO0FBQUEsTUFBL0IsVUFBK0IsUUFBL0IsVUFBK0I7QUFBQSxNQUFuQixLQUFtQixRQUFuQixLQUFtQjtBQUFBLE1BQVosS0FBWSxRQUFaLEtBQVk7O0FBQ2hHLFNBQ0U7QUFDRSxVQUFNLElBRFI7QUFFRSxhQUFTLE9BRlg7QUFHRSxVQUFLLFFBSFA7QUFJRSxTQUFLLEdBSlA7QUFLRSx3QkFDSyxLQURMO0FBRUUsb0JBRkY7QUFHRTtBQUhGLE1BTEY7QUFVRSxZQUFRLE1BVlY7QUFXRSxpQkFBYSxXQVhmO0FBWUUsZ0JBQVk7QUFaZCxJQURGO0FBZ0JELENBakJEOztBQW1CQSxRQUFPLFNBQVAsR0FBbUI7QUFDakIsUUFBTSxnQkFBTSxTQUFOLENBQWdCLE1BREw7QUFFakIsV0FBUyxnQkFBTSxTQUFOLENBQWdCLE1BRlI7QUFHakIsT0FBSyxnQkFBTSxTQUFOLENBQWdCLE1BSEo7QUFJakIsVUFBUSxnQkFBTSxTQUFOLENBQWdCLEtBSlA7QUFLakIsVUFBUSxnQkFBTSxTQUFOLENBQWdCLE1BTFA7QUFNakIsY0FBWSxnQkFBTSxTQUFOLENBQWdCLE1BTlg7QUFPakIsZUFBYSxnQkFBTSxTQUFOLENBQWdCLE1BUFo7QUFRakIsU0FBTyxnQkFBTSxTQUFOLENBQWdCLE1BUk47QUFTakIsU0FBTyxnQkFBTSxTQUFOLENBQWdCO0FBVE4sQ0FBbkI7O2tCQVllLE8iLCJmaWxlIjoiU3ltYm9sLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCBMYXllciBmcm9tICcuL0xheWVyJztcbmNvbnN0IFN5bWJvbCA9ICh7IG5hbWUsIF9zb3VyY2UsIGZpbHRlciwgbGF5b3V0LCBtYXAsIHNvdXJjZUxheWVyLCB2aXNpYmlsaXR5LCBzdHlsZSwgcGFpbnQgfSkgPT4ge1xuICByZXR1cm4gKFxuICAgIDxMYXllclxuICAgICAgbmFtZT17bmFtZX1cbiAgICAgIF9zb3VyY2U9e19zb3VyY2V9XG4gICAgICB0eXBlPVwic3ltYm9sXCJcbiAgICAgIG1hcD17bWFwfVxuICAgICAgc3R5bGU9e3tcbiAgICAgICAgLi4uc3R5bGUsXG4gICAgICAgIGxheW91dCxcbiAgICAgICAgcGFpbnQsXG4gICAgICB9fVxuICAgICAgZmlsdGVyPXtmaWx0ZXJ9XG4gICAgICBzb3VyY2VMYXllcj17c291cmNlTGF5ZXJ9XG4gICAgICB2aXNpYmlsaXR5PXt2aXNpYmlsaXR5fVxuICAgIC8+XG4gICk7XG59O1xuXG5TeW1ib2wucHJvcFR5cGVzID0ge1xuICBuYW1lOiBSZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuICBfc291cmNlOiBSZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuICBtYXA6IFJlYWN0LlByb3BUeXBlcy5vYmplY3QsXG4gIGZpbHRlcjogUmVhY3QuUHJvcFR5cGVzLmFycmF5LFxuICBsYXlvdXQ6IFJlYWN0LlByb3BUeXBlcy5vYmplY3QsXG4gIHZpc2liaWxpdHk6IFJlYWN0LlByb3BUeXBlcy5zdHJpbmcsXG4gIHNvdXJjZUxheWVyOiBSZWFjdC5Qcm9wVHlwZXMuc3RyaW5nLFxuICBzdHlsZTogUmVhY3QuUHJvcFR5cGVzLm9iamVjdCxcbiAgcGFpbnQ6IFJlYWN0LlByb3BUeXBlcy5vYmplY3QsXG59O1xuXG5leHBvcnQgZGVmYXVsdCBTeW1ib2w7XG5cbiJdfQ== -------------------------------------------------------------------------------- /bundle/helper.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.clean = clean; 7 | function clean(argObj) { 8 | var obj = argObj; 9 | Object.keys(obj).forEach(function (key) { 10 | if (typeof obj[key] === 'undefined') { 11 | delete obj[key]; 12 | } 13 | }); 14 | return obj; 15 | } 16 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9oZWxwZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7UUFBZ0IsSyxHQUFBLEs7QUFBVCxTQUFTLEtBQVQsQ0FBZSxNQUFmLEVBQXVCO0FBQzVCLE1BQU0sTUFBTSxNQUFaO0FBQ0EsU0FBTyxJQUFQLENBQVksR0FBWixFQUFpQixPQUFqQixDQUF5QixVQUFDLEdBQUQsRUFBUztBQUNoQyxRQUFJLE9BQU8sSUFBSSxHQUFKLENBQVAsS0FBb0IsV0FBeEIsRUFBcUM7QUFDbkMsYUFBTyxJQUFJLEdBQUosQ0FBUDtBQUNEO0FBQ0YsR0FKRDtBQUtBLFNBQU8sR0FBUDtBQUNEIiwiZmlsZSI6ImhlbHBlci5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBmdW5jdGlvbiBjbGVhbihhcmdPYmopIHtcbiAgY29uc3Qgb2JqID0gYXJnT2JqO1xuICBPYmplY3Qua2V5cyhvYmopLmZvckVhY2goKGtleSkgPT4ge1xuICAgIGlmICh0eXBlb2Ygb2JqW2tleV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBkZWxldGUgb2JqW2tleV07XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIG9iajtcbn1cbiJdfQ== -------------------------------------------------------------------------------- /bundle/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.Line = exports.Symbol = exports.Source = exports.Layer = exports.Circle = exports.Map = undefined; 7 | 8 | var _Map = require('./Map'); 9 | 10 | var _Map2 = _interopRequireDefault(_Map); 11 | 12 | var _Circle = require('./Circle'); 13 | 14 | var _Circle2 = _interopRequireDefault(_Circle); 15 | 16 | var _Layer = require('./Layer'); 17 | 18 | var _Layer2 = _interopRequireDefault(_Layer); 19 | 20 | var _Source = require('./Source'); 21 | 22 | var _Source2 = _interopRequireDefault(_Source); 23 | 24 | var _Symbol2 = require('./Symbol'); 25 | 26 | var _Symbol3 = _interopRequireDefault(_Symbol2); 27 | 28 | var _Line = require('./Line'); 29 | 30 | var _Line2 = _interopRequireDefault(_Line); 31 | 32 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 33 | 34 | exports.Map = _Map2.default; 35 | exports.Circle = _Circle2.default; 36 | exports.Layer = _Layer2.default; 37 | exports.Source = _Source2.default; 38 | exports.Symbol = _Symbol3.default; 39 | exports.Line = _Line2.default; 40 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9pbmRleC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7Ozs7UUFFUyxHO1FBQUssTTtRQUFRLEs7UUFBTyxNO1FBQVEsTTtRQUFRLEkiLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgTWFwIGZyb20gJy4vTWFwJztcbmltcG9ydCBDaXJjbGUgZnJvbSAnLi9DaXJjbGUnO1xuaW1wb3J0IExheWVyIGZyb20gJy4vTGF5ZXInO1xuaW1wb3J0IFNvdXJjZSBmcm9tICcuL1NvdXJjZSc7XG5pbXBvcnQgU3ltYm9sIGZyb20gJy4vU3ltYm9sJztcbmltcG9ydCBMaW5lIGZyb20gJy4vTGluZSc7XG5cbmV4cG9ydCB7IE1hcCwgQ2lyY2xlLCBMYXllciwgU291cmNlLCBTeW1ib2wsIExpbmUgfTtcblxuIl19 -------------------------------------------------------------------------------- /examples/CenterOnSymbol.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Map from '../lib/Map'; 3 | import Source from '../lib/Source'; 4 | import Symbol from '../lib/Symbol'; 5 | import mapboxgl from 'mapbox-gl'; 6 | import GL_TOKEN from '../app/token'; 7 | 8 | mapboxgl.accessToken = GL_TOKEN; 9 | 10 | export default class CenterOnSymbol extends React.Component { 11 | 12 | state = { 13 | map: null, 14 | } 15 | coords = [ 16 | [-91.395263671875, -0.9145729757782163], 17 | [-90.32958984375, -0.6344474832838974], 18 | [-91.34033203125, 0.01647949196029245], 19 | ] 20 | 21 | makeData = () => ({ 22 | type: 'FeatureCollection', 23 | features: this.coords.map((c) => ({ 24 | type: 'Feature', 25 | properties: {}, 26 | geometry: { 27 | type: 'Point', 28 | coordinates: c, 29 | }, 30 | }) 31 | ), 32 | }) 33 | 34 | handleClick = (e, query, map) => { 35 | const feat = query(e.point); 36 | if (feat.length > 0) { 37 | this.state.map.flyTo({ 38 | center: feat[0].geometry.coordinates, 39 | }); 40 | } 41 | } 42 | 43 | render() { 44 | return ( 45 |
46 | fly 47 | this.setState({ map })} 52 | mapboxgl={mapboxgl} 53 | > 54 | 60 | 64 | 65 | 66 |
67 | 68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /examples/Cluster.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Map from '../lib/Map'; 3 | import Source from '../lib/Source'; 4 | import Symbol from '../lib/Symbol'; 5 | import Circle from '../lib/Circle'; 6 | import mapboxgl from 'mapbox-gl'; 7 | import GL_TOKEN from '../app/token'; 8 | 9 | mapboxgl.accessToken = GL_TOKEN; 10 | var layers = [ 11 | [150, '#f28cb1'], 12 | [20, '#f1f075'], 13 | [0, '#51bbd6'] 14 | ]; 15 | 16 | export default () => 17 | 23 | 31 | 37 | {layers.map((layer, i) => 38 | =', 'point_count', layer[0]] : 47 | ['all', 48 | ['>=', 'point_count', layer[0]], 49 | ['<', 'point_count', layers[i - 1][0]]] 50 | } 51 | /> 52 | )} 53 | 64 | 65 | 66 | 67 | ; 68 | -------------------------------------------------------------------------------- /examples/ColorSwitcher.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Map from '../lib/Map'; 3 | import Source from '../lib/Source'; 4 | import Symbol from '../lib/Symbol'; 5 | import mapboxgl from 'mapbox-gl'; 6 | import GL_TOKEN from '../app/token'; 7 | 8 | mapboxgl.accessToken = GL_TOKEN; 9 | export default class CenterOnSymbol extends React.Component { 10 | 11 | state = { 12 | map: null, 13 | } 14 | coords = [ 15 | [-91.395263671875, -0.9145729757782163], 16 | [-90.32958984375, -0.6344474832838974], 17 | [-91.34033203125, 0.01647949196029245], 18 | ] 19 | 20 | makeData = () => ({ 21 | type: 'FeatureCollection', 22 | features: this.coords.map((c) => ({ 23 | type: 'Feature', 24 | properties: {}, 25 | geometry: { 26 | type: 'Point', 27 | coordinates: c, 28 | }, 29 | }) 30 | ), 31 | }) 32 | 33 | handleClick = (e, query, map) => { 34 | const feat = query(e.point); 35 | if (feat.length > 0) { 36 | this.state.map.flyTo({ 37 | center: feat[0].geometry.coordinates, 38 | }); 39 | } 40 | } 41 | 42 | render() { 43 | return ( 44 |
45 | fly 46 | this.setState({ map })} 51 | mapboxgl={mapboxgl} 52 | > 53 | 59 | 63 | 64 | 65 |
66 | 67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /examples/DisplayMap.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Map from '../lib/Map'; 3 | import mapboxgl from 'mapbox-gl'; 4 | import GL_TOKEN from '../app/token'; 5 | 6 | mapboxgl.accessToken = GL_TOKEN; 7 | export default () => 8 | 15 | ; 16 | -------------------------------------------------------------------------------- /examples/FitBounds.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Map from '../lib/Map'; 3 | import mapboxgl from 'mapbox-gl'; 4 | import GL_TOKEN from '../app/token'; 5 | 6 | mapboxgl.accessToken = GL_TOKEN; 7 | export default class FitBounds extends React.Component { 8 | map = null 9 | goToKenya = () => { 10 | if (this.map) { 11 | this.map.fitBounds([[ 12 | 32.958984, 13 | -5.353521, 14 | ], [ 15 | 43.50585, 16 | 5.615985, 17 | ]]); 18 | } 19 | } 20 | render() { 21 | return ( 22 |
23 | Go To Kenya 24 | { this.map = map; }} 29 | mapboxgl={mapboxgl} 30 | /> 31 |
32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/SetStyle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Map from '../lib/Map'; 3 | import mapboxgl from 'mapbox-gl'; 4 | import GL_TOKEN from '../app/token'; 5 | 6 | mapboxgl.accessToken = GL_TOKEN; 7 | const options = [ 8 | 'basic', 'streets', 'emerald', 'bright', 'light', 'dark', 'satellite', 9 | ]; 10 | 11 | export default class SetStyle extends React.Component { 12 | state = { 13 | options: [true].concat(new Array(6).fill(false)), 14 | index: 0, 15 | } 16 | changeIt = (i) => { 17 | const array = new Array(7).fill(false); 18 | array[i] = true; 19 | this.setState({ 20 | options: array, 21 | index: i, 22 | }); 23 | } 24 | render() { 25 | return ( 26 |
27 | 43 |
44 | ); 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /examples/SlowlyFly.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Map from '../lib/Map'; 3 | import mapboxgl from 'mapbox-gl'; 4 | import GL_TOKEN from '../app/token'; 5 | 6 | mapboxgl.accessToken = GL_TOKEN; 7 | export default class SlowlyFly extends React.Component { 8 | 9 | isAtStart: true 10 | map = null 11 | start = [-74.50, 40] 12 | end = [74.50, 40] 13 | flyto = () => { 14 | if (this.map) { 15 | const target = this.isAtStart ? this.end : this.start; 16 | this.isAtStart = !this.isAtStart; 17 | this.map.flyTo({ 18 | // These options control the ending camera position: centered at 19 | // the target, at zoom level 9, and north up. 20 | center: target, 21 | zoom: 9, 22 | bearing: 0, 23 | 24 | // These options control the flight curve, making it move 25 | // slowly and zoom out almost completely before starting 26 | // to pan. 27 | speed: 0.2, // make the flying slow 28 | curve: 1, // change the speed at which it zooms out 29 | 30 | // This can be any easing function: it takes a number between 31 | // 0 and 1 and returns another number between 0 and 1. 32 | easing: (t) => t, 33 | }); 34 | } 35 | } 36 | render() { 37 | return ( 38 |
39 | fly 40 | { this.map = map; }} 45 | mapboxgl={mapboxgl} 46 | /> 47 |
48 | 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /examples/ToggleLayer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Map from '../lib/Map'; 3 | import Source from '../lib/Source'; 4 | import Circle from '../lib/Circle'; 5 | import Line from '../lib/Line'; 6 | import mapboxgl from 'mapbox-gl'; 7 | import GL_TOKEN from '../app/token'; 8 | 9 | mapboxgl.accessToken = GL_TOKEN; 10 | export default class ToggleLayer extends React.Component { 11 | 12 | state = { 13 | contours: 'visible', 14 | museums: 'visible', 15 | } 16 | 17 | render() { 18 | return ( 19 |
20 |
21 | this.setState({ contours: this.state.contours === 'visible' ? 'none' : 'visible' })}>Contour 22 | this.setState({ museums: this.state.museums === 'visible' ? 'none' : 'visible' })}> Museums 23 |
24 | 30 | 35 | 44 | 45 | 50 | 63 | 64 | 65 |
66 | ); 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /examples/VectorSource.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Map from '../lib/Map'; 3 | import Source from '../lib/Source'; 4 | import Line from '../lib/Line'; 5 | import mapboxgl from 'mapbox-gl'; 6 | import GL_TOKEN from '../app/token'; 7 | 8 | mapboxgl.accessToken = GL_TOKEN; 9 | export default () => 10 | 16 | 21 | 33 | 34 | 35 | ; 36 | -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kepta/maps-react/117aa399eabaf2ad899f393e41c93968a7a46766/examples/index.js -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | manifest="<%= htmlWebpackPlugin.files.manifest %>"<% } %>> 7 | 8 | 9 | <%= htmlWebpackPlugin.options.title || 'Webpack App'%> 10 | <% if (htmlWebpackPlugin.files.favicon) { %> 11 | 12 | <% } %> 13 | <% if (htmlWebpackPlugin.options.mobile) { %> 14 | 15 | <% } %> 16 | 17 | <% for (var css in htmlWebpackPlugin.files.css) { %> 18 | 19 | <% } %> 20 | 21 | <% if (htmlWebpackPlugin.options.baseHref) { %> 22 | 23 | <% } %> 24 | 25 | 26 | 27 | 28 | <% if (htmlWebpackPlugin.options.unsupportedBrowser) { %> 29 | 30 |
31 | Sorry, your browser is not supported. Please upgrade to 32 | the latest version or switch your browser to use this site. 33 | See outdatedbrowser.com 34 | for options. 35 |
36 | <% } %> 37 | 38 | <% if (htmlWebpackPlugin.options.appMountId) { %> 39 |
40 | <% } %> 41 | 42 | <% if (htmlWebpackPlugin.options.appMountIds && htmlWebpackPlugin.options.appMountIds.length > 0) { %> 43 | <% for (var index in htmlWebpackPlugin.options.appMountIds) { %> 44 |
45 | <% } %> 46 | <% } %> 47 | 48 | <% if (htmlWebpackPlugin.options.window) { %> 49 | 54 | <% } %> 55 | 56 | <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> 57 | 58 | <% } %> 59 | 60 | <% if (htmlWebpackPlugin.options.devServer) { %> 61 | 62 | <% } %> 63 | 64 | <% if (htmlWebpackPlugin.options.googleAnalytics) { %> 65 | 75 | <% } %> 76 | 77 | 78 | -------------------------------------------------------------------------------- /lib/Circle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Layer from './Layer'; 3 | const Circle = ({ name, _source, filter, paint, map, sourceLayer, visibility }) => 4 | ; 14 | 15 | Circle.propTypes = { 16 | name: React.PropTypes.string, 17 | _source: React.PropTypes.string, 18 | sourceLayer: React.PropTypes.string, 19 | visibility: React.PropTypes.string, 20 | map: React.PropTypes.object, 21 | filter: React.PropTypes.array, 22 | paint: React.PropTypes.shape({ 23 | 'circle-radius': React.PropTypes.number, 24 | 'circle-color': React.PropTypes.string, 25 | 'circle-blur': React.PropTypes.number, 26 | 'circle-opacity': React.PropTypes.number, 27 | 'circle-translate': React.PropTypes.array, 28 | 'circle-translate-anchor': React.PropTypes.oneOf(['map', 'viewport']), 29 | }), 30 | }; 31 | 32 | export default Circle; 33 | -------------------------------------------------------------------------------- /lib/Layer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { clean } from './helper'; 3 | 4 | export default class Layer extends React.Component { 5 | static propTypes = { 6 | name: React.PropTypes.string.isRequired, 7 | _source: React.PropTypes.string, 8 | map: React.PropTypes.object, 9 | style: React.PropTypes.object.isRequired, 10 | filter: React.PropTypes.array, 11 | type: React.PropTypes.string.isRequired, 12 | sourceLayer: React.PropTypes.string, 13 | visibility: React.PropTypes.string, 14 | } 15 | 16 | constructor(props) { 17 | super(props); 18 | this.layer = this.addLayer(props); 19 | } 20 | componentWillUpdate(nextProps) { 21 | if (nextProps.name !== this.props.name && nextProps._source) { 22 | console.debug('removing layer', this.props.name); 23 | nextProps.map.removeLayer(this.props.name); 24 | this.layer = this.addLayer(nextProps); 25 | } 26 | if (this.props.visibility !== nextProps.visibility) { 27 | console.debug('changing visibility'); 28 | nextProps.map.setLayoutProperty(nextProps.name, 'visibility', nextProps.visibility); 29 | } 30 | } 31 | componentWillUnmount() { 32 | console.debug('removing layer', this.props.name); 33 | this.props.map.removeLayer(this.props.name); 34 | } 35 | addLayer = (props) => { 36 | const obj = { 37 | ...clean(props.style), 38 | id: props.name, 39 | source: props._source, 40 | type: props.type, 41 | 'source-layer': props.sourceLayer, 42 | }; 43 | if (props.visibility) { 44 | if (!obj.layout) obj.layout = {}; 45 | obj.layout.visibility = props.visibility; 46 | } 47 | return props.map.addLayer(clean(obj)); 48 | } 49 | render() { 50 | if (this.layer && this.props.filter) { 51 | this.props.map.setFilter(this.props.name, this.props.filter); 52 | } 53 | return ( 54 | null 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /lib/Line.js: -------------------------------------------------------------------------------- 1 | 2 | import React from 'react'; 3 | import Layer from './Layer'; 4 | const Line = ({ name, _source, filter, paint, map, sourceLayer, visibility, layout }) => 5 | ; 16 | 17 | Line.propTypes = { 18 | name: React.PropTypes.string, 19 | _source: React.PropTypes.string, 20 | sourceLayer: React.PropTypes.string, 21 | visibility: React.PropTypes.string, 22 | map: React.PropTypes.object, 23 | filter: React.PropTypes.array, 24 | paint: React.PropTypes.object, 25 | layout: React.PropTypes.object, 26 | }; 27 | 28 | export default Line; 29 | -------------------------------------------------------------------------------- /lib/Map.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { clean } from './helper'; 3 | 4 | export default class Map extends React.Component { 5 | static propTypes = { 6 | children: React.PropTypes.element, 7 | center: React.PropTypes.array, 8 | onLoad: React.PropTypes.func, 9 | style: React.PropTypes.string, 10 | zoom: React.PropTypes.number, 11 | pitch: React.PropTypes.number, 12 | bearing: React.PropTypes.number, 13 | mapboxgl: React.PropTypes.object.isRequired, 14 | } 15 | 16 | static defaultProps = { 17 | center: [-77.0152, 38.8937], 18 | zoom: 16, 19 | pitch: 0, 20 | style: 'mapbox://styles/mapbox/satellite-streets-v9', 21 | onLoad: () => {}, 22 | } 23 | state = { 24 | map: null, 25 | } 26 | componentDidMount() { 27 | const map = new this.props.mapboxgl.Map({ 28 | container: 'map', 29 | style: this.props.style, // stylesheet location 30 | center: this.props.center, 31 | zoom: this.props.zoom, 32 | pitch: this.props.pitch, 33 | }); 34 | map.on('load', () => { 35 | this.setState({ 36 | map, 37 | }); 38 | this.props.onLoad(map); 39 | }); 40 | } 41 | componentWillUpdate(nextProps, nextState) { 42 | if (nextState.map) { 43 | if (nextProps.style !== this.props.style) { 44 | this.state.map.setStyle(nextProps.style); 45 | } 46 | } 47 | } 48 | sendProps = () => { 49 | return React.Children.map(this.props.children, 50 | (child) => React.cloneElement(child, { 51 | map: this.state.map, 52 | }) 53 | ); 54 | } 55 | render() { 56 | // console.log(this.state.map); 57 | return ( 58 |
59 |
60 | { 61 | this.state.map ? 62 | this.sendProps() 63 | : null 64 | } 65 |
66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lib/Source.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { clean } from './helper'; 3 | export default class Source extends React.Component { 4 | static propTypes = { 5 | name: React.PropTypes.string.isRequired, 6 | children: React.PropTypes.node.isRequired, 7 | map: React.PropTypes.object, 8 | data: React.PropTypes.any, 9 | url: React.PropTypes.string, 10 | type: React.PropTypes.string.isRequired, 11 | cluster: React.PropTypes.bool, 12 | clusterMaxZoom: React.PropTypes.number, 13 | clusterRadius: React.PropTypes.number, 14 | onClick: React.PropTypes.func, 15 | tiles: React.PropTypes.array, 16 | maxZoom: React.PropTypes.number, 17 | minZoom: React.PropTypes.number, 18 | 19 | } 20 | 21 | constructor(props) { 22 | super(props); 23 | this.state = { 24 | name: this.props.name, 25 | }; 26 | this.addSource(props); 27 | if (props.onClick) { 28 | props.map.on('click', this.onClick); 29 | } 30 | } 31 | 32 | onClick = (e) => { 33 | this.props.onClick(e, this.queryRenderedFeatures, this.props.map); 34 | } 35 | 36 | queryRenderedFeatures = (e) => { 37 | console.log(React.Children.map(this.props.children, child => child.props.name)) 38 | return this.props.map.queryRenderedFeatures(e, { 39 | layers: React.Children.map(this.props.children, child => child.props.name), 40 | }); 41 | } 42 | componentWillUpdate(nextProps) { 43 | if (this.props.name !== nextProps.name) { 44 | console.debug('removing', this.props.name); 45 | nextProps.map.removeSource(this.props.name); 46 | this.addSource(nextProps); 47 | return this.setState({ 48 | name: nextProps.name, 49 | }); 50 | } 51 | if (this.props.data !== nextProps.data) { 52 | return nextProps.map.getSource(nextProps.name).setData(nextProps.data); 53 | } 54 | } 55 | 56 | componentWillUnmount() { 57 | console.debug('removing', this.props.name); 58 | if (this.props.onClick) { this.props.map.off('click', this.onClick); } 59 | this.props.map.removeSource(this.state.name); 60 | } 61 | 62 | cloneChildren = () => React.Children.map(this.props.children, 63 | (child) => React.cloneElement(child, { 64 | _source: this.props.name, 65 | map: this.props.map, 66 | }) 67 | ); 68 | 69 | addSource(props) { 70 | const obj = { 71 | type: props.type, 72 | url: props.url, 73 | data: props.data, 74 | cluster: props.cluster, 75 | clusterMaxZoom: props.clusterMaxZoom, 76 | clusterRadius: props.clusterRadius, 77 | tiles: props.tiles, 78 | maxZoom: props.maxZoom, 79 | minZoom: props.minZoom, 80 | }; 81 | props.map.addSource(props.name, clean(obj)); 82 | } 83 | render() { 84 | return ( 85 |
86 | {this.props.name ? this.cloneChildren() : null} 87 |
88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lib/Symbol.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Layer from './Layer'; 3 | const Symbol = ({ name, _source, filter, layout, map, sourceLayer, visibility, paint }) => { 4 | return ( 5 | 16 | ); 17 | }; 18 | 19 | Symbol.propTypes = { 20 | name: React.PropTypes.string, 21 | _source: React.PropTypes.string, 22 | map: React.PropTypes.object, 23 | filter: React.PropTypes.array, 24 | visibility: React.PropTypes.oneOf(['visible', 'none']), 25 | sourceLayer: React.PropTypes.string, 26 | layout: React.PropTypes.shape({ 27 | 'symbol-placement': React.PropTypes.oneOf(['point', 'line']), 28 | 'symbol-spacing': React.PropTypes.number, 29 | 'symbol-avoid-edges': React.PropTypes.bool, 30 | 'icon-allow-overlap': React.PropTypes.bool, 31 | 'icon-ignore-placement': React.PropTypes.bool, 32 | 'icon-optional': React.PropTypes.bool, 33 | 'icon-rotation-alignment': React.PropTypes.oneOf(['map', 'viewport']), 34 | 'icon-size': React.PropTypes.number, 35 | 'icon-text-fit': React.PropTypes.oneOf(['none', 'both', 'width', 'height']), 36 | 'icon-text-fit-padding': React.PropTypes.array, 37 | 'icon-image': React.PropTypes.string, 38 | 'icon-rotate': React.PropTypes.number, 39 | 'icon-padding': React.PropTypes.number, 40 | 'icon-keep-upright': React.PropTypes.bool, 41 | 'icon-offset': React.PropTypes.array, 42 | 'text-pitch-alignment': React.PropTypes.oneOf(['map', 'viewport']), 43 | 'text-rotation-alignment': React.PropTypes.oneOf(['map', 'viewport']), 44 | 'text-field': React.PropTypes.string, 45 | 'text-font': React.PropTypes.array, 46 | 'text-size': React.PropTypes.number, 47 | 'text-max-width': React.PropTypes.number, 48 | 'text-line-height': React.PropTypes.number, 49 | 'text-letter-spacing': React.PropTypes.number, 50 | 'text-justify': React.PropTypes.oneOf(['left', 'center', 'right']), 51 | 'text-anchor': React.PropTypes.oneOf(['center', 'left', 'right', 'top', 'bottom', 'top-left', 'top-right', 'bottom-left', 'bottom-right']), 52 | 'text-max-angle': React.PropTypes.number, 53 | 'text-rotate': React.PropTypes.number, 54 | 'text-padding': React.PropTypes.number, 55 | 'text-keep-upright': React.PropTypes.number, 56 | 'text-transform': React.PropTypes.oneOf(['none', 'uppercase', 'lowercase']), 57 | 'text-offset': React.PropTypes.array, 58 | 'text-allow-overlap': React.PropTypes.bool, 59 | 'text-ignore-placement': React.PropTypes.bool, 60 | 'text-optional': React.PropTypes.bool, 61 | }), 62 | paint: React.PropTypes.shape({ 63 | 'icon-opacity': React.PropTypes.number, 64 | 'icon-color': React.PropTypes.string, 65 | 'icon-halo-color': React.PropTypes.string, 66 | 'icon-halo-width': React.PropTypes.number, 67 | 'icon-halo-blur': React.PropTypes.number, 68 | 'icon-translate': React.PropTypes.array, 69 | 'icon-translate-anchor': React.PropTypes.oneOf(['map', 'viewport']), 70 | 'text-opacity': React.PropTypes.number, 71 | 'text-color': React.PropTypes.string, 72 | 'text-halo-color': React.PropTypes.string, 73 | 'text-halo-width': React.PropTypes.number, 74 | 'text-halo-blur': React.PropTypes.number, 75 | 'text-translate': React.PropTypes.array, 76 | 'text-translate-anchor': React.PropTypes.oneOf(['map', 'viewport']), 77 | }), 78 | }; 79 | 80 | export default Symbol; 81 | -------------------------------------------------------------------------------- /lib/helper.js: -------------------------------------------------------------------------------- 1 | export function clean(argObj) { 2 | const obj = argObj; 3 | Object.keys(obj).forEach((key) => { 4 | if (typeof obj[key] === 'undefined') { 5 | delete obj[key]; 6 | } 7 | }); 8 | return obj; 9 | } 10 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | import Map from './Map'; 2 | import Circle from './Circle'; 3 | import Layer from './Layer'; 4 | import Source from './Source'; 5 | import Symbol from './Symbol'; 6 | import Line from './Line'; 7 | 8 | export { Map, Circle, Layer, Source, Symbol, Line }; 9 | 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "maps-react", 3 | "version": "0.0.27", 4 | "description": "", 5 | "main": "bundle/index.js", 6 | "scripts": { 7 | "test": "mocha tests/.setup.js tests/**/*.test.js --compilers js:babel-core/register", 8 | "start": "webpack-dev-server --content-base build", 9 | "build": "webpack", 10 | "lint": "eslint . --ext .js --ext .jsx ", 11 | "prepublish": "babel --source-maps inline --presets es2015,react,stage-0 -d bundle/ lib/ ", 12 | "deploy": "gh-pages -d build" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "babel-cli": "^6.9.0", 18 | "babel-core": "^6.9.0", 19 | "babel-eslint": "^6.0.4", 20 | "babel-loader": "^6.2.4", 21 | "babel-plugin-transform-object-assign": "^6.8.0", 22 | "babel-preset-es2015": "^6.9.0", 23 | "babel-preset-es2015-native-modules": "^6.6.0", 24 | "babel-preset-es2015-rollup": "^1.1.1", 25 | "babel-preset-react": "^6.5.0", 26 | "babel-preset-react-hmre": "^1.1.1", 27 | "babel-preset-stage-0": "^6.5.0", 28 | "babel-preset-survivejs-kanban": "^0.3.3", 29 | "chai": "^3.5.0", 30 | "chai-enzyme": "^0.4.2", 31 | "clean-webpack-plugin": "^0.1.9", 32 | "css-loader": "^0.23.1", 33 | "enzyme": "^2.3.0", 34 | "eslint": "^2.10.2", 35 | "eslint-config-airbnb": "^9.0.1", 36 | "eslint-loader": "^1.3.0", 37 | "eslint-plugin-import": "^1.8.0", 38 | "eslint-plugin-jsx-a11y": "^1.2.2", 39 | "eslint-plugin-react": "^5.1.1", 40 | "expect": "^1.20.1", 41 | "expose-loader": "^0.7.1", 42 | "extract-text-webpack-plugin": "^1.0.1", 43 | "file-loader": "^0.8.5", 44 | "gh-pages": "^0.11.0", 45 | "html-webpack-plugin": "^2.17.0", 46 | "html-webpack-template": "^5.0.0", 47 | "jsdom": "^9.2.0", 48 | "mapbox-gl": "^0.19.1", 49 | "mocha": "^2.5.3", 50 | "nock": "^8.0.0", 51 | "react": "^15.1.0", 52 | "react-addons-perf": "^15.1.0", 53 | "react-addons-pure-render-mixin": "^15.1.0", 54 | "react-addons-test-utils": "^15.1.0", 55 | "react-dom": "^15.1.0", 56 | "react-loading": "0.0.9", 57 | "react-mapbox-gl": "^0.5.1", 58 | "react-redux": "^4.4.5", 59 | "react-router": "^2.4.1", 60 | "react-router-redux": "^4.0.4", 61 | "react-tap-event-plugin": "^1.0.0", 62 | "react-waypoint": "^2.0.2", 63 | "redux": "^3.5.2", 64 | "redux-logger": "^2.6.1", 65 | "redux-mock-store": "^1.0.3", 66 | "redux-thunk": "^2.1.0", 67 | "rollup-plugin-babel": "^2.5.1", 68 | "rollup-plugin-commonjs": "^3.0.0", 69 | "rollup-plugin-npm": "^1.4.0", 70 | "script-loader": "^0.7.0", 71 | "sinon": "^1.17.4", 72 | "style-loader": "^0.13.1", 73 | "url-loader": "^0.5.7", 74 | "webpack": "^2.1.0-beta.7", 75 | "webpack-dev-server": "^2.0.0-beta", 76 | "webpack-merge": "^0.13.0" 77 | }, 78 | "peerDependencies": { 79 | "react": "^15.1.0" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /tests/.setup.js: -------------------------------------------------------------------------------- 1 | import { jsdom } from 'jsdom'; 2 | const exposedProperties = ['window', 'navigator', 'document']; 3 | 4 | global.document = jsdom(''); 5 | global.window = document.defaultView; 6 | Object.keys(document.defaultView).forEach((property) => { 7 | if (typeof global[property] === 'undefined') { 8 | exposedProperties.push(property); 9 | global[property] = document.defaultView[property]; 10 | } 11 | }); 12 | 13 | global.navigator = { 14 | userAgent: 'node.js', 15 | }; 16 | -------------------------------------------------------------------------------- /tests/Sample.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow, mount } from 'enzyme'; 3 | import chai, { expect } from 'chai'; 4 | import chaiEnzyme from 'chai-enzyme'; 5 | chai.use(chaiEnzyme()); 6 | import sinon from 'sinon'; 7 | import Sample from '../app/Sample'; 8 | 9 | describe('', () => { 10 | it('clicking overlay should change state', () => { 11 | const onButtonClick = sinon.spy(); 12 | const wrapper = shallow(); 13 | wrapper.find('.magical').simulate('click'); 14 | wrapper.find('.magical').simulate('click'); 15 | expect(onButtonClick.calledTwice).to.equal(true); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /tests/gol.test.js: -------------------------------------------------------------------------------- 1 | const size = 32; 2 | 3 | class Cell { 4 | constructor() { 5 | this.life = false; 6 | } 7 | setNeighbours = () => { 8 | this.neighbours = this.neighbours.clone(); 9 | } 10 | getLife() { 11 | return this.life; 12 | } 13 | setLife(life) { 14 | this.life = life; 15 | } 16 | getPopulation = () => 17 | this.neighbours.reduce((prev, curr) => prev + curr.getLife()) 18 | } 19 | 20 | const grid = new Array(size); 21 | grid.forEach((z, k) => { 22 | grid[k] = new Array(size); 23 | for (let i = 0; i < size; i++) { 24 | grid[k][i] = new Cell(); 25 | } 26 | console.log(grid[k]); 27 | }); 28 | 29 | function rules(x, y, grid) { 30 | const neighbours = getPopulation(x, y, grid); 31 | if (neighbours < 2) { 32 | return false; 33 | } 34 | if (neighbours > 3) { 35 | return false; 36 | } 37 | if (neighbours === 2 || neighbours === 3) { 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const merge = require('webpack-merge'); 3 | const webpack = require('webpack'); 4 | const pkg = require('./package.json'); 5 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | const Clean = require('clean-webpack-plugin'); 7 | const TARGET = process.env.npm_lifecycle_event; 8 | const PATHS = { 9 | app: [path.join(__dirname, 'lib'), path.join(__dirname, 'examples'), path.join(__dirname, 'app')], 10 | build: path.join(__dirname, 'build'), 11 | test: path.join(__dirname, 'tests'), 12 | }; 13 | 14 | process.env.BABEL_ENV = TARGET; 15 | 16 | const common = { 17 | entry: PATHS.app, 18 | resolve: { 19 | extensions: ['', '.js', '.jsx'], 20 | alias: { 21 | 'mapbox-gl': path.resolve('./node_modules/mapbox-gl/dist/mapbox-gl.js'), 22 | }, 23 | }, 24 | output: { 25 | path: PATHS.build, 26 | // Output using entry name 27 | filename: '[name].js', 28 | }, 29 | module: { 30 | loaders: [ 31 | { 32 | test: /\.css$/, 33 | loaders: ['style', 'css'], 34 | }, 35 | { 36 | test: /\.jsx?$/, 37 | loaders: ['babel?cacheDirectory'], 38 | include: PATHS.app, 39 | }, 40 | { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file' }, 41 | { test: /\.(woff|woff2)$/, loader: 'url?prefix=font/&limit=5000' }, 42 | { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream' }, 43 | { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml' }, 44 | ], 45 | }, 46 | plugins: [ 47 | new HtmlWebpackPlugin({ 48 | template: 'index.html', 49 | title: 'react mapboxgl', 50 | appMountId: 'app', 51 | inject: false, 52 | }), 53 | ], 54 | }; 55 | 56 | if (TARGET === 'start' || !TARGET) { 57 | module.exports = merge(common, { 58 | devtool: 'cheap-module-eval-source-map', 59 | devServer: { 60 | 61 | historyApiFallback: true, 62 | hot: true, 63 | inline: true, 64 | progress: true, 65 | 66 | // display only errors to reduce the amount of output 67 | stats: 'errors-only', 68 | 69 | // parse host and port from env so this is easy 70 | // to customize 71 | host: process.env.HOST, 72 | port: process.env.PORT, 73 | }, 74 | plugins: [ 75 | new webpack.HotModuleReplacementPlugin(), 76 | ], 77 | }); 78 | } 79 | 80 | if (TARGET === 'build') { 81 | module.exports = merge(common, { 82 | // Define entry points needed for splitting 83 | entry: { 84 | app: PATHS.app, 85 | vendor: Object.keys(pkg.dependencies).filter(v => v !== 'alt-utils'), 86 | // Exclude alt-utils as it won't work with this setup 87 | // due to the way the package has been designed 88 | // (no package.json main). 89 | 90 | }, 91 | output: { 92 | path: PATHS.build, 93 | filename: '[name].[chunkhash].js', 94 | chunkFilename: '[chunkhash].js', 95 | }, 96 | plugins: [ 97 | new Clean([PATHS.build], { 98 | verbose: false, // Don't write logs to console 99 | }), 100 | // Extract vendor and manifest files 101 | new webpack.optimize.CommonsChunkPlugin({ 102 | names: ['vendor', 'manifest'], 103 | }), 104 | // Setting DefinePlugin affects React library size! 105 | new webpack.DefinePlugin({ 106 | 'process.env.NODE_ENV': JSON.stringify('production'), 107 | 108 | // You can set this to JSON.stringify('development') for your 109 | // development target to force NODE_ENV to development mode 110 | // no matter what 111 | }), 112 | new webpack.optimize.UglifyJsPlugin({ 113 | compress: { 114 | warnings: false, 115 | }, 116 | }), 117 | ], 118 | }); 119 | } 120 | 121 | if (TARGET === 'test' || TARGET === 'tdd') { 122 | module.exports = merge(common, { 123 | devtool: 'inline-source-map', 124 | resolve: { 125 | alias: { 126 | app: PATHS.app, 127 | }, 128 | }, 129 | module: { 130 | preLoaders: [ 131 | { 132 | test: /\.jsx?$/, 133 | loaders: ['isparta-instrumenter'], 134 | include: PATHS.app, 135 | }, 136 | ], 137 | loaders: [ 138 | { 139 | test: /\.jsx?$/, 140 | loaders: ['babel?cacheDirectory'], 141 | include: PATHS.test, 142 | }, 143 | ], 144 | }, 145 | externals: { 146 | 'cheerio': 'window', 147 | 'react/lib/ExecutionEnvironment': true, 148 | 'react/lib/ReactContext': true, 149 | }, 150 | }); 151 | } 152 | --------------------------------------------------------------------------------