diff --git a/src/HeatmapLayer.js b/src/HeatmapLayer.js
new file mode 100644
index 00000000..421d055d
--- /dev/null
+++ b/src/HeatmapLayer.js
@@ -0,0 +1,60 @@
+import {
+ default as React,
+ Component,
+} from "react";
+
+import {
+ default as canUseDOM,
+} from "can-use-dom";
+
+import {
+ default as HeatmapLayerCreator,
+ heatmapLayerDefaultPropTypes,
+ heatmapLayerControlledPropTypes,
+ heatmapLayerEventPropTypes,
+} from "./creators/HeatmapLayerCreator";
+
+export default class HeatmapLayer extends Component {
+ static propTypes = {
+ // Uncontrolled default[props] - used only in componentDidMount
+ ...heatmapLayerDefaultPropTypes,
+ // Controlled [props] - used in componentDidMount/componentDidUpdate
+ ...heatmapLayerControlledPropTypes,
+ // Event [onEventName]
+ ...heatmapLayerEventPropTypes,
+ }
+
+ // Public APIs
+ //
+ // https://developers.google.com/maps/documentation/javascript/3.exp/reference#HeatmapLayer
+ //
+ getData() { return this.state.heatmapLayer.getData(); }
+
+ // END - Public APIs
+ //
+ // https://developers.google.com/maps/documentation/javascript/3.exp/reference#HeatmapLayer
+
+ state = {
+ }
+
+ componentWillMount() {
+ if (!canUseDOM) {
+ return;
+ }
+ const heatmapLayer = HeatmapLayerCreator._createHeatmapLayer(this.props);
+
+ this.setState({ heatmapLayer });
+ }
+
+ render() {
+ if (this.state.heatmapLayer) {
+ return (
+
+ {this.props.children}
+
+ );
+ } else {
+ return ();
+ }
+ }
+}
diff --git a/src/creators/HeatmapLayerCreator.js b/src/creators/HeatmapLayerCreator.js
new file mode 100644
index 00000000..83b99143
--- /dev/null
+++ b/src/creators/HeatmapLayerCreator.js
@@ -0,0 +1,67 @@
+import {
+ default as React,
+ PropTypes,
+ Component,
+} from "react";
+
+import { default as HeatmapLayerEventList } from "../eventLists/HeatmapLayerEventList";
+import { default as eventHandlerCreator } from "../utils/eventHandlerCreator";
+import { default as defaultPropsCreator } from "../utils/defaultPropsCreator";
+import { default as composeOptions } from "../utils/composeOptions";
+import { default as componentLifecycleDecorator } from "../utils/componentLifecycleDecorator";
+
+import { default as GoogleMapHolder } from "./GoogleMapHolder";
+
+export const heatmapLayerControlledPropTypes = {
+// NOTICE!!!!!!
+//
+// Only expose those with getters & setters in the table as controlled props.
+//
+// https://developers.google.com/maps/documentation/javascript/3.exp/reference#HeatmapLayer
+ data: PropTypes.any,
+ options: PropTypes.object,
+};
+
+export const heatmapLayerDefaultPropTypes = defaultPropsCreator(heatmapLayerControlledPropTypes);
+
+const heatmapLayerUpdaters = {
+ data(data, component) { component.getHeatmapLayer().setData(data); },
+ options(options, component) { component.getHeatmapLayer().setOptions(options); },
+};
+
+const { eventPropTypes, registerEvents } = eventHandlerCreator(HeatmapLayerEventList);
+
+export const heatmapLayerEventPropTypes = eventPropTypes;
+
+@componentLifecycleDecorator({
+ registerEvents,
+ instanceMethodName: `getHeatmapLayer`,
+ updaters: heatmapLayerUpdaters,
+})
+export default class HeatmapLayerCreator extends Component {
+
+ static propTypes = {
+ mapHolderRef: PropTypes.instanceOf(GoogleMapHolder).isRequired,
+ heatmapLayer: PropTypes.object.isRequired,
+ }
+
+ static _createHeatmapLayer(heatmapLayerProps) {
+ const { mapHolderRef } = heatmapLayerProps;
+ // https://developers.google.com/maps/documentation/javascript/3.exp/reference#HeatmapLayer
+ const heatmapLayer = new google.maps.visualization.HeatmapLayer(
+ composeOptions(heatmapLayerProps, heatmapLayerControlledPropTypes)
+ );
+
+ heatmapLayer.setMap(mapHolderRef.getMap());
+
+ return heatmapLayer;
+ }
+
+ getHeatmapLayer() {
+ return this.props.heatmapLayer;
+ }
+
+ render() {
+ return ();
+ }
+}
diff --git a/src/eventLists/HeatmapLayerEventList.js b/src/eventLists/HeatmapLayerEventList.js
new file mode 100644
index 00000000..e8ac7de1
--- /dev/null
+++ b/src/eventLists/HeatmapLayerEventList.js
@@ -0,0 +1,5 @@
+// https://developers.google.com/maps/documentation/javascript/3.exp/reference#HeatmapLayer
+// [].map.call($0.querySelectorAll("tr>td>code"), function(it){ return it.textContent; })
+export default [
+ `zoom_changed`,
+];
diff --git a/src/index.js b/src/index.js
index cd8595b6..392dfd7e 100644
--- a/src/index.js
+++ b/src/index.js
@@ -12,3 +12,4 @@ export { default as Polygon } from "./Polygon";
export { default as Polyline } from "./Polyline";
export { default as Rectangle } from "./Rectangle";
export { default as SearchBox } from "./SearchBox";
+export { default as HeatmapLayer } from "./HeatmapLayer";