Move 2 yarn, add prettier, update linters (#360)

* Move 2 yarn, add prettier, update linters

* Fix linting error
This commit is contained in:
Ivan Starkov 2017-04-11 00:47:54 +03:00 committed by GitHub
parent 1b088ceef5
commit 07368e23ad
47 changed files with 6558 additions and 968 deletions

View File

@ -1,29 +1,65 @@
{
"extends": "airbnb",
"extends": [
"airbnb",
"prettier",
"prettier/flowtype",
"prettier/react"
],
"plugins": [
"babel",
"prettier"
],
"parser": "babel-eslint",
"env": {
"es6": true,
"browser": true,
"mocha": true,
"jest": true,
"node": true
},
"globals": {
"__DEV__": false,
"__DEV_TOOLS__": false
},
"rules": {
"no-confusing-arrow": 0,
"no-nested-ternary": 0,
"yoda": 0,
"no-underscore-dangle": 0,
"react/prop-types": 0
},
"parserOptions": {
"ecmaVersion": 6,
"ecmaVersion": 2017,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true,
"generators": true,
"experimentalObjectRestSpread": true
}
},
"plugins": [
"react"
],
"parser": "babel-eslint"
}
"rules": {
"no-bitwise": 0,
"no-nested-ternary": 0,
"react/prop-types": 0,
"react/jsx-filename-extension": 0,
"react/require-default-props": 0,
"react/no-unused-prop-types": 0,
"no-sequences": 1,
"comma-dangle": 0,
"no-mixed-operators": 0,
"no-underscore-dangle": 0,
"no-restricted-properties": 0,
"jsx-a11y/no-static-element-interactions": 0,
"import/no-extraneous-dependencies": 0,
"no-plusplus": 0,
"no-unused-vars": [
"error",
{
"ignoreRestSiblings": true
}
],
"react/sort-comp": 0,
"prettier/prettier": [
"error",
{
"trailingComma": "es5",
"singleQuote": true
}
]
},
"settings": {
"polyfills": [
"fetch__"
]
},
"globals": {}
}

View File

@ -5,5 +5,5 @@ cache:
directories:
- node_modules
script:
- npm run lint
- npm test
- yarn run lint
- yarn test

4
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,4 @@
// Place your settings in this file to overwrite default and user settings.
{
"editor.formatOnSave": true
}

View File

@ -1,24 +1,31 @@
import React, { PropTypes } from 'react';
import compose from 'recompose/compose';
import defaultProps from 'recompose/defaultProps';
import withStateSelector from './utils/withStateSelector';
import withHandlers from 'recompose/withHandlers';
import withState from 'recompose/withState';
import withContext from 'recompose/withContext';
import withProps from 'recompose/withProps';
import withPropsOnChange from 'recompose/withPropsOnChange';
import ptInBounds from './utils/ptInBounds';
import GoogleMapReact from '../src';
import SimpleMarker from './markers/SimpleMarker';
import { createSelector } from 'reselect';
import ptInBounds from './utils/ptInBounds';
import SimpleMarker from './markers/SimpleMarker';
import withStateSelector from './utils/withStateSelector';
import GoogleMapReact from '../src';
import { susolvkaCoords, generateMarkers } from './data/fakeData';
export const gMap = ({
style, hoverDistance, options,
mapParams: { center, zoom },
onChange, onChildMouseEnter, onChildMouseLeave,
markers, draggable, // hoveredMarkerId,
}) => (
export const gMap = (
{
style,
hoverDistance,
options,
mapParams: { center, zoom },
onChange,
onChildMouseEnter,
onChildMouseLeave,
markers,
draggable, // hoveredMarkerId,
}
) => (
<GoogleMapReact
draggable={draggable}
style={style}
@ -30,9 +37,7 @@ export const gMap = ({
onChildMouseEnter={onChildMouseEnter}
onChildMouseLeave={onChildMouseLeave}
>
{
markers
}
{markers}
</GoogleMapReact>
);
@ -51,57 +56,44 @@ export const gMapHOC = compose(
flex: 1,
},
}),
withContext(
{ hello: PropTypes.string },
() => ({ hello: 'world' })
),
withContext({ hello: PropTypes.string }, () => ({ hello: 'world' })),
// withState so you could change markers if you want
withStateSelector(
'markers',
'setMarkers',
() => createSelector(
withStateSelector('markers', 'setMarkers', () =>
createSelector(
({ route: { markersCount = 20 } }) => markersCount,
(markersCount) => generateMarkers(markersCount)
)
),
markersCount => generateMarkers(markersCount)
)),
withState('hoveredMarkerId', 'setHoveredMarkerId', -1),
withState('mapParams', 'setMapParams', { center: susolvkaCoords, zoom: 6 }),
// describe events
withHandlers({
onChange: ({ setMapParams }) => ({ center, zoom, bounds }) => {
setMapParams({ center, zoom, bounds });
},
onChildMouseEnter: ({ setHoveredMarkerId }) => (hoverKey, { id }) => {
setHoveredMarkerId(id);
},
onChildMouseLeave: ({ setHoveredMarkerId }) => () => {
setHoveredMarkerId(-1);
},
onChange: ({ setMapParams }) =>
({ center, zoom, bounds }) => {
setMapParams({ center, zoom, bounds });
},
onChildMouseEnter: ({ setHoveredMarkerId }) =>
(hoverKey, { id }) => {
setHoveredMarkerId(id);
},
onChildMouseLeave: ({ setHoveredMarkerId }) =>
() => {
setHoveredMarkerId(-1);
},
}),
withPropsOnChange(
['markers', 'mapParams'],
({ markers, mapParams: { bounds } }) => ({
markers: bounds
? markers.filter(m => ptInBounds(bounds, m))
: [],
})
),
withPropsOnChange(['markers', 'mapParams'], ({
markers,
mapParams: { bounds },
}) => ({
markers: bounds ? markers.filter(m => ptInBounds(bounds, m)) : [],
})),
withProps(({ hoveredMarkerId }) => ({
draggable: hoveredMarkerId === -1,
})),
withPropsOnChange(
['markers'],
({ markers }) => ({
markers: markers
.map(({ ...markerProps, id }) => (
<SimpleMarker
key={id}
id={id}
{...markerProps}
/>
)),
})
)
withPropsOnChange(['markers'], ({ markers }) => ({
markers: markers.map(({ ...markerProps, id }) => (
<SimpleMarker key={id} id={id} {...markerProps} />
)),
}))
);
export default gMapHOC(gMap);

View File

