@page-speed/maps 0.1.8 → 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.
@@ -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",
@@ -902,9 +970,50 @@ function GeoMap({
902
970
  clearSelectionOnMapClick = true,
903
971
  mapChildren,
904
972
  optixFlowConfig,
973
+ mapSize,
905
974
  IconComponent = FallbackIcon,
906
975
  ImgComponent = FallbackImg
907
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
+ });
984
+ const [isMobile, setIsMobile] = React3__namespace.useState(false);
985
+ React3__namespace.useEffect(() => {
986
+ const checkMobile = () => {
987
+ setIsMobile(window.innerWidth < 768);
988
+ };
989
+ checkMobile();
990
+ window.addEventListener("resize", checkMobile);
991
+ return () => window.removeEventListener("resize", checkMobile);
992
+ }, []);
993
+ const calculatedHeight = React3__namespace.useMemo(() => {
994
+ if (mapSize) {
995
+ return isMobile ? mapSize.mobile : mapSize.desktop;
996
+ }
997
+ return isMobile ? 420 : 520;
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]);
908
1017
  const normalizedStandaloneMarkers = React3__namespace.useMemo(
909
1018
  () => markers.map((marker, index) => ({
910
1019
  ...marker,
@@ -988,39 +1097,41 @@ function GeoMap({
988
1097
  longitude: DEFAULT_VIEW_STATE.longitude
989
1098
  };
990
1099
  }, [normalizedClusters, normalizedStandaloneMarkers]);
991
- const calculatedZoom = React3__namespace.useMemo(() => {
992
- if (normalizedStandaloneMarkers.length + normalizedClusters.length <= 1) {
993
- return markerFocusZoom;
994
- }
995
- const allCoords = [];
1100
+ const zoomCoordinates = React3__namespace.useMemo(() => {
1101
+ const coords = [];
996
1102
  normalizedStandaloneMarkers.forEach((marker) => {
997
- allCoords.push({
998
- latitude: marker.latitude,
999
- longitude: marker.longitude
1103
+ coords.push({
1104
+ lat: marker.latitude,
1105
+ lng: marker.longitude
1000
1106
  });
1001
1107
  });
1002
1108
  normalizedClusters.forEach((cluster) => {
1003
- allCoords.push({
1004
- latitude: cluster.latitude,
1005
- longitude: cluster.longitude
1109
+ coords.push({
1110
+ lat: cluster.latitude,
1111
+ lng: cluster.longitude
1006
1112
  });
1007
1113
  });
1008
- if (allCoords.length === 0) {
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) {
1009
1130
  return DEFAULT_VIEW_STATE.zoom;
1010
1131
  }
1011
- const lats = allCoords.map((c) => c.latitude);
1012
- const lngs = allCoords.map((c) => c.longitude);
1013
- const latDiff = Math.max(...lats) - Math.min(...lats);
1014
- const lngDiff = Math.max(...lngs) - Math.min(...lngs);
1015
- const maxDiff = Math.max(latDiff, lngDiff);
1016
- if (maxDiff > 10) return 3;
1017
- if (maxDiff > 5) return 5;
1018
- if (maxDiff > 2) return 7;
1019
- if (maxDiff > 1) return 9;
1020
- if (maxDiff > 0.5) return 10;
1021
- if (maxDiff > 0.1) return 12;
1022
- return 13;
1023
- }, [normalizedClusters, normalizedStandaloneMarkers, markerFocusZoom]);
1132
+ const adjustedZoom = properZoom ? properZoom - 0.5 : DEFAULT_VIEW_STATE.zoom;
1133
+ return Math.min(adjustedZoom, 15);
1134
+ }, [properZoom, zoomCoordinates.length, markerFocusZoom]);
1024
1135
  const [uncontrolledViewState, setUncontrolledViewState] = React3__namespace.useState({
1025
1136
  latitude: defaultViewState?.latitude ?? firstCoordinate.latitude,
1026
1137
  longitude: defaultViewState?.longitude ?? firstCoordinate.longitude,
@@ -1346,25 +1457,35 @@ function GeoMap({
1346
1457
  return /* @__PURE__ */ jsxRuntime.jsxs(
1347
1458
  "div",
1348
1459
  {
1460
+ ref: containerRef,
1349
1461
  className: cn(
1350
- "relative overflow-hidden rounded-2xl border border-border bg-background",
1462
+ "relative rounded-2xl border border-border bg-background",
1463
+ // Remove overflow-hidden from outer container to allow panel to overflow
1351
1464
  className
1352
1465
  ),
1466
+ style: {
1467
+ // If className includes height settings, they'll override via CSS specificity
1468
+ height: className?.includes("h-[") || className?.includes("min-h-[") || className?.includes("max-h-[") ? void 0 : `${calculatedHeight}px`,
1469
+ // Explicitly allow overflow for marker panels
1470
+ overflow: "visible"
1471
+ },
1353
1472
  children: [
1354
1473
  /* @__PURE__ */ jsxRuntime.jsx(
1355
1474
  "div",
1356
1475
  {
1357
1476
  className: cn(
1358
- "w-full",
1359
- // Default height, can be overridden by mapWrapperClassName
1360
- mapWrapperClassName || "h-[520px]"
1477
+ "w-full rounded-2xl",
1478
+ // Only apply default height class if mapWrapperClassName not provided
1479
+ !mapWrapperClassName && `h-[${calculatedHeight}px]`,
1480
+ mapWrapperClassName
1361
1481
  ),
1362
1482
  style: {
1363
- // CRITICAL: Always use explicit height to prevent MapLibre canvas expansion
1364
- height: mapWrapperClassName ? void 0 : "520px",
1483
+ // If mapWrapperClassName includes height, let it handle the height
1484
+ height: mapWrapperClassName?.includes("h-[") || mapWrapperClassName?.includes("min-h-[") || mapWrapperClassName?.includes("max-h-[") ? void 0 : `${calculatedHeight}px`,
1365
1485
  maxHeight: "100vh",
1366
1486
  // Prevent excessive growth
1367
1487
  position: "relative",
1488
+ // Keep overflow hidden only on the map wrapper to contain the canvas
1368
1489
  overflow: "hidden"
1369
1490
  },
1370
1491
  children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -1390,6 +1511,10 @@ function GeoMap({
1390
1511
  geolocateControlPosition,
1391
1512
  flyToOptions,
1392
1513
  className: cn("h-full w-full", mapClassName),
1514
+ style: {
1515
+ // Pass the calculated height to MapLibre for better zoom calculations
1516
+ height: mapClassName?.includes("h-[") || mapClassName?.includes("min-h-[") || mapClassName?.includes("max-h-[") ? void 0 : `${calculatedHeight}px`
1517
+ },
1393
1518
  children: mapChildren
1394
1519
  }
1395
1520
  )
@@ -1399,9 +1524,13 @@ function GeoMap({
1399
1524
  "div",
1400
1525
  {
1401
1526
  className: cn(
1402
- "pointer-events-none absolute z-20",
1527
+ "pointer-events-none absolute z-30",
1403
1528
  PANEL_POSITION_CLASS[panelPosition]
1404
1529
  ),
1530
+ style: {
1531
+ // Ensure panel can overflow and has higher z-index
1532
+ zIndex: 30
1533
+ },
1405
1534
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto", children: renderMarkerPanel() })
1406
1535
  }
1407
1536
  ) : null