@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
package/dist/components/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { clsx } from 'clsx';
|
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import * as React3 from 'react';
|
|
5
|
-
import React3__default from 'react';
|
|
5
|
+
import React3__default, { useMemo } from 'react';
|
|
6
6
|
import { Marker, Map as Map$1, GeolocateControl, NavigationControl } from 'react-map-gl/maplibre';
|
|
7
7
|
|
|
8
8
|
// src/utils/cn.ts
|
|
@@ -637,6 +637,74 @@ function MapLibre({
|
|
|
637
637
|
}
|
|
638
638
|
);
|
|
639
639
|
}
|
|
640
|
+
var TILE_SIZE = 512;
|
|
641
|
+
function latToMercatorY(lat) {
|
|
642
|
+
const latRad = lat * Math.PI / 180;
|
|
643
|
+
const mercN = Math.log(Math.tan(Math.PI / 4 + latRad / 2));
|
|
644
|
+
return TILE_SIZE / (2 * Math.PI) * (Math.PI - mercN);
|
|
645
|
+
}
|
|
646
|
+
function lngToMercatorX(lng) {
|
|
647
|
+
return TILE_SIZE / (2 * Math.PI) * ((lng + 180) / 360 * 2 * Math.PI);
|
|
648
|
+
}
|
|
649
|
+
function computeDefaultZoom(options) {
|
|
650
|
+
const {
|
|
651
|
+
coordinates,
|
|
652
|
+
mapWidth,
|
|
653
|
+
mapHeight,
|
|
654
|
+
padding = 50,
|
|
655
|
+
maxZoom = 18,
|
|
656
|
+
minZoom = 1
|
|
657
|
+
} = options;
|
|
658
|
+
if (coordinates.length === 0) return null;
|
|
659
|
+
if (coordinates.length === 1) return maxZoom;
|
|
660
|
+
if (mapWidth <= 0 || mapHeight <= 0) return null;
|
|
661
|
+
let minLat = Infinity;
|
|
662
|
+
let maxLat = -Infinity;
|
|
663
|
+
let minLng = Infinity;
|
|
664
|
+
let maxLng = -Infinity;
|
|
665
|
+
for (const coord of coordinates) {
|
|
666
|
+
if (coord.lat < minLat) minLat = coord.lat;
|
|
667
|
+
if (coord.lat > maxLat) maxLat = coord.lat;
|
|
668
|
+
if (coord.lng < minLng) minLng = coord.lng;
|
|
669
|
+
if (coord.lng > maxLng) maxLng = coord.lng;
|
|
670
|
+
}
|
|
671
|
+
const pixelXMin = lngToMercatorX(minLng);
|
|
672
|
+
const pixelXMax = lngToMercatorX(maxLng);
|
|
673
|
+
const pixelYMin = latToMercatorY(maxLat);
|
|
674
|
+
const pixelYMax = latToMercatorY(minLat);
|
|
675
|
+
const dx = Math.abs(pixelXMax - pixelXMin);
|
|
676
|
+
const dy = Math.abs(pixelYMax - pixelYMin);
|
|
677
|
+
const availableWidth = mapWidth - padding * 2;
|
|
678
|
+
const availableHeight = mapHeight - padding * 2;
|
|
679
|
+
if (availableWidth <= 0 || availableHeight <= 0) return minZoom;
|
|
680
|
+
let zoom;
|
|
681
|
+
if (dx === 0 && dy === 0) {
|
|
682
|
+
return maxZoom;
|
|
683
|
+
} else if (dx === 0) {
|
|
684
|
+
zoom = Math.log2(availableHeight / dy);
|
|
685
|
+
} else if (dy === 0) {
|
|
686
|
+
zoom = Math.log2(availableWidth / dx);
|
|
687
|
+
} else {
|
|
688
|
+
const zoomX = Math.log2(availableWidth / dx);
|
|
689
|
+
const zoomY = Math.log2(availableHeight / dy);
|
|
690
|
+
zoom = Math.min(zoomX, zoomY);
|
|
691
|
+
}
|
|
692
|
+
return Math.max(minZoom, Math.min(maxZoom, Math.floor(zoom * 100) / 100));
|
|
693
|
+
}
|
|
694
|
+
function useDefaultZoom(options) {
|
|
695
|
+
const { coordinates, mapWidth, mapHeight, padding, maxZoom, minZoom } = options;
|
|
696
|
+
return useMemo(
|
|
697
|
+
() => computeDefaultZoom({
|
|
698
|
+
coordinates,
|
|
699
|
+
mapWidth,
|
|
700
|
+
mapHeight,
|
|
701
|
+
padding,
|
|
702
|
+
maxZoom,
|
|
703
|
+
minZoom
|
|
704
|
+
}),
|
|
705
|
+
[coordinates, mapWidth, mapHeight, padding, maxZoom, minZoom]
|
|
706
|
+
);
|
|
707
|
+
}
|
|
640
708
|
var PANEL_POSITION_CLASS = {
|
|
641
709
|
"top-left": "left-4 top-4",
|
|
642
710
|
"top-right": "right-4 top-4",
|
|
@@ -885,6 +953,13 @@ function GeoMap({
|
|
|
885
953
|
IconComponent = FallbackIcon,
|
|
886
954
|
ImgComponent = FallbackImg
|
|
887
955
|
}) {
|
|
956
|
+
const containerRef = React3.useRef(null);
|
|
957
|
+
const [containerDimensions, setContainerDimensions] = React3.useState({
|
|
958
|
+
width: 800,
|
|
959
|
+
// Default width
|
|
960
|
+
height: 520
|
|
961
|
+
// Default height
|
|
962
|
+
});
|
|
888
963
|
const [isMobile, setIsMobile] = React3.useState(false);
|
|
889
964
|
React3.useEffect(() => {
|
|
890
965
|
const checkMobile = () => {
|
|
@@ -900,6 +975,24 @@ function GeoMap({
|
|
|
900
975
|
}
|
|
901
976
|
return isMobile ? 420 : 520;
|
|
902
977
|
}, [mapSize, isMobile]);
|
|
978
|
+
React3.useEffect(() => {
|
|
979
|
+
if (!containerRef.current) return;
|
|
980
|
+
const updateDimensions = () => {
|
|
981
|
+
if (containerRef.current) {
|
|
982
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
983
|
+
setContainerDimensions({
|
|
984
|
+
width: rect.width || 800,
|
|
985
|
+
height: rect.height || calculatedHeight
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
};
|
|
989
|
+
updateDimensions();
|
|
990
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
991
|
+
const resizeObserver = new ResizeObserver(updateDimensions);
|
|
992
|
+
resizeObserver.observe(containerRef.current);
|
|
993
|
+
return () => resizeObserver.disconnect();
|
|
994
|
+
}
|
|
995
|
+
}, [calculatedHeight]);
|
|
903
996
|
const normalizedStandaloneMarkers = React3.useMemo(
|
|
904
997
|
() => markers.map((marker, index) => ({
|
|
905
998
|
...marker,
|
|
@@ -983,42 +1076,41 @@ function GeoMap({
|
|
|
983
1076
|
longitude: DEFAULT_VIEW_STATE.longitude
|
|
984
1077
|
};
|
|
985
1078
|
}, [normalizedClusters, normalizedStandaloneMarkers]);
|
|
986
|
-
const
|
|
987
|
-
|
|
988
|
-
return markerFocusZoom;
|
|
989
|
-
}
|
|
990
|
-
const allCoords = [];
|
|
1079
|
+
const zoomCoordinates = React3.useMemo(() => {
|
|
1080
|
+
const coords = [];
|
|
991
1081
|
normalizedStandaloneMarkers.forEach((marker) => {
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1082
|
+
coords.push({
|
|
1083
|
+
lat: marker.latitude,
|
|
1084
|
+
lng: marker.longitude
|
|
995
1085
|
});
|
|
996
1086
|
});
|
|
997
1087
|
normalizedClusters.forEach((cluster) => {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1088
|
+
coords.push({
|
|
1089
|
+
lat: cluster.latitude,
|
|
1090
|
+
lng: cluster.longitude
|
|
1001
1091
|
});
|
|
1002
1092
|
});
|
|
1003
|
-
|
|
1093
|
+
return coords;
|
|
1094
|
+
}, [normalizedStandaloneMarkers, normalizedClusters]);
|
|
1095
|
+
const properZoom = useDefaultZoom({
|
|
1096
|
+
coordinates: zoomCoordinates,
|
|
1097
|
+
mapWidth: containerDimensions.width,
|
|
1098
|
+
mapHeight: containerDimensions.height,
|
|
1099
|
+
padding: 80,
|
|
1100
|
+
// Increased padding for better framing
|
|
1101
|
+
maxZoom: 18,
|
|
1102
|
+
minZoom: 1
|
|
1103
|
+
});
|
|
1104
|
+
const calculatedZoom = React3.useMemo(() => {
|
|
1105
|
+
if (zoomCoordinates.length === 1) {
|
|
1106
|
+
return markerFocusZoom;
|
|
1107
|
+
}
|
|
1108
|
+
if (zoomCoordinates.length === 0) {
|
|
1004
1109
|
return DEFAULT_VIEW_STATE.zoom;
|
|
1005
1110
|
}
|
|
1006
|
-
const
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
const lngDiff = Math.max(...lngs) - Math.min(...lngs);
|
|
1010
|
-
const maxDiff = Math.max(latDiff, lngDiff);
|
|
1011
|
-
const heightFactor = calculatedHeight / 520;
|
|
1012
|
-
const paddingFactor = 0.85;
|
|
1013
|
-
if (maxDiff > 10) return Math.max(2, 3 * heightFactor * paddingFactor);
|
|
1014
|
-
if (maxDiff > 5) return Math.max(4, 5 * heightFactor * paddingFactor);
|
|
1015
|
-
if (maxDiff > 2) return Math.max(6, 7 * heightFactor * paddingFactor);
|
|
1016
|
-
if (maxDiff > 1) return Math.max(8, 9 * heightFactor * paddingFactor);
|
|
1017
|
-
if (maxDiff > 0.5) return Math.max(9, 10 * heightFactor * paddingFactor);
|
|
1018
|
-
if (maxDiff > 0.1) return Math.max(11, 12 * heightFactor * paddingFactor);
|
|
1019
|
-
if (maxDiff > 0.01) return Math.max(12, 13 * heightFactor * paddingFactor);
|
|
1020
|
-
return Math.max(11, 12 * heightFactor * paddingFactor);
|
|
1021
|
-
}, [normalizedClusters, normalizedStandaloneMarkers, markerFocusZoom, calculatedHeight]);
|
|
1111
|
+
const adjustedZoom = properZoom ? properZoom - 0.5 : DEFAULT_VIEW_STATE.zoom;
|
|
1112
|
+
return Math.min(adjustedZoom, 15);
|
|
1113
|
+
}, [properZoom, zoomCoordinates.length, markerFocusZoom]);
|
|
1022
1114
|
const [uncontrolledViewState, setUncontrolledViewState] = React3.useState({
|
|
1023
1115
|
latitude: defaultViewState?.latitude ?? firstCoordinate.latitude,
|
|
1024
1116
|
longitude: defaultViewState?.longitude ?? firstCoordinate.longitude,
|
|
@@ -1344,6 +1436,7 @@ function GeoMap({
|
|
|
1344
1436
|
return /* @__PURE__ */ jsxs(
|
|
1345
1437
|
"div",
|
|
1346
1438
|
{
|
|
1439
|
+
ref: containerRef,
|
|
1347
1440
|
className: cn(
|
|
1348
1441
|
"relative rounded-2xl border border-border bg-background",
|
|
1349
1442
|
// Remove overflow-hidden from outer container to allow panel to overflow
|