@ -1,24 +1,31 @@
import React, { PropTypes } from 'react';
import compose from 'recompose/compose';
import defaultProps from 'recompose/defaultProps';
import withStateSelector from './utils/withStateSelector';
import withHandlers from 'recompose/withHandlers';
import withState from 'recompose/withState';
import withContext from 'recompose/withContext';
import withProps from 'recompose/withProps';
import withPropsOnChange from 'recompose/withPropsOnChange';
import { createSelector } from 'reselect';
import ptInBounds from './utils/ptInBounds';
import GoogleMapReact from '../src';
import withStateSelector from './utils/withStateSelector';
import SimpleMarker from './markers/SimpleMarker';
import { createSelector } from 'reselect';
import { londonCoords, generateMarkers } from './data/fakeData';
export const gMap = ({
style, hoverDistance, options,
mapParams: { center, zoom },
onChange, onChildMouseEnter, onChildMouseLeave,
markers, draggable, // hoveredMarkerId,
}) => (
export const gMap = (
{
style,
hoverDistance,
options,
mapParams: { center, zoom },
onChange,
onChildMouseEnter,
onChildMouseLeave,
markers,
draggable, // hoveredMarkerId,
}
) => (
<GoogleMapReact
draggable={draggable}
style={style}
@ -26,14 +33,16 @@ export const gMap = ({
hoverDistance={hoverDistance}
center={center}
zoom={zoom}
layerTypes={zoom > 12 ? [] : zoom > 10 ? ['TrafficLayer'] : ['TrafficLayer', 'TransitLayer']}
layerTypes={
zoom > 12
? []
: zoom > 10 ? ['TrafficLayer'] : ['TrafficLayer', 'TransitLayer']
}
onChange={onChange}
onChildMouseEnter={onChildMouseEnter}
onChildMouseLeave={onChildMouseLeave}
>
{
markers
}
{markers}
</GoogleMapReact>
);
@ -52,57 +61,44 @@ export const gMapHOC = compose(
flex: 1,
},
}),
withContext(
{ hello: PropTypes.string },
() => ({ hello: 'world' })
),
withContext({ hello: PropTypes.string }, () => ({ hello: 'world' })),
// withState so you could change markers if you want
withStateSelector(
'markers',
'setMarkers',
() => createSelector(
withStateSelector('markers', 'setMarkers', () =>
createSelector(
({ route: { markersCount = 20 } }) => markersCount,
(markersCount) => generateMarkers(markersCount)
)
),
markersCount => generateMarkers(markersCount)
)),
withState('hoveredMarkerId', 'setHoveredMarkerId', -1),
withState('mapParams', 'setMapParams', { center: londonCoords, zoom: 9 }),
// describe events
withHandlers({
onChange: ({ setMapParams }) => ({ center, zoom, bounds }) => {
setMapParams({ center, zoom, bounds });
},
onChildMouseEnter: ({ setHoveredMarkerId }) => (hoverKey, { id }) => {
setHoveredMarkerId(id);
},
onChildMouseLeave: ({ setHoveredMarkerId }) => () => {
setHoveredMarkerId(-1);
},
onChange: ({ setMapParams }) =>
({ center, zoom, bounds }) => {
setMapParams({ center, zoom, bounds });
},
onChildMouseEnter: ({ setHoveredMarkerId }) =>
(hoverKey, { id }) => {
setHoveredMarkerId(id);
},
onChildMouseLeave: ({ setHoveredMarkerId }) =>
() => {
setHoveredMarkerId(-1);
},
}),
withPropsOnChange(
['markers', 'mapParams'],
({ markers, mapParams: { bounds } }) => ({
markers: bounds
? markers.filter(m => ptInBounds(bounds, m))
: [],
})
),
withPropsOnChange(['markers', 'mapParams'], ({
markers,
mapParams: { bounds },
}) => ({
markers: bounds ? markers.filter(m => ptInBounds(bounds, m)) : [],
})),
withProps(({ hoveredMarkerId }) => ({
draggable: hoveredMarkerId === -1,
})),
withPropsOnChange(
['markers'],
({ markers }) => ({
markers: markers
.map(({ ...markerProps, id }) => (
<SimpleMarker
key={id}
id={id}
{...markerProps}
/>
)),
})
)
withPropsOnChange(['markers'], ({ markers }) => ({
markers: markers.map(({ ...markerProps, id }) => (
<SimpleMarker key={id} id={id} {...markerProps} />
)),
}))
);
export default gMapHOC(gMap);

View File

@ -8,25 +8,32 @@
import React from 'react';
import compose from 'recompose/compose';
import defaultProps from 'recompose/defaultProps';
import withStateSelector from './utils/withStateSelector';
import withHandlers from 'recompose/withHandlers';
import withState from 'recompose/withState';
import withPropsOnChange from 'recompose/withPropsOnChange';
import withProps from 'recompose/withProps';
import { createSelector } from 'reselect';
import withStateSelector from './utils/withStateSelector';
import ptInBounds from './utils/ptInBounds';
import GoogleMapReact from '../src';
// import SimpleMarker from './markers/SimpleMarker';
import ReactiveMarker from './markers/ReactiveMarker';
import { createSelector } from 'reselect';
import { susolvkaCoords, generateMarkers } from './data/fakeData';
import props2Stream from './utils/props2Stream';
export const gMap = ({
style, hoverDistance, options,
mapParams: { center, zoom },
onChange, onChildMouseEnter, onChildMouseLeave,
markers, draggable,
}) => (
export const gMap = (
{
style,
hoverDistance,
options,
mapParams: { center, zoom },
onChange,
onChildMouseEnter,
onChildMouseLeave,
markers,
draggable,
}
) => (
<GoogleMapReact
style={style}
options={options}
@ -58,56 +65,52 @@ export const gMapHOC = compose(
flex: 1,
},
}),
// withState so you could change markers if you want
withStateSelector(
'markers',
'setMarkers',
() => createSelector(
withStateSelector('markers', 'setMarkers', () =>
createSelector(
({ route: { markersCount = 20 } }) => markersCount,
(markersCount) => generateMarkers(markersCount)
)
),
markersCount => generateMarkers(markersCount)
)),
withState('hoveredMarkerId', 'setHoveredMarkerId', -1),
withState('mapParams', 'setMapParams', { center: susolvkaCoords, zoom: 6 }),
// describe events
withHandlers({
onChange: ({ setMapParams }) => ({ center, zoom, bounds }) => {
setMapParams({ center, zoom, bounds });
},
onChildMouseEnter: ({ setHoveredMarkerId }) => (hoverKey, { id }) => {
setHoveredMarkerId(id);
},
onChildMouseLeave: ({ setHoveredMarkerId }) => () => {
setHoveredMarkerId(-1);
},
onChange: ({ setMapParams }) =>
({ center, zoom, bounds }) => {
setMapParams({ center, zoom, bounds });
},
onChildMouseEnter: ({ setHoveredMarkerId }) =>
(hoverKey, { id }) => {
setHoveredMarkerId(id);
},
onChildMouseLeave: ({ setHoveredMarkerId }) =>
() => {
setHoveredMarkerId(-1);
},
}),
withPropsOnChange(
['markers', 'mapParams'],
({ markers, mapParams: { bounds } }) => ({
markers: bounds
? markers.filter(m => ptInBounds(bounds, m))
: [],
})
),
withPropsOnChange(['markers', 'mapParams'], ({
markers,
mapParams: { bounds },
}) => ({
markers: bounds ? markers.filter(m => ptInBounds(bounds, m)) : [],
})),
withProps(({ hoveredMarkerId }) => ({
draggable: hoveredMarkerId === -1,
})),
props2Stream('hoveredMarkerId'),
withPropsOnChange(
['markers', 'hoveredMarkerId$'],
({ markers, hoveredMarkerId$ }) => ({
markers: markers
.map(({ ...markerProps, id }) => (
<ReactiveMarker
key={id}
id={id}
hoveredMarkerId$={hoveredMarkerId$}
{...markerProps}
/>
)),
})
)
withPropsOnChange(['markers', 'hoveredMarkerId$'], ({
markers,
hoveredMarkerId$,
}) => ({
markers: markers.map(({ ...markerProps, id }) => (
<ReactiveMarker
key={id}
id={id}
hoveredMarkerId$={hoveredMarkerId$}
{...markerProps}
/>
)),
}))
);
export default gMapHOC(gMap);

View File

