From 2733c8c5572515e84d168571eb9ad341e3a730b0 Mon Sep 17 00:00:00 2001 From: Finn Hermeling Date: Mon, 24 Feb 2025 22:02:20 +0100 Subject: [PATCH 1/5] fix: tolerate Math platform implementation variance --- src/map/Map.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/map/Map.tsx b/src/map/Map.tsx index 38a9c26..247d9ba 100644 --- a/src/map/Map.tsx +++ b/src/map/Map.tsx @@ -1047,10 +1047,18 @@ export class Map extends Component { const tileX = lng2tile(latLng[1], zoom) const tileY = lat2tile(latLng[0], zoom) - return [ - (tileX - tileCenterX) * 256.0 + width / 2 + (pixelDelta ? pixelDelta[0] : 0), - (tileY - tileCenterY) * 256.0 + height / 2 + (pixelDelta ? pixelDelta[1] : 0), - ] as Point + const pixelX = (tileX - tileCenterX) * 256.0 + width / 2 + (pixelDelta ? pixelDelta[0] : 0) + const pixelY = (tileY - tileCenterY) * 256.0 + height / 2 + (pixelDelta ? pixelDelta[1] : 0) + + // If SSR is used, this enclosing function must always return the same result for the same input. + // When the values are computed with e.g. Math.cos (Math.log, ...), the exact implementatiom is platform + // dependent and results can slightly vary. + // See https://stackoverflow.com/questions/26570626/math-log2-precision-has-changed-in-chrome + const roundMathImprecision = (pixel: number) => { + return Math.round(pixel * 1000) / 1000 + } + + return [roundMathImprecision(pixelX), roundMathImprecision(pixelY)] } calculateZoomCenter = (center: Point, coords: Point, oldZoom: number, newZoom: number): Point => { From c954c748ce5bea2e8d5cfc628979490d613893b4 Mon Sep 17 00:00:00 2001 From: Finn Hermeling Date: Tue, 25 Feb 2025 00:39:08 +0100 Subject: [PATCH 2/5] fix: correctly declare callback argument type --- src/overlays/Marker.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/overlays/Marker.tsx b/src/overlays/Marker.tsx index f1970c2..76f79a7 100644 --- a/src/overlays/Marker.tsx +++ b/src/overlays/Marker.tsx @@ -1,5 +1,11 @@ import React, { useState } from 'react' -import { PigeonProps } from '../types' +import { PigeonProps, Point } from '../types' + +type CallbackArgs = { + event: React.MouseEvent + anchor: Point + payload: any +} interface MarkerProps extends PigeonProps { color?: string @@ -16,10 +22,10 @@ interface MarkerProps extends PigeonProps { children?: JSX.Element // callbacks - onClick?: ({ event: HTMLMouseEvent, anchor: Point, payload: any }) => void - onContextMenu?: ({ event: HTMLMouseEvent, anchor: Point, payload: any }) => void - onMouseOver?: ({ event: HTMLMouseEvent, anchor: Point, payload: any }) => void - onMouseOut?: ({ event: HTMLMouseEvent, anchor: Point, payload: any }) => void + onClick?: (arg: CallbackArgs) => void + onContextMenu?: (arg: CallbackArgs) => void + onMouseOver?: (arg: CallbackArgs) => void + onMouseOut?: (arg: CallbackArgs) => void } export function Marker(props: MarkerProps): JSX.Element { From 0616549584cd9fc5d12e0f63da84935b02493b72 Mon Sep 17 00:00:00 2001 From: Finn Hermeling Date: Tue, 25 Feb 2025 00:54:23 +0100 Subject: [PATCH 3/5] feat: strongly type payload argument --- src/overlays/Marker.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/overlays/Marker.tsx b/src/overlays/Marker.tsx index 76f79a7..bac47ca 100644 --- a/src/overlays/Marker.tsx +++ b/src/overlays/Marker.tsx @@ -1,15 +1,15 @@ import React, { useState } from 'react' import { PigeonProps, Point } from '../types' -type CallbackArgs = { +type CallbackArgs

= { event: React.MouseEvent anchor: Point - payload: any + payload: P } -interface MarkerProps extends PigeonProps { +interface MarkerProps

extends PigeonProps { color?: string - payload?: any + payload?: P width?: number height?: number @@ -22,13 +22,13 @@ interface MarkerProps extends PigeonProps { children?: JSX.Element // callbacks - onClick?: (arg: CallbackArgs) => void - onContextMenu?: (arg: CallbackArgs) => void - onMouseOver?: (arg: CallbackArgs) => void - onMouseOut?: (arg: CallbackArgs) => void + onClick?: (arg: CallbackArgs

) => void + onContextMenu?: (arg: CallbackArgs

) => void + onMouseOver?: (arg: CallbackArgs

) => void + onMouseOut?: (arg: CallbackArgs

) => void } -export function Marker(props: MarkerProps): JSX.Element { +export function Marker

(props: MarkerProps

): JSX.Element { const width = typeof props.width !== 'undefined' ? props.width From 467af2e78adde14ea488af1408d21b7e63931669 Mon Sep 17 00:00:00 2001 From: Finn Hermeling Date: Tue, 25 Feb 2025 10:57:23 +0100 Subject: [PATCH 4/5] fix: run pre commit hook on tsx files --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index cd1a758..1597f8e 100644 --- a/package.json +++ b/package.json @@ -98,6 +98,8 @@ } }, "lint-staged": { - "*.{js,css,scss}": "prettier --write" + "*.{js,css,scss}": "prettier --write", + "src/**/*.tsx": "prettier --write", + "demo/**/*.tsx": "prettier --write" } } From 80c5fcace6ddab09b3defc9fb0f422e86fbaaf2a Mon Sep 17 00:00:00 2001 From: Finn Hermeling Date: Tue, 25 Feb 2025 11:04:17 +0100 Subject: [PATCH 5/5] feat: include width and height with enclosing container It is irritating if the width and height is unused when using custom icons for the marker. --- src/overlays/Marker.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/overlays/Marker.tsx b/src/overlays/Marker.tsx index bac47ca..c13e102 100644 --- a/src/overlays/Marker.tsx +++ b/src/overlays/Marker.tsx @@ -60,6 +60,8 @@ export function Marker

(props: MarkerProps

): JSX.Element { filter: hover ? 'drop-shadow(0 0 4px rgba(0, 0, 0, .3))' : '', pointerEvents: 'none', cursor: 'pointer', + width: width, + height: height, ...(props.style || {}), }} className={props.className ? `${props.className} pigeon-click-block` : 'pigeon-click-block'}