From 92159bd0313808bab3cc261d20608317a7ac0798 Mon Sep 17 00:00:00 2001 From: Tom Chen Date: Wed, 13 Sep 2017 22:21:40 +0800 Subject: [PATCH] feat(TrafficLayer): revamp with jscodeshift --- src/lib/InfoWindow.js | 166 ------------------------------------ src/lib/TrafficLayer.js | 96 --------------------- src/macros/InfoWindow.jsx | 116 +++++++++++++++++++++++++ src/macros/TrafficLayer.jsx | 76 +++++++++++++++++ 4 files changed, 192 insertions(+), 262 deletions(-) delete mode 100644 src/lib/InfoWindow.js delete mode 100644 src/lib/TrafficLayer.js create mode 100644 src/macros/InfoWindow.jsx create mode 100644 src/macros/TrafficLayer.jsx diff --git a/src/lib/InfoWindow.js b/src/lib/InfoWindow.js deleted file mode 100644 index 9f78720c..00000000 --- a/src/lib/InfoWindow.js +++ /dev/null @@ -1,166 +0,0 @@ -/* global google */ -import _ from "lodash"; - -import invariant from "invariant"; - -import PropTypes from "prop-types"; - -import createReactClass from "create-react-class"; - -import { Children } from "react"; - -import { - unstable_renderSubtreeIntoContainer, - unmountComponentAtNode, -} from "react-dom"; - -import { - MAP, - ANCHOR, - INFO_WINDOW, -} from "./constants"; - -import { - addDefaultPrefixToPropTypes, - collectUncontrolledAndControlledProps, - default as enhanceElement, -} from "./enhanceElement"; - -const controlledPropTypes = { - // NOTICE!!!!!! - // - // Only expose those with getters & setters in the table as controlled props. - // - // [].map.call($0.querySelectorAll("tr>td>code", function(it){ return it.textContent; }) - // .filter(function(it){ return it.match(/^set/) && !it.match(/^setMap/); }) - // - // https://developers.google.com/maps/documentation/javascript/3.exp/reference#InfoWindow - children: PropTypes.element, - options: PropTypes.object, - position: PropTypes.any, - zIndex: PropTypes.number, -}; - -const defaultUncontrolledPropTypes = addDefaultPrefixToPropTypes(controlledPropTypes); - -const eventMap = { - // https://developers.google.com/maps/documentation/javascript/3.exp/reference#InfoWindow - // [].map.call($0.querySelectorAll("tr>td>code"), function(it){ return it.textContent; }) - onCloseClick: `closeclick`, - - onContentChanged: `content_changed`, - - onDomReady: `domready`, - - onPositionChanged: `position_changed`, - - onZIndexChanged: `zindex_changed`, -}; - -const publicMethodMap = { - // Public APIs - // - // https://developers.google.com/maps/documentation/javascript/3.exp/reference#InfoWindow - // - // [].map.call($0.querySelectorAll("tr>td>code"), function(it){ return it.textContent; }) - // .filter(function(it){ return it.match(/^get/) && !it.match(/Map$/); }) - getPosition(infoWindow) { return infoWindow.getPosition(); }, - - getZIndex(infoWindow) { return infoWindow.getZIndex(); }, - // END - Public APIs -}; - -const controlledPropUpdaterMap = { - children(infoWindow, children, component) { - unstable_renderSubtreeIntoContainer(component, Children.only(children), infoWindow.getContent()); - }, - options(infoWindow, options) { infoWindow.setOptions(options); }, - position(infoWindow, position) { infoWindow.setPosition(position); }, - zIndex(infoWindow, zIndex) { infoWindow.setZIndex(zIndex); }, -}; - -function getInstanceFromComponent(component) { - return component.state[INFO_WINDOW]; -} - -function openInfoWindow(context, infoWindow) { - const map = context[MAP]; - const anchor = context[ANCHOR]; - if (anchor) { - infoWindow.open(map, anchor); - } else if (infoWindow.getPosition()) { - infoWindow.open(map); - } else { - invariant(false, -`You must provide either an anchor (typically a ) or a position for .` - ); - } -} - -export default _.flowRight( - createReactClass, - enhanceElement(getInstanceFromComponent, publicMethodMap, eventMap, controlledPropUpdaterMap), -)({ - displayName: `InfoWindow`, - - propTypes: { - ...controlledPropTypes, - ...defaultUncontrolledPropTypes, - }, - - contextTypes: { - [MAP]: PropTypes.object, - [ANCHOR]: PropTypes.object, - }, - - getInitialState() { - const map = this.context[MAP]; - // https://developers.google.com/maps/documentation/javascript/3.exp/reference#InfoWindow - const infoWindow = new google.maps.InfoWindow({ - map, - ...collectUncontrolledAndControlledProps( - defaultUncontrolledPropTypes, - controlledPropTypes, - this.props - ), - // Override props of ReactElement type - content: undefined, - children: undefined, - }); - - openInfoWindow(this.context, infoWindow); - return { - [INFO_WINDOW]: infoWindow, - }; - }, - - componentDidMount() { - const infoWindow = getInstanceFromComponent(this); - const content = document.createElement(`div`) - - controlledPropUpdaterMap.children({ - getContent() { return content }, - }, this.props.children, this); - infoWindow.setContent(content) - }, - - componentWillReceiveProps(nextProps, nextContext) { - const anchorChanged = this.context[ANCHOR] !== nextContext[ANCHOR]; - if (anchorChanged) { - const infoWindow = getInstanceFromComponent(this); - openInfoWindow(nextContext, infoWindow); - } - }, - - componentWillUnmount() { - const infoWindow = getInstanceFromComponent(this); - if (infoWindow) { - unmountComponentAtNode(infoWindow.getContent()); - infoWindow.setMap(null); - } - }, - - render() { - return false; - }, -}); diff --git a/src/lib/TrafficLayer.js b/src/lib/TrafficLayer.js deleted file mode 100644 index b29c0ca7..00000000 --- a/src/lib/TrafficLayer.js +++ /dev/null @@ -1,96 +0,0 @@ -/* global google */ -import _ from "lodash"; - -import PropTypes from "prop-types"; - -import createReactClass from "create-react-class"; - -import { - MAP, - TRAFFIC_LAYER, -} from "./constants"; - -import { - addDefaultPrefixToPropTypes, - collectUncontrolledAndControlledProps, - default as enhanceElement, -} from "./enhanceElement"; - -const controlledPropTypes = { - // NOTICE!!!!!! - // - // Only expose those with getters & setters in the table as controlled props. - // - // [].map.call($0.querySelectorAll("tr>td>code", function(it){ return it.textContent; }) - // .filter(function(it){ return it.match(/^set/) && !it.match(/^setMap/); }) - // - // https://developers.google.com/maps/documentation/javascript/3.exp/reference#TrafficLayer - options: PropTypes.object, -}; - -const defaultUncontrolledPropTypes = addDefaultPrefixToPropTypes(controlledPropTypes); - -const eventMap = { - // https://developers.google.com/maps/documentation/javascript/3.exp/reference#TrafficLayer - // [].map.call($0.querySelectorAll("tr>td>code"), function(it){ return it.textContent; }) -}; - -const publicMethodMap = { - // Public APIs - // - // https://developers.google.com/maps/documentation/javascript/3.exp/reference#TrafficLayer - // - // [].map.call($0.querySelectorAll("tr>td>code"), function(it){ return it.textContent; }) - // .filter(function(it){ return it.match(/^get/) && !it.match(/Map$/); }) - // END - Public APIs -}; - -const controlledPropUpdaterMap = { - options(trafficLayer, options) { trafficLayer.setOptions(options); }, -}; - -function getInstanceFromComponent(component) { - return component.state[TRAFFIC_LAYER]; -} - -export default _.flowRight( - createReactClass, - enhanceElement(getInstanceFromComponent, publicMethodMap, eventMap, controlledPropUpdaterMap), -)({ - displayName: `TrafficLayer`, - - propTypes: { - ...controlledPropTypes, - ...defaultUncontrolledPropTypes, - }, - - contextTypes: { - [MAP]: PropTypes.object, - }, - - getInitialState() { - // https://developers.google.com/maps/documentation/javascript/3.exp/reference#TrafficLayer - const trafficLayer = new google.maps.TrafficLayer({ - map: this.context[MAP], - ...collectUncontrolledAndControlledProps( - defaultUncontrolledPropTypes, - controlledPropTypes, - this.props - ), - }); - return { - [TRAFFIC_LAYER]: trafficLayer, - }; - }, - - componentWillUnmount() { - const trafficLayer = getInstanceFromComponent(this); - if (trafficLayer) { - trafficLayer.setMap(null); - } - }, - - render() { - return false; - }, -}); diff --git a/src/macros/InfoWindow.jsx b/src/macros/InfoWindow.jsx new file mode 100644 index 00000000..cc391849 --- /dev/null +++ b/src/macros/InfoWindow.jsx @@ -0,0 +1,116 @@ +/* global google */ +import invariant from "invariant" +import React from "react" +import ReactDOM from "react-dom" +import PropTypes from "prop-types" + +import { + construct, + componentDidMount, + componentDidUpdate, + componentWillUnmount, +} from "../utils/MapChildHelper" + +import { MAP, ANCHOR, INFO_WINDOW } from "../constants" + +export const __jscodeshiftPlaceholder__ = `{ + "prohibitedPropNames": [ + "content" + ], + "eventMapOverrides": { + "onCloseClick": "closeclick", + "onDomReady": "domready" + }, + "getInstanceFromComponent": "this.state[INFO_WINDOW]" +}` + +/** + * @url https://developers.google.com/maps/documentation/javascript/3.exp/reference#InfoWindow + */ +export class InfoWindow extends React.PureComponent { + static propTypes = { + __jscodeshiftPlaceholder__: null, + } + + static contextTypes = { + [MAP]: PropTypes.object, + [ANCHOR]: PropTypes.object, + } + + /* + * @url https://developers.google.com/maps/documentation/javascript/3.exp/reference#InfoWindow + */ + constructor(props, context) { + super(props, context) + const infoWindow = new google.maps.InfoWindow() + construct(InfoWindow.propTypes, updaterMap, this.props, infoWindow) + infoWindow.setMap(this.context[MAP]) + this.state = { + [INFO_WINDOW]: infoWindow, + } + } + + componentDidMount() { + componentDidMount(this, this.state[INFO_WINDOW], eventMap) + const content = document.createElement(`div`) + ReactDOM.unstable_renderSubtreeIntoContainer( + this, + React.Children.only(this.props.children), + content + ) + this.state[INFO_WINDOW].setContent(content) + open(this.state[INFO_WINDOW], this.context[ANCHOR]) + } + + componentDidUpdate(prevProps) { + componentDidUpdate( + this, + this.state[INFO_WINDOW], + eventMap, + updaterMap, + prevProps + ) + if (this.props.children !== prevProps.children) { + ReactDOM.unstable_renderSubtreeIntoContainer( + this, + React.Children.only(this.props.children), + this.state[INFO_WINDOW].getContent() + ) + } + open(this.state[INFO_WINDOW], this.context[ANCHOR]) + } + + componentWillUnmount() { + componentWillUnmount(this) + const infoWindow = this.state[INFO_WINDOW] + if (infoWindow) { + if (infoWindow.getContent()) { + ReactDOM.unmountComponentAtNode(infoWindow.getContent()) + } + infoWindow.setMap(null) + } + } + + render() { + return false + } +} + +export default InfoWindow + +const open = (infoWindow, anchor) => { + if (anchor) { + infoWindow.open(infoWindow.getMap(), anchor) + } else if (infoWindow.getPosition()) { + infoWindow.open(infoWindow.getMap()) + } else { + invariant( + false, + `You must provide either an anchor (typically render it inside a ) or a position props for .` + ) + } +} + +const eventMap = {} + +const updaterMap = {} diff --git a/src/macros/TrafficLayer.jsx b/src/macros/TrafficLayer.jsx new file mode 100644 index 00000000..bafbfaac --- /dev/null +++ b/src/macros/TrafficLayer.jsx @@ -0,0 +1,76 @@ +/* global google */ +import React from "react" +import PropTypes from "prop-types" + +import { + construct, + componentDidMount, + componentDidUpdate, + componentWillUnmount, +} from "../utils/MapChildHelper" + +import { MAP, TRAFFIC_LAYER } from "../constants" + +export const __jscodeshiftPlaceholder__ = `{ + "eventMapOverrides": { + }, + "getInstanceFromComponent": "this.state[TRAFFIC_LAYER]" +}` + +/** + * @url https://developers.google.com/maps/documentation/javascript/3.exp/reference#TrafficLayer + */ +export class TrafficLayer extends React.PureComponent { + static propTypes = { + __jscodeshiftPlaceholder__: null, + } + + static contextTypes = { + [MAP]: PropTypes.object, + } + + /* + * @url https://developers.google.com/maps/documentation/javascript/3.exp/reference#TrafficLayer + */ + constructor(props, context) { + super(props, context) + const trafficLayer = new google.maps.TrafficLayer() + construct(TrafficLayer.propTypes, updaterMap, this.props, trafficLayer) + trafficLayer.setMap(this.context[MAP]) + this.state = { + [TRAFFIC_LAYER]: trafficLayer, + } + } + + componentDidMount() { + componentDidMount(this, this.state[TRAFFIC_LAYER], eventMap) + } + + componentDidUpdate(prevProps) { + componentDidUpdate( + this, + this.state[TRAFFIC_LAYER], + eventMap, + updaterMap, + prevProps + ) + } + + componentWillUnmount() { + componentWillUnmount(this) + const trafficLayer = this.state[TRAFFIC_LAYER] + if (trafficLayer) { + trafficLayer.setMap(null) + } + } + + render() { + return false + } +} + +export default TrafficLayer + +const eventMap = {} + +const updaterMap = {}