Merged in feat/SW-2041-map-zoom-buttons (pull request #2550)
Feat(SW-661): Hotel page map zoom restrictions * fix(SW-2041): update tokens * chore(SW-2041): restrict zooming * fix(SW-2041): remove ref * fix(SW-2041): create map zoom hook Approved-by: Erik Tiekstra Approved-by: Hrishikesh Vaipurkar
This commit is contained in:
@@ -4,10 +4,17 @@ import { Map, type MapProps, useMap } from "@vis.gl/react-google-maps"
|
||||
import { useEffect, useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { IconButton } from "@scandic-hotels/design-system/IconButton"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
||||
|
||||
import { MAP_RESTRICTIONS } from "@/constants/map"
|
||||
import {
|
||||
DEFAULT_ZOOM,
|
||||
MAP_RESTRICTIONS,
|
||||
MAX_ZOOM,
|
||||
MIN_ZOOM,
|
||||
} from "@/constants/map"
|
||||
|
||||
import { useZoomControls } from "@/hooks/maps/useZoomControls"
|
||||
|
||||
import HotelListingMapContent from "./HotelListingMapContent"
|
||||
import PoiMapMarkers from "./PoiMapMarkers"
|
||||
@@ -31,9 +38,12 @@ export default function InteractiveMap({
|
||||
const intl = useIntl()
|
||||
const map = useMap()
|
||||
const [hasInitializedBounds, setHasInitializedBounds] = useState(false)
|
||||
const { zoomIn, zoomOut, isMaxZoom, isMinZoom } = useZoomControls()
|
||||
|
||||
const mapOptions: MapProps = {
|
||||
defaultZoom: 14,
|
||||
defaultZoom: DEFAULT_ZOOM,
|
||||
minZoom: MIN_ZOOM,
|
||||
maxZoom: MAX_ZOOM,
|
||||
defaultCenter: coordinates,
|
||||
disableDefaultUI: true,
|
||||
clickableIcons: false,
|
||||
@@ -42,19 +52,6 @@ export default function InteractiveMap({
|
||||
restriction: MAP_RESTRICTIONS,
|
||||
}
|
||||
|
||||
function zoomIn() {
|
||||
const currentZoom = map && map.getZoom()
|
||||
if (currentZoom) {
|
||||
map.setZoom(currentZoom + 1)
|
||||
}
|
||||
}
|
||||
function zoomOut() {
|
||||
const currentZoom = map && map.getZoom()
|
||||
if (currentZoom) {
|
||||
map.setZoom(currentZoom - 1)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (map && hotelPins?.length && !hasInitializedBounds) {
|
||||
if (fitBounds) {
|
||||
@@ -62,7 +59,6 @@ export default function InteractiveMap({
|
||||
hotelPins.forEach((marker) => {
|
||||
bounds.extend(marker.coordinates)
|
||||
})
|
||||
|
||||
map.fitBounds(bounds, 100)
|
||||
}
|
||||
setHasInitializedBounds(true)
|
||||
@@ -86,32 +82,31 @@ export default function InteractiveMap({
|
||||
<div className={styles.ctaButtons}>
|
||||
{closeButton}
|
||||
<div className={styles.zoomButtons}>
|
||||
<Button
|
||||
theme="base"
|
||||
intent="inverted"
|
||||
variant="icon"
|
||||
size="small"
|
||||
<IconButton
|
||||
theme="Inverted"
|
||||
style="Elevated"
|
||||
className={styles.zoomButton}
|
||||
onClick={zoomOut}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Zoom in",
|
||||
defaultMessage: "Zoom out",
|
||||
})}
|
||||
isDisabled={isMinZoom}
|
||||
>
|
||||
<MaterialIcon icon="remove" color="CurrentColor" />
|
||||
</Button>
|
||||
<Button
|
||||
theme="base"
|
||||
intent="inverted"
|
||||
variant="icon"
|
||||
size="small"
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
theme="Inverted"
|
||||
style="Elevated"
|
||||
className={styles.zoomButton}
|
||||
onClick={zoomIn}
|
||||
aria-label={intl.formatMessage({
|
||||
defaultMessage: "Zoom out",
|
||||
defaultMessage: "Zoom in",
|
||||
})}
|
||||
isDisabled={isMaxZoom}
|
||||
>
|
||||
<MaterialIcon icon="add" color="CurrentColor" />
|
||||
</Button>
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -59,8 +59,8 @@
|
||||
}
|
||||
|
||||
.zoomButton {
|
||||
width: var(--Spacing-x5);
|
||||
height: var(--Spacing-x5);
|
||||
width: var(--Space-x5);
|
||||
height: var(--Space-x5);
|
||||
padding: 0;
|
||||
pointer-events: initial;
|
||||
box-shadow: var(--button-box-shadow);
|
||||
|
||||
@@ -3,3 +3,7 @@ export const MAP_RESTRICTIONS = {
|
||||
// See https://developers.google.com/maps/documentation/javascript/reference/map#MapRestriction.latLngBounds
|
||||
latLngBounds: { north: 85, south: -85, west: -180, east: 180 },
|
||||
}
|
||||
|
||||
export const DEFAULT_ZOOM = 14
|
||||
export const MAX_ZOOM = 18
|
||||
export const MIN_ZOOM = 8
|
||||
|
||||
43
apps/scandic-web/hooks/maps/useZoomControls.ts
Normal file
43
apps/scandic-web/hooks/maps/useZoomControls.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { useMap } from "@vis.gl/react-google-maps"
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
import { DEFAULT_ZOOM, MAX_ZOOM, MIN_ZOOM } from "@/constants/map"
|
||||
|
||||
export function useZoomControls() {
|
||||
const map = useMap()
|
||||
const [zoomLevel, setZoomLevel] = useState(DEFAULT_ZOOM)
|
||||
|
||||
const zoomIn = () => {
|
||||
if (map && zoomLevel < MAX_ZOOM) {
|
||||
map.setZoom(zoomLevel + 1)
|
||||
}
|
||||
}
|
||||
|
||||
const zoomOut = () => {
|
||||
if (map && zoomLevel > MIN_ZOOM) {
|
||||
map.setZoom(zoomLevel - 1)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!map) return
|
||||
|
||||
const handleZoomChanged = () => {
|
||||
const currentZoom = map.getZoom()
|
||||
if (currentZoom != null) {
|
||||
setZoomLevel(currentZoom)
|
||||
}
|
||||
}
|
||||
|
||||
const listener = map.addListener("zoom_changed", handleZoomChanged)
|
||||
return () => listener.remove()
|
||||
}, [map])
|
||||
|
||||
return {
|
||||
zoomLevel,
|
||||
zoomIn,
|
||||
zoomOut,
|
||||
isMinZoom: zoomLevel <= MIN_ZOOM,
|
||||
isMaxZoom: zoomLevel >= MAX_ZOOM,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user