@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
|
@@ -658,6 +658,74 @@ function MapLibre({
|
|
|
658
658
|
}
|
|
659
659
|
);
|
|
660
660
|
}
|
|
661
|
+
var TILE_SIZE = 512;
|
|
662
|
+
function latToMercatorY(lat) {
|
|
663
|
+
const latRad = lat * Math.PI / 180;
|
|
664
|
+
const mercN = Math.log(Math.tan(Math.PI / 4 + latRad / 2));
|
|
665
|
+
return TILE_SIZE / (2 * Math.PI) * (Math.PI - mercN);
|
|
666
|
+
}
|
|
667
|
+
function lngToMercatorX(lng) {
|
|
668
|
+
return TILE_SIZE / (2 * Math.PI) * ((lng + 180) / 360 * 2 * Math.PI);
|
|
669
|
+
}
|
|
670
|
+
function computeDefaultZoom(options) {
|
|
671
|
+
const {
|
|
672
|
+
coordinates,
|
|
673
|
+
mapWidth,
|
|
674
|
+
mapHeight,
|
|
675
|
+
padding = 50,
|
|
676
|
+
maxZoom = 18,
|
|
677
|
+
minZoom = 1
|
|
678
|
+
} = options;
|
|
679
|
+
if (coordinates.length === 0) return null;
|
|
680
|
+
if (coordinates.length === 1) return maxZoom;
|
|
681
|
+
if (mapWidth <= 0 || mapHeight <= 0) return null;
|
|
682
|
+
let minLat = Infinity;
|
|
683
|
+
let maxLat = -Infinity;
|
|
684
|
+
let minLng = Infinity;
|
|
685
|
+
let maxLng = -Infinity;
|
|
686
|
+
for (const coord of coordinates) {
|
|
687
|
+
if (coord.lat < minLat) minLat = coord.lat;
|
|
688
|
+
if (coord.lat > maxLat) maxLat = coord.lat;
|
|
689
|
+
if (coord.lng < minLng) minLng = coord.lng;
|
|
690
|
+
if (coord.lng > maxLng) maxLng = coord.lng;
|
|
691
|
+
}
|
|
692
|
+
const pixelXMin = lngToMercatorX(minLng);
|
|
693
|
+
const pixelXMax = lngToMercatorX(maxLng);
|
|
694
|
+
const pixelYMin = latToMercatorY(maxLat);
|
|
695
|
+
const pixelYMax = latToMercatorY(minLat);
|
|
696
|
+
const dx = Math.abs(pixelXMax - pixelXMin);
|
|
697
|
+
const dy = Math.abs(pixelYMax - pixelYMin);
|
|
698
|
+
const availableWidth = mapWidth - padding * 2;
|
|
699
|
+
const availableHeight = mapHeight - padding * 2;
|
|
700
|
+
if (availableWidth <= 0 || availableHeight <= 0) return minZoom;
|
|
701
|
+
let zoom;
|
|
702
|
+
if (dx === 0 && dy === 0) {
|
|
703
|
+
return maxZoom;
|
|
704
|
+
} else if (dx === 0) {
|
|
705
|
+
zoom = Math.log2(availableHeight / dy);
|
|
706
|
+
} else if (dy === 0) {
|
|
707
|
+
zoom = Math.log2(availableWidth / dx);
|
|
708
|
+
} else {
|
|
709
|
+
const zoomX = Math.log2(availableWidth / dx);
|
|
710
|
+
const zoomY = Math.log2(availableHeight / dy);
|
|
711
|
+
zoom = Math.min(zoomX, zoomY);
|
|
712
|
+
}
|
|
713
|
+
return Math.max(minZoom, Math.min(maxZoom, Math.floor(zoom * 100) / 100));
|
|
714
|
+
}
|
|
715
|
+
function useDefaultZoom(options) {
|
|
716
|
+
const { coordinates, mapWidth, mapHeight, padding, maxZoom, minZoom } = options;
|
|
717
|
+
return React3.useMemo(
|
|
718
|
+
() => computeDefaultZoom({
|
|
719
|
+
coordinates,
|
|
720
|
+
mapWidth,
|
|
721
|
+
mapHeight,
|
|
722
|
+
padding,
|
|
723
|
+
maxZoom,
|
|
724
|
+
minZoom
|
|
725
|
+
}),
|
|
726
|
+
[coordinates, mapWidth, mapHeight, padding, maxZoom, minZoom]
|
|
727
|
+
);
|
|
728
|
+
}
|
|
661
729
|
var PANEL_POSITION_CLASS = {
|
|
662
730
|
"top-left": "left-4 top-4",
|
|
663
731
|
"top-right": "right-4 top-4",
|
|
@@ -906,6 +974,13 @@ function GeoMap({
|
|
|
906
974
|
IconComponent = FallbackIcon,
|
|
907
975
|
ImgComponent = FallbackImg
|
|
908
976
|
}) {
|
|
977
|
+
const containerRef = React3__namespace.useRef(null);
|
|
978
|
+
const [containerDimensions, setContainerDimensions] = React3__namespace.useState({
|
|
979
|
+
width: 800,
|
|
980
|
+
// Default width
|
|
981
|
+
height: 520
|
|
982
|
+
// Default height
|
|
983
|
+
});
|
|
909
984
|
const [isMobile, setIsMobile] = React3__namespace.useState(false);
|
|
910
985
|
React3__namespace.useEffect(() => {
|
|
911
986
|
const checkMobile = () => {
|
|
@@ -921,6 +996,24 @@ function GeoMap({
|
|
|
921
996
|
}
|
|
922
997
|
return isMobile ? 420 : 520;
|
|
923
998
|
}, [mapSize, isMobile]);
|
|
999
|
+
React3__namespace.useEffect(() => {
|
|
1000
|
+
if (!containerRef.current) return;
|
|
1001
|
+
const updateDimensions = () => {
|
|
1002
|
+
if (containerRef.current) {
|
|
1003
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
1004
|
+
setContainerDimensions({
|
|
1005
|
+
width: rect.width || 800,
|
|
1006
|
+
height: rect.height || calculatedHeight
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
1010
|
+
updateDimensions();
|
|
1011
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
1012
|
+
const resizeObserver = new ResizeObserver(updateDimensions);
|
|
1013
|
+
resizeObserver.observe(containerRef.current);
|
|
1014
|
+
return () => resizeObserver.disconnect();
|
|
1015
|
+
}
|
|
1016
|
+
}, [calculatedHeight]);
|
|
924
1017
|
const normalizedStandaloneMarkers = React3__namespace.useMemo(
|
|
925
1018
|
() => markers.map((marker, index) => ({
|
|
926
1019
|
...marker,
|
|
@@ -1004,42 +1097,41 @@ function GeoMap({
|
|
|
1004
1097
|
longitude: DEFAULT_VIEW_STATE.longitude
|
|
1005
1098
|
};
|
|
1006
1099
|
}, [normalizedClusters, normalizedStandaloneMarkers]);
|
|
1007
|
-
const
|
|
1008
|
-
|
|
1009
|
-
return markerFocusZoom;
|
|
1010
|
-
}
|
|
1011
|
-
const allCoords = [];
|
|
1100
|
+
const zoomCoordinates = React3__namespace.useMemo(() => {
|
|
1101
|
+
const coords = [];
|
|
1012
1102
|
normalizedStandaloneMarkers.forEach((marker) => {
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1103
|
+
coords.push({
|
|
1104
|
+
lat: marker.latitude,
|
|
1105
|
+
lng: marker.longitude
|
|
1016
1106
|
});
|
|
1017
1107
|
});
|
|
1018
1108
|
normalizedClusters.forEach((cluster) => {
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1109
|
+
coords.push({
|
|
1110
|
+
lat: cluster.latitude,
|
|
1111
|
+
lng: cluster.longitude
|
|
1022
1112
|
});
|
|
1023
1113
|
});
|
|
1024
|
-
|
|
1114
|
+
return coords;
|
|
1115
|
+
}, [normalizedStandaloneMarkers, normalizedClusters]);
|
|
1116
|
+
const properZoom = useDefaultZoom({
|
|
1117
|
+
coordinates: zoomCoordinates,
|
|
1118
|
+
mapWidth: containerDimensions.width,
|
|
1119
|
+
mapHeight: containerDimensions.height,
|
|
1120
|
+
padding: 80,
|
|
1121
|
+
// Increased padding for better framing
|
|
1122
|
+
maxZoom: 18,
|
|
1123
|
+
minZoom: 1
|
|
1124
|
+
});
|
|
1125
|
+
const calculatedZoom = React3__namespace.useMemo(() => {
|
|
1126
|
+
if (zoomCoordinates.length === 1) {
|
|
1127
|
+
return markerFocusZoom;
|
|
1128
|
+
}
|
|
1129
|
+
if (zoomCoordinates.length === 0) {
|
|
1025
1130
|
return DEFAULT_VIEW_STATE.zoom;
|
|
1026
1131
|
}
|
|
1027
|
-
const
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
const lngDiff = Math.max(...lngs) - Math.min(...lngs);
|
|
1031
|
-
const maxDiff = Math.max(latDiff, lngDiff);
|
|
1032
|
-
const heightFactor = calculatedHeight / 520;
|
|
1033
|
-
const paddingFactor = 0.85;
|
|
1034
|
-
if (maxDiff > 10) return Math.max(2, 3 * heightFactor * paddingFactor);
|
|
1035
|
-
if (maxDiff > 5) return Math.max(4, 5 * heightFactor * paddingFactor);
|
|
1036
|
-
if (maxDiff > 2) return Math.max(6, 7 * heightFactor * paddingFactor);
|
|
1037
|
-
if (maxDiff > 1) return Math.max(8, 9 * heightFactor * paddingFactor);
|
|
1038
|
-
if (maxDiff > 0.5) return Math.max(9, 10 * heightFactor * paddingFactor);
|
|
1039
|
-
if (maxDiff > 0.1) return Math.max(11, 12 * heightFactor * paddingFactor);
|
|
1040
|
-
if (maxDiff > 0.01) return Math.max(12, 13 * heightFactor * paddingFactor);
|
|
1041
|
-
return Math.max(11, 12 * heightFactor * paddingFactor);
|
|
1042
|
-
}, [normalizedClusters, normalizedStandaloneMarkers, markerFocusZoom, calculatedHeight]);
|
|
1132
|
+
const adjustedZoom = properZoom ? properZoom - 0.5 : DEFAULT_VIEW_STATE.zoom;
|
|
1133
|
+
return Math.min(adjustedZoom, 15);
|
|
1134
|
+
}, [properZoom, zoomCoordinates.length, markerFocusZoom]);
|
|
1043
1135
|
const [uncontrolledViewState, setUncontrolledViewState] = React3__namespace.useState({
|
|
1044
1136
|
latitude: defaultViewState?.latitude ?? firstCoordinate.latitude,
|
|
1045
1137
|
longitude: defaultViewState?.longitude ?? firstCoordinate.longitude,
|
|
@@ -1365,6 +1457,7 @@ function GeoMap({
|
|
|
1365
1457
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1366
1458
|
"div",
|
|
1367
1459
|
{
|
|
1460
|
+
ref: containerRef,
|
|
1368
1461
|
className: cn(
|
|
1369
1462
|
"relative rounded-2xl border border-border bg-background",
|
|
1370
1463
|
// Remove overflow-hidden from outer container to allow panel to overflow
|