@ -14,12 +14,19 @@ import SimpleMarker from './markers/SimpleMarker';
import { createSelector } from 'reselect';
import { susolvkaCoords, generateMarkers } from './data/fakeData';
export const gMapResizable = ({
style, hoverDistance, options,
mapParams: { center, zoom },
onChange, onChildMouseEnter, onChildMouseLeave,
markers, draggable, // hoveredMarkerId,
}) => (
export const gMapResizable = (
{
style,
hoverDistance,
options,
mapParams: { center, zoom },
onChange,
onChildMouseEnter,
onChildMouseLeave,
markers,
draggable, // hoveredMarkerId,
}
) => (
<GoogleMapReact
draggable={draggable}
style={style}
@ -31,11 +38,9 @@ export const gMapResizable = ({
onChildMouseEnter={onChildMouseEnter}
onChildMouseLeave={onChildMouseLeave}
resetBoundsOnResize={true}
apiKey={"AIzaSyC-BebC7ChnHPzxQm7DAHYFMCqR5H3Jlps"}
apiKey={'AIzaSyC-BebC7ChnHPzxQm7DAHYFMCqR5H3Jlps'}
>
{
markers
}
{markers}
</GoogleMapReact>
);
@ -54,57 +59,44 @@ export const gMapHOC = compose(
flex: 1,
},
}),
withContext(
{ hello: PropTypes.string },
() => ({ hello: 'world' })
),
withContext({ hello: PropTypes.string }, () => ({ hello: 'world' })),
// withState so you could change markers if you want
withStateSelector(
'markers',
'setMarkers',
() => createSelector(
withStateSelector('markers', 'setMarkers', () =>
createSelector(
({ route: { markersCount = 20 } }) => markersCount,
(markersCount) => generateMarkers(markersCount)
)
),
markersCount => generateMarkers(markersCount)
)),
withState('hoveredMarkerId', 'setHoveredMarkerId', -1),
withState('mapParams', 'setMapParams', { center: susolvkaCoords, zoom: 6 }),
// describe events
withHandlers({
onChange: ({ setMapParams }) => ({ center, zoom, bounds }) => {
setMapParams({ center, zoom, bounds });
},
onChildMouseEnter: ({ setHoveredMarkerId }) => (hoverKey, { id }) => {
setHoveredMarkerId(id);
},
onChildMouseLeave: ({ setHoveredMarkerId }) => () => {
setHoveredMarkerId(-1);
},
onChange: ({ setMapParams }) =>
({ center, zoom, bounds }) => {
setMapParams({ center, zoom, bounds });
},
onChildMouseEnter: ({ setHoveredMarkerId }) =>
(hoverKey, { id }) => {
setHoveredMarkerId(id);
},
onChildMouseLeave: ({ setHoveredMarkerId }) =>
() => {
setHoveredMarkerId(-1);
},
}),
withPropsOnChange(
['markers', 'mapParams'],
({ markers, mapParams: { bounds } }) => ({
markers: bounds
? markers.filter(m => ptInBounds(bounds, m))
: [],
})
),
withPropsOnChange(['markers', 'mapParams'], ({
markers,
mapParams: { bounds },
}) => ({
markers: bounds ? markers.filter(m => ptInBounds(bounds, m)) : [],
})),
withProps(({ hoveredMarkerId }) => ({
draggable: hoveredMarkerId === -1,
})),
withPropsOnChange(
['markers'],
({ markers }) => ({
markers: markers
.map(({ ...markerProps, id }) => (
<SimpleMarker
key={id}
id={id}
{...markerProps}
/>
)),
})
)
withPropsOnChange(['markers'], ({ markers }) => ({
markers: markers.map(({ ...markerProps, id }) => (
<SimpleMarker key={id} id={id} {...markerProps} />
)),
}))
);
export default gMapHOC(gMapResizable);

View File

