@page-speed/maps 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/geo-map.cjs +121 -28
- package/dist/components/geo-map.cjs.map +1 -1
- package/dist/components/geo-map.js +122 -29
- package/dist/components/geo-map.js.map +1 -1
- package/dist/components/index.cjs +121 -28
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +122 -29
- package/dist/components/index.js.map +1 -1
- package/dist/index.cjs +53 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +53 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React3 from 'react';
|
|
2
|
-
import React3__default from 'react';
|
|
2
|
+
import React3__default, { useMemo } from 'react';
|
|
3
3
|
import { Marker, Map as Map$1, GeolocateControl, NavigationControl } from 'react-map-gl/maplibre';
|
|
4
4
|
import { clsx } from 'clsx';
|
|
5
5
|
import { twMerge } from 'tailwind-merge';
|
|
@@ -518,6 +518,74 @@ function MapLibre({
|
|
|
518
518
|
}
|
|
519
519
|
);
|
|
520
520
|
}
|
|
521
|
+
var TILE_SIZE = 512;
|
|
522
|
+
function latToMercatorY(lat) {
|
|
523
|
+
const latRad = lat * Math.PI / 180;
|
|
524
|
+
const mercN = Math.log(Math.tan(Math.PI / 4 + latRad / 2));
|
|
525
|
+
return TILE_SIZE / (2 * Math.PI) * (Math.PI - mercN);
|
|
526
|
+
}
|
|
527
|
+
function lngToMercatorX(lng) {
|
|
528
|
+
return TILE_SIZE / (2 * Math.PI) * ((lng + 180) / 360 * 2 * Math.PI);
|
|
529
|
+
}
|
|
530
|
+
function computeDefaultZoom(options) {
|
|
531
|
+
const {
|
|
532
|
+
coordinates,
|
|
533
|
+
mapWidth,
|
|
534
|
+
mapHeight,
|
|
535
|
+
padding = 50,
|
|
536
|
+
maxZoom = 18,
|
|
537
|
+
minZoom = 1
|
|
538
|
+
} = options;
|
|
539
|
+
if (coordinates.length === 0) return null;
|
|
540
|
+
if (coordinates.length === 1) return maxZoom;
|
|
541
|
+
if (mapWidth <= 0 || mapHeight <= 0) return null;
|
|
542
|
+
let minLat = Infinity;
|
|
543
|
+
let maxLat = -Infinity;
|
|
544
|
+
let minLng = Infinity;
|
|
545
|
+
let maxLng = -Infinity;
|
|
546
|
+
for (const coord of coordinates) {
|
|
547
|
+
if (coord.lat < minLat) minLat = coord.lat;
|
|
548
|
+
if (coord.lat > maxLat) maxLat = coord.lat;
|
|
549
|
+
if (coord.lng < minLng) minLng = coord.lng;
|
|
550
|
+
if (coord.lng > maxLng) maxLng = coord.lng;
|
|
551
|
+
}
|
|
552
|
+
const pixelXMin = lngToMercatorX(minLng);
|
|
553
|
+
const pixelXMax = lngToMercatorX(maxLng);
|
|
554
|
+
const pixelYMin = latToMercatorY(maxLat);
|
|
555
|
+
const pixelYMax = latToMercatorY(minLat);
|
|
556
|
+
const dx = Math.abs(pixelXMax - pixelXMin);
|
|
557
|
+
const dy = Math.abs(pixelYMax - pixelYMin);
|
|
558
|
+
const availableWidth = mapWidth - padding * 2;
|
|
559
|
+
const availableHeight = mapHeight - padding * 2;
|
|
560
|
+
if (availableWidth <= 0 || availableHeight <= 0) return minZoom;
|
|
561
|
+
let zoom;
|
|
562
|
+
if (dx === 0 && dy === 0) {
|
|
563
|
+
return maxZoom;
|
|
564
|
+
} else if (dx === 0) {
|
|
565
|
+
zoom = Math.log2(availableHeight / dy);
|
|
566
|
+
} else if (dy === 0) {
|
|
567
|
+
zoom = Math.log2(availableWidth / dx);
|
|
568
|
+
} else {
|
|
569
|
+
const zoomX = Math.log2(availableWidth / dx);
|
|
570
|
+
const zoomY = Math.log2(availableHeight / dy);
|
|
571
|
+
zoom = Math.min(zoomX, zoomY);
|
|
572
|
+
}
|
|
573
|
+
return Math.max(minZoom, Math.min(maxZoom, Math.floor(zoom * 100) / 100));
|
|
574
|
+
}
|
|
575
|
+
function useDefaultZoom(options) {
|
|
576
|
+
const { coordinates, mapWidth, mapHeight, padding, maxZoom, minZoom } = options;
|
|
577
|
+
return useMemo(
|
|
578
|
+
() => computeDefaultZoom({
|
|
579
|
+
coordinates,
|
|
580
|
+
mapWidth,
|
|
581
|
+
mapHeight,
|
|
582
|
+
padding,
|
|
583
|
+
maxZoom,
|
|
584
|
+
minZoom
|
|
585
|
+
}),
|
|
586
|
+
[coordinates, mapWidth, mapHeight, padding, maxZoom, minZoom]
|
|
587
|
+
);
|
|
588
|
+
}
|
|
521
589
|
var PANEL_POSITION_CLASS = {
|
|
522
590
|
"top-left": "left-4 top-4",
|
|
523
591
|
"top-right": "right-4 top-4",
|
|
@@ -766,6 +834,13 @@ function GeoMap({
|
|
|
766
834
|
IconComponent = FallbackIcon,
|
|
767
835
|
ImgComponent = FallbackImg
|
|
768
836
|
}) {
|
|
837
|
+
const containerRef = React3.useRef(null);
|
|
838
|
+
const [containerDimensions, setContainerDimensions] = React3.useState({
|
|
839
|
+
width: 800,
|
|
840
|
+
// Default width
|
|
841
|
+
height: 520
|
|
842
|
+
// Default height
|
|
843
|
+
});
|
|
769
844
|
const [isMobile, setIsMobile] = React3.useState(false);
|
|
770
845
|
React3.useEffect(() => {
|
|
771
846
|
const checkMobile = () => {
|
|
@@ -781,6 +856,24 @@ function GeoMap({
|
|
|
781
856
|
}
|
|
782
857
|
return isMobile ? 420 : 520;
|
|
783
858
|
}, [mapSize, isMobile]);
|
|
859
|
+
React3.useEffect(() => {
|
|
860
|
+
if (!containerRef.current) return;
|
|
861
|
+
const updateDimensions = () => {
|
|
862
|
+
if (containerRef.current) {
|
|
863
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
864
|
+
setContainerDimensions({
|
|
865
|
+
width: rect.width || 800,
|
|
866
|
+
height: rect.height || calculatedHeight
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
updateDimensions();
|
|
871
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
872
|
+
const resizeObserver = new ResizeObserver(updateDimensions);
|
|
873
|
+
resizeObserver.observe(containerRef.current);
|
|
874
|
+
return () => resizeObserver.disconnect();
|
|
875
|
+
}
|
|
876
|
+
}, [calculatedHeight]);
|
|
784
877
|
const normalizedStandaloneMarkers = React3.useMemo(
|
|
785
878
|
() => markers.map((marker, index) => ({
|
|
786
879
|
...marker,
|
|
@@ -864,42 +957,41 @@ function GeoMap({
|
|
|
864
957
|
longitude: DEFAULT_VIEW_STATE.longitude
|
|
865
958
|
};
|
|
866
959
|
}, [normalizedClusters, normalizedStandaloneMarkers]);
|
|
867
|
-
const
|
|
868
|
-
|
|
869
|
-
return markerFocusZoom;
|
|
870
|
-
}
|
|
871
|
-
const allCoords = [];
|
|
960
|
+
const zoomCoordinates = React3.useMemo(() => {
|
|
961
|
+
const coords = [];
|
|
872
962
|
normalizedStandaloneMarkers.forEach((marker) => {
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
963
|
+
coords.push({
|
|
964
|
+
lat: marker.latitude,
|
|
965
|
+
lng: marker.longitude
|
|
876
966
|
});
|
|
877
967
|
});
|
|
878
968
|
normalizedClusters.forEach((cluster) => {
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
969
|
+
coords.push({
|
|
970
|
+
lat: cluster.latitude,
|
|
971
|
+
lng: cluster.longitude
|
|
882
972
|
});
|
|
883
973
|
});
|
|
884
|
-
|
|
974
|
+
return coords;
|
|
975
|
+
}, [normalizedStandaloneMarkers, normalizedClusters]);
|
|
976
|
+
const properZoom = useDefaultZoom({
|
|
977
|
+
coordinates: zoomCoordinates,
|
|
978
|
+
mapWidth: containerDimensions.width,
|
|
979
|
+
mapHeight: containerDimensions.height,
|
|
980
|
+
padding: 80,
|
|
981
|
+
// Increased padding for better framing
|
|
982
|
+
maxZoom: 18,
|
|
983
|
+
minZoom: 1
|
|
984
|
+
});
|
|
985
|
+
const calculatedZoom = React3.useMemo(() => {
|
|
986
|
+
if (zoomCoordinates.length === 1) {
|
|
987
|
+
return markerFocusZoom;
|
|
988
|
+
}
|
|
989
|
+
if (zoomCoordinates.length === 0) {
|
|
885
990
|
return DEFAULT_VIEW_STATE.zoom;
|
|
886
991
|
}
|
|
887
|
-
const
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
const lngDiff = Math.max(...lngs) - Math.min(...lngs);
|
|
891
|
-
const maxDiff = Math.max(latDiff, lngDiff);
|
|
892
|
-
const heightFactor = calculatedHeight / 520;
|
|
893
|
-
const paddingFactor = 0.85;
|
|
894
|
-
if (maxDiff > 10) return Math.max(2, 3 * heightFactor * paddingFactor);
|
|
895
|
-
if (maxDiff > 5) return Math.max(4, 5 * heightFactor * paddingFactor);
|
|
896
|
-
if (maxDiff > 2) return Math.max(6, 7 * heightFactor * paddingFactor);
|
|
897
|
-
if (maxDiff > 1) return Math.max(8, 9 * heightFactor * paddingFactor);
|
|
898
|
-
if (maxDiff > 0.5) return Math.max(9, 10 * heightFactor * paddingFactor);
|
|
899
|
-
if (maxDiff > 0.1) return Math.max(11, 12 * heightFactor * paddingFactor);
|
|
900
|
-
if (maxDiff > 0.01) return Math.max(12, 13 * heightFactor * paddingFactor);
|
|
901
|
-
return Math.max(11, 12 * heightFactor * paddingFactor);
|
|
902
|
-
}, [normalizedClusters, normalizedStandaloneMarkers, markerFocusZoom, calculatedHeight]);
|
|
992
|
+
const adjustedZoom = properZoom ? properZoom - 0.5 : DEFAULT_VIEW_STATE.zoom;
|
|
993
|
+
return Math.min(adjustedZoom, 15);
|
|
994
|
+
}, [properZoom, zoomCoordinates.length, markerFocusZoom]);
|
|
903
995
|
const [uncontrolledViewState, setUncontrolledViewState] = React3.useState({
|
|
904
996
|
latitude: defaultViewState?.latitude ?? firstCoordinate.latitude,
|
|
905
997
|
longitude: defaultViewState?.longitude ?? firstCoordinate.longitude,
|
|
@@ -1225,6 +1317,7 @@ function GeoMap({
|
|
|
1225
1317
|
return /* @__PURE__ */ jsxs(
|
|
1226
1318
|
"div",
|
|
1227
1319
|
{
|
|
1320
|
+
ref: containerRef,
|
|
1228
1321
|
className: cn(
|
|
1229
1322
|
"relative rounded-2xl border border-border bg-background",
|
|
1230
1323
|
// Remove overflow-hidden from outer container to allow panel to overflow
|