1. import React, { Component } from 'react'
  2. import PropTypes from 'prop-types'
  3. import { BasemapThumbnail, Label, BasemapSliderContainer, BasemapOption } from './styled'
  4. import { stamenTerrain, osm, stamenTonerDark, stamenTonerLite } from './thumbnails'
  5. import OpenStreetMap from './OpenStreetMap'
  6. import BlankWhite from './BlankWhite'
  7. import StamenTerrain from './StamenTerrain'
  8. import StamenTonerDark from './StamenTonerDark'
  9. import StamenTonerLite from './StamenTonerLite'
  10. import { connectToContext } from 'Provider'
  11. /**
  12. * A floating basemap selector that slides options up to toggle basemap
  13. * @component
  14. * @category Basemap
  15. * @since 0.7.0
  16. */
  17. class BasemapContainer extends Component {
  18. constructor (props) {
  19. super(props)
  20. this.state = {
  21. showBasemaps: false,
  22. basemapOptions: props.basemapOptions
  23. }
  24. }
  25. hideBasemaps = () => {
  26. this.setState({ showBasemaps: false })
  27. }
  28. componentDidUpdate (_, prevState) {
  29. if (prevState.showBasemaps !== this.state.showBasemaps && this.state.showBasemaps === true) {
  30. this.props.map.on('click', this.hideBasemaps)
  31. } else {
  32. this.props.map.un('click', this.hideBasemaps)
  33. }
  34. }
  35. onBasemapChanged = (layer) => {
  36. const { layerTypeID } = this.props
  37. const clonedBasemapOptions = [...this.state.basemapOptions]
  38. const newBasemap = clonedBasemapOptions.find(basemap => basemap.key === layer.get(layerTypeID))
  39. const newIndexOfBasemap = clonedBasemapOptions.indexOf(newBasemap)
  40. const selectedBasemap = clonedBasemapOptions.splice(newIndexOfBasemap, 1)
  41. this.setState({ showBasemaps: false, basemapOptions: [...selectedBasemap, ...clonedBasemapOptions] })
  42. }
  43. render () {
  44. const { showBasemaps, basemapOptions } = this.state
  45. const { variation, style, translations } = this.props
  46. return basemapOptions.map((basemap, i) => {
  47. const zIndex = basemapOptions.length - i
  48. const translationKey = (key) => {
  49. if (key === 'osm') {
  50. return 'OpenStreetMap'
  51. } else {
  52. return key[0].toUpperCase() + key.slice(1)
  53. }
  54. }
  55. if (showBasemaps) {
  56. return (
  57. <BasemapSliderContainer
  58. variation={variation}
  59. style={style}
  60. zIndex={zIndex}
  61. left={0}
  62. bottom={14 + (i * 90)}
  63. key={i}>
  64. {React.cloneElement(basemap, { onBasemapChanged: (layer) => this.onBasemapChanged(layer) })}
  65. </BasemapSliderContainer>
  66. )
  67. } else {
  68. return (
  69. <BasemapSliderContainer
  70. variation={variation}
  71. style={style}
  72. zIndex={zIndex}
  73. onClick={() => this.setState({ showBasemaps: true })}
  74. key={i}
  75. noBoxShadow={i !== 0}>
  76. <BasemapOption>
  77. <BasemapThumbnail thumbnail={basemap.props.thumbnail} />
  78. <Label>{translations[`_ol_kit.${translationKey(basemap.key)}.title`]}</Label>
  79. </BasemapOption>
  80. </BasemapSliderContainer>
  81. )
  82. }
  83. })
  84. }
  85. }
  86. BasemapContainer.defaultProps = {
  87. basemapOptions: [
  88. <OpenStreetMap key='osm' thumbnail={osm} />,
  89. <StamenTerrain key='stamenTerrain' thumbnail={stamenTerrain} />,
  90. <StamenTonerDark key='stamenTonerDark' thumbnail={stamenTonerDark} />,
  91. <StamenTonerLite key='stamenTonerLite' thumbnail={stamenTonerLite} />,
  92. <BlankWhite key='blankWhite' />
  93. ],
  94. layerTypeID: '_ol_kit_basemap'
  95. }
  96. BasemapContainer.propTypes = {
  97. /** array of basemaps i.e. BasemapOpenStreetMap, BasemapStamenTerrain */
  98. basemapOptions: PropTypes.array,
  99. /** 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. */
  100. layerTypeID: PropTypes.oneOfType([PropTypes.symbol, PropTypes.string]),
  101. /** reference to Openlayers map object */
  102. map: PropTypes.object.isRequired,
  103. /** apply inline styles to the map container */
  104. style: PropTypes.object,
  105. /** object of string key/values (see: locales) */
  106. translations: PropTypes.shape({
  107. '_ol_kit.BingMaps.title': PropTypes.string,
  108. '_ol_kit.BlankWhite.title': PropTypes.string,
  109. '_ol_kit.OpenStreetMap.title': PropTypes.string,
  110. '_ol_kit.StamenTerrain.title': PropTypes.string,
  111. '_ol_kit.StamenTonerDark.title': PropTypes.string,
  112. '_ol_kit.StamenTonerLite.title': PropTypes.string
  113. }).isRequired,
  114. /** light or dark variation for styling */
  115. variation: PropTypes.string
  116. }
  117. export default connectToContext(BasemapContainer)