@ -1,12 +1,16 @@
/* eslint-disable react/prefer-stateless-function */
import React, { Component } from 'react';
import compose from 'recompose/compose';
import { Link } from 'react-router';
import defaultProps from 'recompose/defaultProps';
import layoutStyles from './Layout.sass';
// for hmr to work I need the first class to extend Component
export class Layout extends Component { // eslint-disable-line
export class Layout extends Component {
// eslint-disable-line
render() {
const { styles: { layout, header, main, footer, logo, links } } = this.props;
const {
styles: { layout, header, main, footer, logo, links },
} = this.props;
return (
<div className={layout}>
<header className={header}>
@ -32,7 +36,7 @@ export class Layout extends Component { // eslint-disable-line
Ivan Starkov
</a>
</div>
<div className={logo}></div>
<div className={logo} />
<div>
<a href="https://twitter.com/icelabaratory">
@icelabaratory

View File

@ -1,14 +1,14 @@
// file: main.jsx
/* eslint-disable import/no-named-as-default */
import React from 'react';
import { render } from 'react-dom';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';
import 'normalize.css/normalize.css';
import Layout from './Layout';
import GMap from './GMap';
import GMapLayers from './GMapLayers';
import GMapOptim from './GMapOptim';
import GMapResizable from './GMapResizable';
import 'normalize.css/normalize.css';
import './Main.sass';
const mountNode = document.getElementById('app');
@ -22,7 +22,6 @@ render(
<Route markersCount={20} path="resizable" component={GMapResizable} />
<IndexRoute markersCount={20} component={GMap} />
</Route>
</Router>
,
</Router>,
mountNode
);

View File

@ -1,18 +1,17 @@
import path from 'path'; // eslint-disable-line no-var
import autoprefixer from 'autoprefixer'; // eslint-disable-line no-var
import autoprefixer from 'autoprefixer'; // eslint-disable-line no-var
import webpack from 'webpack';
export default {
devtool: 'cheap-module-eval-source-map',
postcss: [
autoprefixer({ browsers: ['last 2 versions'] }),
],
postcss: [autoprefixer({ browsers: ['last 2 versions'] })],
plugins: [
new webpack.DefinePlugin(process.env.NODE_ENV
? {
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
}
: {}
new webpack.DefinePlugin(
process.env.NODE_ENV
? {
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
}
: {}
),
],
module: {

View File

@ -2,16 +2,20 @@ export const susolvkaCoords = { lat: 60.814305, lng: 47.051773 };
export const londonCoords = { lat: 51.508411, lng: -0.125364 };
export const generateMarkers = (count) =>
[...Array(count)].fill(0) // fill(0) for loose mode
.map((__, index) => ({
id: index,
lat: susolvkaCoords.lat +
0.01 * index *
export const generateMarkers = count =>
[...Array(count)].fill(0).map((__, index) => ({
// fill(0) for loose mode
id: index,
lat: susolvkaCoords.lat +
0.01 *
index *
Math.sin(30 * Math.PI * index / 180) *
Math.cos(50 * Math.PI * index / 180) + Math.sin(5 * index / 180),
lng: susolvkaCoords.lng +
0.01 * index *
Math.cos(50 * Math.PI * index / 180) +
Math.sin(5 * index / 180),
lng: susolvkaCoords.lng +
0.01 *
index *
Math.cos(70 + 23 * Math.PI * index / 180) *
Math.cos(50 * Math.PI * index / 180) + Math.sin(5 * index / 180),
}));
Math.cos(50 * Math.PI * index / 180) +
Math.sin(5 * index / 180),
}));

View File

@ -6,31 +6,30 @@ import pure from 'recompose/pure';
import { Motion, spring } from 'react-motion';
import clusterMarkerStyles from './ClusterMarker.sass';
export const clusterMarker = ({
styles, text, hovered, $hover,
defaultMotionStyle, motionStyle,
}) => (
<Motion
defaultStyle={defaultMotionStyle}
style={motionStyle}
>
export const clusterMarker = (
{
({ scale }) => (
styles,
text,
hovered,
$hover,
defaultMotionStyle,
motionStyle,
}
) => (
<Motion defaultStyle={defaultMotionStyle} style={motionStyle}>
{({ scale }) => (
<div
className={styles.marker}
style={{
transform: `translate3D(0,0,0) scale(${scale}, ${scale})`,
zIndex: (hovered || $hover) ? 1 : 0,
zIndex: hovered || $hover ? 1 : 0,
}}
>
<div
className={styles.text}
>
<div className={styles.text}>
{text}
</div>
</div>
)
}
)}
</Motion>
);
@ -49,29 +48,33 @@ export const clusterMarkerHOC = compose(
// pure optimization can cause some effects you don't want,
// don't use it in development for markers
pure,
withPropsOnChange(
['initialScale'],
({ initialScale, defaultScale, $prerender }) => ({
initialScale,
defaultMotionStyle: { scale: $prerender ? defaultScale : initialScale },
})
),
withPropsOnChange(
['hovered', '$hover'],
({
hovered, $hover, hoveredScale, defaultScale,
stiffness, damping, precision,
}) => ({
$hover,
hovered,
motionStyle: {
scale: spring(
(hovered || $hover) ? hoveredScale : defaultScale,
{ stiffness, damping, precision }
),
},
})
)
withPropsOnChange(['initialScale'], ({
initialScale,
defaultScale,
$prerender,
}) => ({
initialScale,
defaultMotionStyle: { scale: $prerender ? defaultScale : initialScale },
})),
withPropsOnChange(['hovered', '$hover'], ({
hovered,
$hover,
hoveredScale,
defaultScale,
stiffness,
damping,
precision,
}) => ({
$hover,
hovered,
motionStyle: {
scale: spring(hovered || $hover ? hoveredScale : defaultScale, {
stiffness,
damping,
precision,
}),
},
}))
);
export default clusterMarkerHOC(clusterMarker);

View File

@ -1,26 +1,24 @@
import React from 'react';
import compose from 'recompose/compose';
import SimpleMarker from './SimpleMarker';
import stream2Props from '../utils/stream2Props';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/scan';
import 'rxjs/add/operator/distinctUntilChanged';
import SimpleMarker from './SimpleMarker';
import stream2Props from '../utils/stream2Props';
// import defaultProps from 'recompose/defaultProps';
// import reactiveMarkerStyles from './reactiveMarker.scss';
export const reactiveMarker = (props) => (
<SimpleMarker {...props} />
);
export const reactiveMarker = props => <SimpleMarker {...props} />;
export const reactiveMarkerHOC = compose(
stream2Props(({ id, hoveredMarkerId$ }) => (
stream2Props(({ id, hoveredMarkerId$ }) =>
hoveredMarkerId$
.map(hoveredMarkerId => hoveredMarkerId === id)
.distinctUntilChanged()
.map(v => ({ hovered: v }))
))
.map(v => ({ hovered: v })))
);
export default reactiveMarkerHOC(reactiveMarker);

View File

@ -4,31 +4,29 @@ import defaultProps from 'recompose/defaultProps';
import getContext from 'recompose/getContext';
// import mapPropsOnChange from 'recompose/mapPropsOnChange';
import { Motion } from 'react-motion';
import { clusterMarkerHOC } from './ClusterMarker.js';
import { clusterMarkerHOC } from './ClusterMarker';
import simpleMarkerStyles from './SimpleMarker.sass';
export const simpleMarker = ({
styles, hovered, $hover,
defaultMotionStyle, motionStyle,
// hello,
}) => (
// console.log('hello', hello),
<Motion
defaultStyle={defaultMotionStyle}
style={motionStyle}
>
export const simpleMarker = (
{
({ scale }) => (
styles,
hovered,
$hover,
defaultMotionStyle,
motionStyle,
// hello,
} // console.log('hello', hello),
) => (
<Motion defaultStyle={defaultMotionStyle} style={motionStyle}>
{({ scale }) => (
<div
className={styles.marker}
style={{
transform: `translate3D(0,0,0) scale(${scale}, ${scale})`,
zIndex: (hovered || $hover) ? 1 : 0,
zIndex: hovered || $hover ? 1 : 0,
}}
>
</div>
)
}
/>
)}
</Motion>
);

View File

@ -7,8 +7,7 @@ import 'rxjs/add/operator/distinctUntilChanged';
describe('Playground', () => {
it('Play', async () => {
const comparator = (a, b) => a === b;
const props$ = (new BehaviorSubject(1))
.distinctUntilChanged(comparator);
const props$ = new BehaviorSubject(1).distinctUntilChanged(comparator);
props$.subscribe(v => console.log(v)); // eslint-disable-line
props$.next(1);

View File

@ -3,8 +3,9 @@ import isReferentiallyTransparentFunctionComponent
from './isReferentiallyTransparentFunctionComponent';
const createFactory = type => {
const isReferentiallyTransparent =
isReferentiallyTransparentFunctionComponent(type);
const isReferentiallyTransparent = isReferentiallyTransparentFunctionComponent(
type
);
return (p, c) =>
createEagerElementUtil(false, isReferentiallyTransparent, type, p, c);
};

View File

@ -1,15 +1,17 @@
const isClassComponent = Component => Boolean(
Component &&
Component.prototype &&
typeof Component.prototype.isReactComponent === 'object'
);
const isClassComponent = Component =>
Boolean(
Component &&
Component.prototype &&
typeof Component.prototype.isReactComponent === 'object'
);
const isReferentiallyTransparentFunctionComponent = Component => Boolean(
typeof Component === 'function' &&
!isClassComponent(Component) &&
!Component.defaultProps &&
!Component.contextTypes &&
!Component.propTypes
);
const isReferentiallyTransparentFunctionComponent = Component =>
Boolean(
typeof Component === 'function' &&
!isClassComponent(Component) &&
!Component.defaultProps &&
!Component.contextTypes &&
!Component.propTypes
);
export default isReferentiallyTransparentFunctionComponent;

View File

@ -3,7 +3,7 @@ const omit = (obj, keys) => {
const { ...rest } = obj;
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (rest.hasOwnProperty(key)) {
if (key in rest) {
delete rest[key];
}
}

View File

@ -4,7 +4,7 @@ const pick = (obj, keys) => {
const result = {};
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (obj.hasOwnProperty(key)) {
if (key in obj) {
result[key] = obj[key];
}
}

View File

@ -1,16 +1,17 @@
import { Component } from 'react';
import createEagerFactory from './createEagerFactory';
import createHelper from 'recompose/createHelper';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import 'rxjs/add/operator/distinctUntilChanged';
import createEagerFactory from './createEagerFactory';
import omit from './omit';
const prop2Stream = (propName, comparator = (a, b) => a === b) =>
BaseComponent => {
const factory = createEagerFactory(BaseComponent);
return class extends Component {
props$ = (new BehaviorSubject(this.props[propName]))
.distinctUntilChanged(comparator);
props$ = new BehaviorSubject(this.props[propName]).distinctUntilChanged(
comparator
);
componentWillReceiveProps(nextProps) {
this.props$.next(nextProps[propName]);

View File

@ -2,12 +2,9 @@ const ptInSect = (x, a, b) => (x - a) * (x - b) <= 0;
export default ({ nw, se }, pt) => {
const lngs = nw.lng < se.lng
? [[nw.lng, se.lng]]
: [[nw.lng, 180], [-180, se.lng]];
? [[nw.lng, se.lng]]
: [[nw.lng, 180], [-180, se.lng]];
return (
ptInSect(pt.lat, se.lat, nw.lat) &&
lngs.some(([lngFrom, lngTo]) => ptInSect(pt.lng, lngFrom, lngTo))
);
return ptInSect(pt.lat, se.lat, nw.lat) &&
lngs.some(([lngFrom, lngTo]) => ptInSect(pt.lng, lngFrom, lngTo));
};

View File

@ -1,18 +1,18 @@
import { Component } from 'react';
import createEagerFactory from './createEagerFactory';
import createHelper from 'recompose/createHelper';
import createEagerFactory from './createEagerFactory';
// if stream prop will change this will fail,
// this is expected behavior
const stream2Props = (props2Stream) =>
const stream2Props = props2Stream =>
BaseComponent => {
const factory = createEagerFactory(BaseComponent);
return class extends Component {
state = {};
componentWillMount() {
this.subscription = props2Stream(this.props)
.subscribe(value => this.setState({ value }));
this.subscription = props2Stream(this.props).subscribe(value =>
this.setState({ value }));
}
componentWillUnmount() {

View File

@ -1,6 +1,6 @@
import { Component } from 'react';
import createEagerFactory from './createEagerFactory';
import createHelper from 'recompose/createHelper';
import createEagerFactory from './createEagerFactory';
const withStateSelector = (stateName, stateUpdaterName, selectorFactory) =>
BaseComponent => {
@ -11,13 +11,15 @@ const withStateSelector = (stateName, stateUpdaterName, selectorFactory) =>
stateValue: this.selector(this.props),
};
updateStateValue = (updateFn, callback) => (
this.setState(({ stateValue }) => ({
stateValue: typeof updateFn === 'function'
? updateFn(stateValue)
: updateFn,
}), callback)
);
updateStateValue = (updateFn, callback) =>
this.setState(
({ stateValue }) => ({
stateValue: typeof updateFn === 'function'
? updateFn(stateValue)
: updateFn,
}),
callback
);
componentWillReceiveProps(nextProps) {
// reselect memoize result

View File

@ -7,13 +7,17 @@
"build:lib": "babel ./src -d lib",
"build:umd": "webpack src/index_umd.js dist/GoogleMapReact.js --config webpack.config.dev.js",
"build:umd:min": "webpack src/index_umd.js dist/GoogleMapReact.min.js --config webpack.config.prod.js",
"build": "npm run build:lib && npm run build:umd && npm run build:umd:min",
"build": "yarn run build:lib && yarn run build:umd && yarn run build:umd:min",
"clean": "rimraf lib dist",
"prepublish": "npm run clean && npm run build",
"lint": "eslint src develop",
"prepublish": "yarn run clean && yarn run build",
"format": "prettier --trailing-comma es5 --single-quote --write 'src/**/*.js' 'src/**/*.js'",
"format:dev": "prettier --trailing-comma es5 --single-quote --write 'develop/**/*.js' 'develop/**/*.js'",
"lint": "eslint src",
"lint:dev": "eslint develop",
"test": "NODE_ENV=eee mocha --compilers js:babel-register --recursive --require babel-polyfill",
"test:watch": "NODE_ENV=eee mocha --compilers js:babel-register --recursive --require babel-polyfill --watch",
"start": "kotatsu serve --port 4000 --config ./develop/config/index.babel.js --presets es2015,stage-0,react,react-hmre ./develop/Main.js"
"start": "kotatsu serve --port 4000 --config ./develop/config/index.babel.js --presets es2015,stage-0,react,react-hmre ./develop/Main.js",
"precommit": "lint-staged"
},
"repository": {
"type": "git",
@ -38,6 +42,7 @@
},
"homepage": "https://github.com/istarkov/google-map-react#readme",
"peerDependencies": {
"prop-types": "^15.5.6",
"react": "^0.14.0 || ^15.0.0"
},
"dependencies": {
@ -60,20 +65,27 @@
"babel-preset-stage-0": "^6.5.0",
"babel-register": "^6.14.0",
"css-loader": "^0.23.1",
"eslint": "^2.12.0",
"eslint-config-airbnb": "^9.0.1",
"eslint-plugin-import": "^1.8.1",
"eslint-plugin-jsx-a11y": "^1.4.2",
"eslint-plugin-react": "^5.1.1",
"eslint": "^3.17.1",
"eslint-config-airbnb": "^14.0.0",
"eslint-config-prettier": "^1.5.0",
"eslint-plugin-babel": "^4.1.1",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-prettier": "^2.0.1",
"eslint-plugin-react": "^6.8.0",
"expect": "^1.11.1",
"file-loader": "^0.8.5",
"husky": "^0.13.3",
"jsdom": "^6.5.1",
"kotatsu": "^0.14.0",
"lint-staged": "^3.4.0",
"lodash": "^4.13.1",
"mocha": "^2.3.3",
"node-sass": "^3.7.0",
"normalize.css": "^4.1.1",
"postcss-loader": "^0.9.1",
"prettier": "^0.22.0",
"prop-types": "^15.5.6",
"react": "^15.1.0",
"react-addons-test-utils": "^15.1.0",
"react-dom": "^15.1.0",
@ -87,5 +99,11 @@
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"webpack": "^1.12.2"
},
"lint-staged": {
"*.js": [
"prettier --trailing-comma es5 --single-quote --write",
"git add"
]
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -16,8 +16,7 @@ export default class GoogleMapMap extends Component {
}
render() {
return (
<div style={style} />
);
const { registerChild } = this.props;
return <div ref={registerChild} style={style} />;
}
}

View File

@ -1,4 +1,7 @@
import React, { PropTypes, Component } from 'react';
/* eslint-disable react/forbid-prop-types */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import shallowEqual from 'fbjs/lib/shallowEqual';
import omit from './utils/omit';
@ -44,7 +47,10 @@ export default class GoogleMapMarkers extends Component {
constructor(props) {
super(props);
this.props.dispatcher.on('kON_CHANGE', this._onChangeHandler);
this.props.dispatcher.on('kON_MOUSE_POSITION_CHANGE', this._onMouseChangeHandler);
this.props.dispatcher.on(
'kON_MOUSE_POSITION_CHANGE',
this._onMouseChangeHandler
);
this.props.dispatcher.on('kON_CLICK', this._onChildClick);
this.props.dispatcher.on('kON_MDOWN', this._onChildMouseDown);
@ -65,12 +71,16 @@ export default class GoogleMapMarkers extends Component {
);
}
return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState);
return !shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState);
}
componentWillUnmount() {
this.props.dispatcher.removeListener('kON_CHANGE', this._onChangeHandler);
this.props.dispatcher.removeListener('kON_MOUSE_POSITION_CHANGE', this._onMouseChangeHandler);
this.props.dispatcher.removeListener(
'kON_MOUSE_POSITION_CHANGE',
this._onMouseChangeHandler
);
this.props.dispatcher.removeListener('kON_CLICK', this._onChildClick);
this.props.dispatcher.removeListener('kON_MDOWN', this._onChildMouseDown);
@ -94,9 +104,9 @@ export default class GoogleMapMarkers extends Component {
state,
() =>
(state.children || []).length !== prevChildCount &&
this._onMouseChangeHandler()
this._onMouseChangeHandler()
);
}
};
_onChildClick = () => {
if (this.props.onChildClick) {
@ -107,7 +117,7 @@ export default class GoogleMapMarkers extends Component {
this.props.onChildClick(hoverKey, childProps);
}
}
}
};
_onChildMouseDown = () => {
if (this.props.onChildMouseDown) {
@ -118,8 +128,7 @@ export default class GoogleMapMarkers extends Component {
this.props.onChildMouseDown(hoverKey, childProps);
}
}
}
};
_onChildMouseEnter = (hoverKey, childProps) => {
if (!this.dimesionsCache_) {
@ -133,7 +142,7 @@ export default class GoogleMapMarkers extends Component {
this.hoverChildProps_ = childProps;
this.hoverKey_ = hoverKey;
this.setState({ hoverKey });
}
};
_onChildMouseLeave = () => {
if (!this.dimesionsCache_) {
@ -152,25 +161,23 @@ export default class GoogleMapMarkers extends Component {
this.hoverChildProps_ = null;
this.setState({ hoverKey: null });
}
}
};
_onMouseAllow = (value) => {
_onMouseAllow = value => {
if (!value) {
this._onChildMouseLeave();
}
this.allowMouse_ = value;
}
};
_onMouseChangeHandler = () => {
if (this.allowMouse_) {
this._onMouseChangeHandler_raf();
this._onMouseChangeHandlerRaf();
}
}
};
_onMouseChangeHandler_raf = () => { // eslint-disable-line
_onMouseChangeHandlerRaf = () => {
if (!this.dimesionsCache_) {
return;
}
@ -184,21 +191,28 @@ export default class GoogleMapMarkers extends Component {
React.Children.forEach(this.state.children, (child, childIndex) => {
if (!child) return;
// layers
if (child.props.latLng === undefined &&
child.props.lat === undefined &&
child.props.lng === undefined) {
if (
child.props.latLng === undefined &&
child.props.lat === undefined &&
child.props.lng === undefined
) {
return;
}
const childKey = child.key !== undefined && child.key !== null ? child.key : childIndex;
const dist = this.props.distanceToMouse(this.dimesionsCache_[childKey], mp, child.props);
const childKey = child.key !== undefined && child.key !== null
? child.key
: childIndex;
const dist = this.props.distanceToMouse(
this.dimesionsCache_[childKey],
mp,
child.props
);
if (dist < hoverDistance) {
distances.push(
{
key: childKey,
dist,
props: child.props,
});
distances.push({
key: childKey,
dist,
props: child.props,
});
}
});
@ -218,79 +232,88 @@ export default class GoogleMapMarkers extends Component {
} else {
this._onChildMouseLeave();
}
}
};
_getDimensions = (key) => {
_getDimensions = key => {
const childKey = key;
return this.dimesionsCache_[childKey];
}
};
render() {
const mainElementStyle = this.props.style || mainStyle;
this.dimesionsCache_ = {};
const markers = React.Children.map(this.state.children, (child, childIndex) => {
if (!child) return undefined;
if (child.props.latLng === undefined &&
const markers = React.Children.map(
this.state.children,
(child, childIndex) => {
if (!child) return undefined;
if (
child.props.latLng === undefined &&
child.props.lat === undefined &&
child.props.lng === undefined) {
return (
React.cloneElement(child, {
child.props.lng === undefined
) {
return React.cloneElement(child, {
$geoService: this.props.geoService,
$onMouseAllow: this._onMouseAllow,
$prerender: this.props.prerender,
})
});
}
const latLng = child.props.latLng !== undefined
? child.props.latLng
: { lat: child.props.lat, lng: child.props.lng };
const pt = this.props.geoService.project(
latLng,
this.props.projectFromLeftTop
);
const stylePtPos = {
left: pt.x,
top: pt.y,
};
let dx = 0;
let dy = 0;
if (!this.props.projectFromLeftTop) {
// center projection
if (this.props.geoService.hasSize()) {
dx = this.props.geoService.getWidth() / 2;
dy = this.props.geoService.getHeight() / 2;
}
}
// to prevent rerender on child element i need to pass
// const params $getDimensions and $dimensionKey instead of dimension object
const childKey = child.key !== undefined && child.key !== null
? child.key
: childIndex;
this.dimesionsCache_[childKey] = {
x: pt.x + dx,
y: pt.y + dy,
...latLng,
};
return (
<div
key={childKey}
style={{ ...style, ...stylePtPos }}
className={child.props.$markerHolderClassName}
>
{React.cloneElement(child, {
$hover: childKey === this.state.hoverKey,
$getDimensions: this._getDimensions,
$dimensionKey: childKey,
$geoService: this.props.geoService,
$onMouseAllow: this._onMouseAllow,
$prerender: this.props.prerender,
})}
</div>
);
}
const latLng = child.props.latLng !== undefined
? child.props.latLng
: { lat: child.props.lat, lng: child.props.lng };
const pt = this.props.geoService.project(latLng, this.props.projectFromLeftTop);
const stylePtPos = {
left: pt.x,
top: pt.y,
};
let dx = 0;
let dy = 0;
if (!this.props.projectFromLeftTop) { // center projection
if (this.props.geoService.hasSize()) {
dx = this.props.geoService.getWidth() / 2;
dy = this.props.geoService.getHeight() / 2;
}
}
// to prevent rerender on child element i need to pass
// const params $getDimensions and $dimensionKey instead of dimension object
const childKey = child.key !== undefined && child.key !== null ? child.key : childIndex;
this.dimesionsCache_[childKey] = {
x: pt.x + dx,
y: pt.y + dy,
...latLng,
};
return (
<div
key={childKey}
style={{ ...style, ...stylePtPos }}
className={child.props.$markerHolderClassName}
>
{React.cloneElement(child, {
$hover: childKey === this.state.hoverKey,
$getDimensions: this._getDimensions,
$dimensionKey: childKey,
$geoService: this.props.geoService,
$onMouseAllow: this._onMouseAllow,
$prerender: this.props.prerender,
})}
</div>
);
});
);
return (
<div style={mainElementStyle}>

View File

@ -1,5 +1,5 @@
import React from 'react';
import GoogleMapMarkers from './google_map_markers.js';
import GoogleMapMarkers from './google_map_markers';
const style = {
width: '50%',
@ -13,7 +13,7 @@ const style = {
// opacity: 0.3
};
export default function (props) {
export default function(props) {
return (
<div style={style}>
<GoogleMapMarkers {...props} prerender />

View File

@ -1 +1 @@
export default from './google_map.js';
export default from './google_map';

View File

@ -1,2 +1,3 @@
import GoogleMap from './google_map.js';
import GoogleMap from './google_map';
module.exports = GoogleMap;

View File

@ -1,4 +1,3 @@
export default function isArraysEqualEps(arrayA, arrayB, eps) {
if (arrayA && arrayB) {
for (let i = 0; i !== arrayA.length; ++i) {

View File

@ -14,15 +14,21 @@ export default function detectBrowser() {
let isChrome = navigator.userAgent.indexOf('Chrome') > -1;
let isSafari = navigator.userAgent.indexOf('Safari') > -1;
if ((isChrome) && (isSafari)) {
if (isChrome && isSafari) {
isSafari = false;
}
if ((isChrome) && (isOpera)) {
if (isChrome && isOpera) {
isChrome = false;
}
detectBrowserResult_ = { isExplorer, isFirefox, isOpera, isChrome, isSafari };
detectBrowserResult_ = {
isExplorer,
isFirefox,
isOpera,
isChrome,
isSafari,
};
return detectBrowserResult_;
}

View File

@ -10,38 +10,47 @@
**/
// Reliable `window` and `document` detection
var canUseDOM = !!(
(typeof window !== 'undefined' &&
window.document && window.document.createElement)
);
var canUseDOM = !!(typeof window !== 'undefined' &&
window.document &&
window.document.createElement);
// Check `document` and `window` in case of server-side rendering
var _window
var _window;
if (canUseDOM) {
_window = window
_window = window;
} else if (typeof self !== 'undefined') {
_window = self
_window = self;
} else {
_window = this
_window = this;
}
var attachEvent = typeof document !== 'undefined' && document.attachEvent;
var stylesCreated = false;
if (canUseDOM && !attachEvent) {
var requestFrame = (function(){
var raf = _window.requestAnimationFrame || _window.mozRequestAnimationFrame || _window.webkitRequestAnimationFrame ||
function(fn){ return _window.setTimeout(fn, 20); };
return function(fn){ return raf(fn); };
var requestFrame = (function() {
var raf = _window.requestAnimationFrame ||
_window.mozRequestAnimationFrame ||
_window.webkitRequestAnimationFrame ||
function(fn) {
return _window.setTimeout(fn, 20);
};
return function(fn) {
return raf(fn);
};
})();
var cancelFrame = (function(){
var cancel = _window.cancelAnimationFrame || _window.mozCancelAnimationFrame || _window.webkitCancelAnimationFrame ||
_window.clearTimeout;
return function(id){ return cancel(id); };
var cancelFrame = (function() {
var cancel = _window.cancelAnimationFrame ||
_window.mozCancelAnimationFrame ||
_window.webkitCancelAnimationFrame ||
_window.clearTimeout;
return function(id) {
return cancel(id);
};
})();
var resetTriggers = function(element){
var resetTriggers = function(element) {
var triggers = element.__resizeTriggers__,
expand = triggers.firstElementChild,
contract = triggers.lastElementChild,
@ -54,20 +63,20 @@ if (canUseDOM && !attachEvent) {
expand.scrollTop = expand.scrollHeight;
};
var checkTriggers = function(element){
var checkTriggers = function(element) {
return element.offsetWidth != element.__resizeLast__.width ||
element.offsetHeight != element.__resizeLast__.height;
}
element.offsetHeight != element.__resizeLast__.height;
};
var scrollListener = function(e){
var scrollListener = function(e) {
var element = this;
resetTriggers(this);
if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);
this.__resizeRAF__ = requestFrame(function(){
this.__resizeRAF__ = requestFrame(function() {
if (checkTriggers(element)) {
element.__resizeLast__.width = element.offsetWidth;
element.__resizeLast__.height = element.offsetHeight;
element.__resizeListeners__.forEach(function(fn){
element.__resizeListeners__.forEach(function(fn) {
fn.call(element, e);
});
}
@ -80,20 +89,24 @@ if (canUseDOM && !attachEvent) {
keyframeprefix = '',
animationstartevent = 'animationstart',
domPrefixes = 'Webkit Moz O ms'.split(' '),
startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '),
pfx = '';
startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(
' '
),
pfx = '';
if(canUseDOM) {
if (canUseDOM) {
var elm = document.createElement('fakeelement');
if( elm.style.animationName !== undefined ) { animation = true; }
if (elm.style.animationName !== undefined) {
animation = true;
}
if( animation === false ) {
for( var i = 0; i < domPrefixes.length; i++ ) {
if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
pfx = domPrefixes[ i ];
if (animation === false) {
for (var i = 0; i < domPrefixes.length; i++) {
if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) {
pfx = domPrefixes[i];
animationstring = pfx + 'Animation';
keyframeprefix = '-' + pfx.toLowerCase() + '-';
animationstartevent = startEvents[ i ];
animationstartevent = startEvents[i];
animation = true;
break;
}
@ -102,16 +115,25 @@ if (canUseDOM && !attachEvent) {
}
var animationName = 'resizeanim';
var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
var animationKeyframes = '@' +
keyframeprefix +
'keyframes ' +
animationName +
' { from { opacity: 0; } to { opacity: 0; } } ';
var animationStyle = keyframeprefix +
'animation: 1ms ' +
animationName +
'; ';
}
var createStyles = function() {
if (!stylesCreated) {
//opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360
var css = (animationKeyframes ? animationKeyframes : '') +
'.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' +
'.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }',
'.resize-triggers { ' +
(animationStyle ? animationStyle : '') +
'visibility: hidden; opacity: 0; } ' +
'.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: " "; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }',
head = document.head || document.getElementsByTagName('head')[0],
style = document.createElement('style');
@ -125,51 +147,64 @@ var createStyles = function() {
head.appendChild(style);
stylesCreated = true;
}
}
};
var addResizeListener = function(element, fn){
var addResizeListener = function(element, fn) {
if (element.parentNode === undefined) {
var tempParentDiv = document.createElement('div');
element.parentNode = tempParentDiv;
}
element = element.parentNode;
if (attachEvent) element.attachEvent('onresize', fn);
if (attachEvent)
element.attachEvent('onresize', fn);
else {
if (!element.__resizeTriggers__) {
if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
if (getComputedStyle(element).position == 'static')
element.style.position = 'relative';
createStyles();
element.__resizeLast__ = {};
element.__resizeListeners__ = [];
(element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers';
(element.__resizeTriggers__ = document.createElement(
'div'
)).className = 'resize-triggers';
element.__resizeTriggers__.innerHTML = '<div class="expand-trigger"><div></div></div>' +
'<div class="contract-trigger"></div>';
'<div class="contract-trigger"></div>';
element.appendChild(element.__resizeTriggers__);
resetTriggers(element);
element.addEventListener('scroll', scrollListener, true);
/* Listen for a css animation to detect element display/re-attach */
animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function(e) {
if(e.animationName == animationName)
resetTriggers(element);
});
animationstartevent &&
element.__resizeTriggers__.addEventListener(
animationstartevent,
function(e) {
if (e.animationName == animationName) resetTriggers(element);
}
);
}
element.__resizeListeners__.push(fn);
}
};
var removeResizeListener = function(element, fn){
var removeResizeListener = function(element, fn) {
element = element.parentNode;
if (attachEvent) element.detachEvent('onresize', fn);
if (attachEvent)
element.detachEvent('onresize', fn);
else {
element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
element.__resizeListeners__.splice(
element.__resizeListeners__.indexOf(fn),
1
);
if (!element.__resizeListeners__.length) {
element.removeEventListener('scroll', scrollListener);
element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__);
element.removeEventListener('scroll', scrollListener);
element.__resizeTriggers__ = !element.removeChild(
element.__resizeTriggers__
);
}
}
}
};
module.exports = {
addResizeListener : addResizeListener,
removeResizeListener : removeResizeListener
addResizeListener: addResizeListener,
removeResizeListener: removeResizeListener,
};

View File

@ -1,11 +1,10 @@
import LatLng from './lib_geo/lat_lng.js';
import Point from 'point-geometry';
import Transform from './lib_geo/transform.js';
import LatLng from './lib_geo/lat_lng';
import Transform from './lib_geo/transform';
export default class Geo {
constructor(tileSize) { // left_top view пользует гугл
constructor(tileSize) {
// left_top view пользует гугл
// super();
this.hasSize_ = false;
this.hasView_ = false;
@ -51,7 +50,8 @@ export default class Geo {
project(ptLatLng, viewFromLeftTop) {
if (viewFromLeftTop) {
const pt = this.transform_.locationPoint(LatLng.convert(ptLatLng));
pt.x -= this.transform_.worldSize * Math.round(pt.x / this.transform_.worldSize);
pt.x -= this.transform_.worldSize *
Math.round(pt.x / this.transform_.worldSize);
pt.x += this.transform_.width / 2;
pt.y += this.transform_.height / 2;
@ -81,12 +81,14 @@ export default class Geo {
}
getBounds(margins, roundFactor) {
const bndT = margins && margins[0] || 0;
const bndR = margins && margins[1] || 0;
const bndB = margins && margins[2] || 0;
const bndL = margins && margins[3] || 0;
const bndT = (margins && margins[0]) || 0;
const bndR = (margins && margins[1]) || 0;
const bndB = (margins && margins[2]) || 0;
const bndL = (margins && margins[3]) || 0;
if (this.getWidth() - bndR - bndL > 0 && this.getHeight() - bndT - bndB > 0) {
if (
this.getWidth() - bndR - bndL > 0 && this.getHeight() - bndT - bndB > 0
) {
const topLeftCorner = this.unproject({
x: bndL - this.getWidth() / 2,
y: bndT - this.getHeight() / 2,
@ -97,10 +99,14 @@ export default class Geo {
});
let res = [
topLeftCorner.lat, topLeftCorner.lng, // NW
bottomRightCorner.lat, bottomRightCorner.lng, // SE
bottomRightCorner.lat, topLeftCorner.lng, // SW
topLeftCorner.lat, bottomRightCorner.lng, // NE
topLeftCorner.lat,
topLeftCorner.lng, // NW
bottomRightCorner.lat,
bottomRightCorner.lng, // SE
bottomRightCorner.lat,
topLeftCorner.lng, // SW
topLeftCorner.lat,
bottomRightCorner.lng, // NE
];
if (roundFactor) {

View File

@ -1,4 +1,3 @@
function isObjectLike(value) {
return !!value && typeof value === 'object';
}

View File

@ -1,5 +1,5 @@
// source taken from https://github.com/rackt/redux/blob/master/src/utils/isPlainObject.js
const fnToString = (fn) => Function.prototype.toString.call(fn);
const fnToString = fn => Function.prototype.toString.call(fn);
/**
* @param {any} obj The object to inspect.
@ -20,7 +20,7 @@ export default function isPlainObject(obj) {
const constructor = proto.constructor;
return typeof constructor === 'function'
&& constructor instanceof constructor
&& fnToString(constructor) === fnToString(Object);
return typeof constructor === 'function' &&
constructor instanceof constructor &&
fnToString(constructor) === fnToString(Object);
}

View File

@ -1,7 +1,7 @@
import { wrap } from './wrap.js';
import { wrap } from './wrap';
export default class LatLng {
static convert = (a) => {
static convert = a => {
if (a instanceof LatLng) {
return a;
}
@ -15,7 +15,7 @@ export default class LatLng {
}
return a;
}
};
constructor(lat, lng) {
if (isNaN(lat) || isNaN(lng)) {

View File

@ -1,10 +1,10 @@
import LatLng from './lat_lng';
export default class LatLngBounds {
static convert = (a) => {
static convert = a => {
if (!a || a instanceof LatLngBounds) return a;
return new LatLngBounds(a);
}
};
constructor(sw, ne) {
if (!sw) return;
@ -49,23 +49,25 @@ export default class LatLngBounds {
return this;
}
getCenter = () => new LatLng(
(this._sw.lat + this._ne.lat) / 2,
(this._sw.lng + this._ne.lng) / 2)
getCenter = () =>
new LatLng(
(this._sw.lat + this._ne.lat) / 2,
(this._sw.lng + this._ne.lng) / 2
);
getSouthWest = () => this._sw
getSouthWest = () => this._sw;
getNorthEast = () => this._ne
getNorthEast = () => this._ne;
getNorthWest = () => new LatLng(this.getNorth(), this.getWest())
getNorthWest = () => new LatLng(this.getNorth(), this.getWest());
getSouthEast = () => new LatLng(this.getSouth(), this.getEast())
getSouthEast = () => new LatLng(this.getSouth(), this.getEast());
getWest = () => this._sw.lng
getWest = () => this._sw.lng;
getSouth = () => this._sw.lat
getSouth = () => this._sw.lat;
getEast = () => this._ne.lng
getEast = () => this._ne.lng;
getNorth = () => this._ne.lat
getNorth = () => this._ne.lat;
}

View File

@ -1,6 +1,7 @@
import LatLng from './lat_lng';
/* eslint-disable class-methods-use-this */
import Point from 'point-geometry';
import { wrap } from './wrap.js';
import LatLng from './lat_lng';
import { wrap } from './wrap';
// A single transform, generally used for a single tile to be scaled, rotated, and zoomed.
export default class Transform {
@ -80,13 +81,15 @@ export default class Transform {
project(latlng, worldSize) {
return new Point(
this.lngX(latlng.lng, worldSize),
this.latY(latlng.lat, worldSize));
this.latY(latlng.lat, worldSize)
);
}
unproject(point, worldSize) {
return new LatLng(
this.yLat(point.y, worldSize),
this.xLng(point.x, worldSize));
this.xLng(point.x, worldSize)
);
}
get x() {
@ -108,7 +111,9 @@ export default class Transform {
// latitude to absolute y coord
latY(lat, worldSize) {
const y = 180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360));
const y = 180 /
Math.PI *
Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360));
return (180 - y) * (worldSize || this.worldSize) / 360;
}

View File

@ -1,3 +1,5 @@
/* eslint-disable import/prefer-default-export */
export function wrap(n, min, max) {
const d = max - min;
return n === max ? n : ((n - min) % d + d) % d + min;

View File

@ -1,3 +1,4 @@
/* eslint-disable no-console */
let $script_ = null;
let loadPromise_;
@ -45,24 +46,27 @@ export default function googleMapLoader(bootstrapURLKeys) {
if (process.env.NODE_ENV !== 'production') {
if (Object.keys(bootstrapURLKeys).indexOf('callback') > -1) {
console.error('"callback" key in bootstrapURLKeys is not allowed, ' + // eslint-disable-line
'use onGoogleApiLoaded property instead');
throw new Error('"callback" key in bootstrapURLKeys is not allowed, ' +
'use onGoogleApiLoaded property instead');
console.error(
'"callback" key in bootstrapURLKeys is not allowed, ' + // eslint-disable-line
'use onGoogleApiLoaded property instead'
);
throw new Error(
'"callback" key in bootstrapURLKeys is not allowed, ' +
'use onGoogleApiLoaded property instead'
);
}
}
const queryString = Object.keys(bootstrapURLKeys)
.reduce(
(r, key) => `${r}&${key}=${bootstrapURLKeys[key]}`,
''
);
const queryString = Object.keys(bootstrapURLKeys).reduce(
(r, key) => `${r}&${key}=${bootstrapURLKeys[key]}`,
''
);
$script_(
`https://maps.googleapis.com/maps/api/js?callback=_$_google_map_initialize_$_${queryString}`,
() =>
typeof window.google === 'undefined' &&
reject(new Error('google map initialization error (not loaded)'))
reject(new Error('google map initialization error (not loaded)'))
);
});

View File

@ -1,6 +1,3 @@
const log2 = Math.log2
? Math.log2
: (x) => Math.log(x) / Math.LN2;
const log2 = Math.log2 ? Math.log2 : x => Math.log(x) / Math.LN2;
export default log2;

View File

@ -3,7 +3,7 @@ const omit = (obj, keys) => {
const { ...rest } = obj;
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
if (rest.hasOwnProperty(key)) {
if (key in rest) {
delete rest[key];
}
}

View File

@ -1,10 +1,13 @@
// source taken from https://github.com/rackt/redux/blob/master/src/utils/pick.js
export default function pick(obj, fn) {
return Object.keys(obj).reduce((result, key) => {
if (fn(obj[key])) {
result[key] = obj[key]; // eslint-disable-line
}
return result;
}, {});
return Object.keys(obj).reduce(
(result, key) => {
if (fn(obj[key])) {
result[key] = obj[key]; // eslint-disable-line
}
return result;
},
{}
);
}

View File

@ -1,10 +1,10 @@
export default function raf(callback) {
if (window.requestAnimationFrame) {
return window.requestAnimationFrame(callback);
}
const nativeRaf = window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
const nativeRaf = window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame;
return nativeRaf
? nativeRaf(callback)

View File

@ -1,16 +1,15 @@
const GOOGLE_TILE_SIZE = 256;
import log2 from './math/log2';
const GOOGLE_TILE_SIZE = 256;
function latLng2World({ lat, lng }) {
const sin = Math.sin(lat * Math.PI / 180);
const x = (lng / 360 + 0.5);
let y = (0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI);
const x = lng / 360 + 0.5;
let y = 0.5 - 0.25 * Math.log((1 + sin) / (1 - sin)) / Math.PI;
y = y < 0 // eslint-disable-line
? 0
: y > 1
? 1
: y;
: y > 1 ? 1 : y;
return { x, y };
}
@ -20,7 +19,7 @@ function world2LatLng({ x, y }) {
// TODO test that this is faster
// 360 * Math.atan(Math.exp((180 - y * 360) * Math.PI / 180)) / Math.PI - 90;
return {
lat: (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)))),
lat: 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))),
lng: x * 360 - 180,
};
}
@ -28,15 +27,20 @@ function world2LatLng({ x, y }) {
// Thank you wiki https://en.wikipedia.org/wiki/Geographic_coordinate_system
function latLng2MetersPerDegree({ lat }) {
const phi = lat * Math.PI / 180;
const metersPerLatDegree = 111132.92 - 559.82 * Math.cos(2 * phi) +
1.175 * Math.cos(4 * phi) - 0.0023 * Math.cos(6 * phi);
const metersPerLatDegree = 111132.92 -
559.82 * Math.cos(2 * phi) +
1.175 * Math.cos(4 * phi) -
0.0023 * Math.cos(6 * phi);
const metersPerLngDegree = 111412.84 * Math.cos(phi) -
93.5 * Math.cos(3 * phi) + 0.118 * Math.cos(5 * phi);
93.5 * Math.cos(3 * phi) +
0.118 * Math.cos(5 * phi);
return { metersPerLatDegree, metersPerLngDegree };
}
function meters2LatLngBounds(meters, { lat, lng }) {
const { metersPerLatDegree, metersPerLngDegree } = latLng2MetersPerDegree({ lat });
const { metersPerLatDegree, metersPerLngDegree } = latLng2MetersPerDegree({
lat,
});
const latDelta = 0.5 * meters / metersPerLatDegree;
const lngDelta = 0.5 * meters / metersPerLngDegree;
@ -69,7 +73,7 @@ function fitNwSe(nw, se, width, height) {
const seWorld = latLng2World(se);
const dx = nwWorld.x < seWorld.x
? seWorld.x - nwWorld.x
: (1 - nwWorld.x) + seWorld.x;
: 1 - nwWorld.x + seWorld.x;
const dy = seWorld.y - nwWorld.y;
if (dx <= 0 && dy <= 0) {
@ -85,8 +89,8 @@ function fitNwSe(nw, se, width, height) {
x: nwWorld.x < seWorld.x // eslint-disable-line
? 0.5 * (nwWorld.x + seWorld.x)
: nwWorld.x + seWorld.x - 1 > 0
? 0.5 * (nwWorld.x + seWorld.x - 1)
: 0.5 * (1 + nwWorld.x + seWorld.x),
? 0.5 * (nwWorld.x + seWorld.x - 1)
: 0.5 * (1 + nwWorld.x + seWorld.x),
y: 0.5 * (nwWorld.y + seWorld.y),
};
@ -179,10 +183,10 @@ export function meters2ScreenPixels(meters, { lat, lng }, zoom) {
export function tile2LatLng({ x, y }, zoom) {
const n = Math.PI - 2 * Math.PI * y / Math.pow(2, zoom);
return ({
lat: (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)))),
lng: (x / Math.pow(2, zoom) * 360 - 180),
});
return {
lat: 180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))),
lng: x / Math.pow(2, zoom) * 360 - 180,
};
}
export function latLng2Tile({ lat, lng }, zoom) {

5352
yarn.lock Normal file

File diff suppressed because it is too large Load Diff