import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { BasemapThumbnail, Label, BasemapSliderContainer, BasemapOption } from './styled'
import { stamenTerrain, osm, stamenTonerDark, stamenTonerLite } from './thumbnails'
import OpenStreetMap from './OpenStreetMap'
import BlankWhite from './BlankWhite'
import StamenTerrain from './StamenTerrain'
import StamenTonerDark from './StamenTonerDark'
import StamenTonerLite from './StamenTonerLite'
import { connectToContext } from 'Provider'
/**
* A floating basemap selector that slides options up to toggle basemap
* @component
* @category Basemap
* @since 0.7.0
*/
class BasemapContainer extends Component {
constructor (props) {
super(props)
this.state = {
showBasemaps: false,
basemapOptions: props.basemapOptions
}
}
hideBasemaps = () => {
this.setState({ showBasemaps: false })
}
componentDidUpdate (_, prevState) {
if (prevState.showBasemaps !== this.state.showBasemaps && this.state.showBasemaps === true) {
this.props.map.on('click', this.hideBasemaps)
} else {
this.props.map.un('click', this.hideBasemaps)
}
}
onBasemapChanged = (layer) => {
const { layerTypeID } = this.props
const clonedBasemapOptions = [...this.state.basemapOptions]
const newBasemap = clonedBasemapOptions.find(basemap => basemap.key === layer.get(layerTypeID))
const newIndexOfBasemap = clonedBasemapOptions.indexOf(newBasemap)
const selectedBasemap = clonedBasemapOptions.splice(newIndexOfBasemap, 1)
this.setState({ showBasemaps: false, basemapOptions: [...selectedBasemap, ...clonedBasemapOptions] })
}
render () {
const { showBasemaps, basemapOptions } = this.state
const { variation, style, translations } = this.props
return basemapOptions.map((basemap, i) => {
const zIndex = basemapOptions.length - i
const translationKey = (key) => {
if (key === 'osm') {
return 'OpenStreetMap'
} else {
return key[0].toUpperCase() + key.slice(1)
}
}
if (showBasemaps) {
return (
<BasemapSliderContainer
variation={variation}
style={style}
zIndex={zIndex}
left={0}
bottom={14 + (i * 90)}
key={i}>
{React.cloneElement(basemap, { onBasemapChanged: (layer) => this.onBasemapChanged(layer) })}
</BasemapSliderContainer>
)
} else {
return (
<BasemapSliderContainer
variation={variation}
style={style}
zIndex={zIndex}
onClick={() => this.setState({ showBasemaps: true })}
key={i}
noBoxShadow={i !== 0}>
<BasemapOption>
<BasemapThumbnail thumbnail={basemap.props.thumbnail} />
<Label>{translations[`_ol_kit.${translationKey(basemap.key)}.title`]}</Label>
</BasemapOption>
</BasemapSliderContainer>
)
}
})
}
}
BasemapContainer.defaultProps = {
basemapOptions: [
<OpenStreetMap key='osm' thumbnail={osm} />,
<StamenTerrain key='stamenTerrain' thumbnail={stamenTerrain} />,
<StamenTonerDark key='stamenTonerDark' thumbnail={stamenTonerDark} />,
<StamenTonerLite key='stamenTonerLite' thumbnail={stamenTonerLite} />,
<BlankWhite key='blankWhite' />
],
layerTypeID: '_ol_kit_basemap'
}
BasemapContainer.propTypes = {
/** array of basemaps i.e. BasemapOpenStreetMap, BasemapStamenTerrain */
basemapOptions: PropTypes.array,
/** A unique string or symbol property name that will be set directly on the layer when it is created with a value containing a string identifying the type of basemap layer (e.g. '_ol_kit_basemap': 'osm'). This property should be a shared ID used to identify individual layers as 'basemap' layers. */
layerTypeID: PropTypes.oneOfType([PropTypes.symbol, PropTypes.string]),
/** reference to Openlayers map object */
map: PropTypes.object.isRequired,
/** apply inline styles to the map container */
style: PropTypes.object,
/** object of string key/values (see: locales) */
translations: PropTypes.shape({
'_ol_kit.BingMaps.title': PropTypes.string,
'_ol_kit.BlankWhite.title': PropTypes.string,
'_ol_kit.OpenStreetMap.title': PropTypes.string,
'_ol_kit.StamenTerrain.title': PropTypes.string,
'_ol_kit.StamenTonerDark.title': PropTypes.string,
'_ol_kit.StamenTonerLite.title': PropTypes.string
}).isRequired,
/** light or dark variation for styling */
variation: PropTypes.string
}
export default connectToContext(BasemapContainer)