@page-speed/maps 0.1.9 → 0.2.1
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 +166 -31
- package/dist/components/geo-map.cjs.map +1 -1
- package/dist/components/geo-map.js +167 -32
- package/dist/components/geo-map.js.map +1 -1
- package/dist/components/index.cjs +166 -31
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +167 -32
- package/dist/components/index.js.map +1 -1
- package/dist/index.cjs +98 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +98 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -749,6 +749,19 @@ var PANEL_POSITION_CLASS = {
|
|
|
749
749
|
"bottom-left": "bottom-4 left-4",
|
|
750
750
|
"bottom-right": "bottom-4 right-4"
|
|
751
751
|
};
|
|
752
|
+
function getOptimalPanelPosition(markerLat, markerLng, mapCenter) {
|
|
753
|
+
const isNorth = markerLat >= mapCenter.latitude;
|
|
754
|
+
const isEast = markerLng >= mapCenter.longitude;
|
|
755
|
+
if (isNorth && isEast) {
|
|
756
|
+
return "bottom-left";
|
|
757
|
+
} else if (isNorth && !isEast) {
|
|
758
|
+
return "bottom-right";
|
|
759
|
+
} else if (!isNorth && isEast) {
|
|
760
|
+
return "top-left";
|
|
761
|
+
} else {
|
|
762
|
+
return "top-right";
|
|
763
|
+
}
|
|
764
|
+
}
|
|
752
765
|
var DEFAULT_VIEW_STATE = {
|
|
753
766
|
latitude: 39.5,
|
|
754
767
|
longitude: -98.35,
|
|
@@ -991,6 +1004,13 @@ function GeoMap({
|
|
|
991
1004
|
IconComponent = FallbackIcon,
|
|
992
1005
|
ImgComponent = FallbackImg
|
|
993
1006
|
}) {
|
|
1007
|
+
const containerRef = React3.useRef(null);
|
|
1008
|
+
const [containerDimensions, setContainerDimensions] = React3.useState({
|
|
1009
|
+
width: 800,
|
|
1010
|
+
// Default width
|
|
1011
|
+
height: 520
|
|
1012
|
+
// Default height
|
|
1013
|
+
});
|
|
994
1014
|
const [isMobile, setIsMobile] = React3.useState(false);
|
|
995
1015
|
React3.useEffect(() => {
|
|
996
1016
|
const checkMobile = () => {
|
|
@@ -1006,6 +1026,24 @@ function GeoMap({
|
|
|
1006
1026
|
}
|
|
1007
1027
|
return isMobile ? 420 : 520;
|
|
1008
1028
|
}, [mapSize, isMobile]);
|
|
1029
|
+
React3.useEffect(() => {
|
|
1030
|
+
if (!containerRef.current) return;
|
|
1031
|
+
const updateDimensions = () => {
|
|
1032
|
+
if (containerRef.current) {
|
|
1033
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
1034
|
+
setContainerDimensions({
|
|
1035
|
+
width: rect.width || 800,
|
|
1036
|
+
height: rect.height || calculatedHeight
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
};
|
|
1040
|
+
updateDimensions();
|
|
1041
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
1042
|
+
const resizeObserver = new ResizeObserver(updateDimensions);
|
|
1043
|
+
resizeObserver.observe(containerRef.current);
|
|
1044
|
+
return () => resizeObserver.disconnect();
|
|
1045
|
+
}
|
|
1046
|
+
}, [calculatedHeight]);
|
|
1009
1047
|
const normalizedStandaloneMarkers = React3.useMemo(
|
|
1010
1048
|
() => markers.map((marker, index) => ({
|
|
1011
1049
|
...marker,
|
|
@@ -1089,47 +1127,49 @@ function GeoMap({
|
|
|
1089
1127
|
longitude: DEFAULT_VIEW_STATE.longitude
|
|
1090
1128
|
};
|
|
1091
1129
|
}, [normalizedClusters, normalizedStandaloneMarkers]);
|
|
1092
|
-
const
|
|
1093
|
-
|
|
1094
|
-
return markerFocusZoom;
|
|
1095
|
-
}
|
|
1096
|
-
const allCoords = [];
|
|
1130
|
+
const zoomCoordinates = React3.useMemo(() => {
|
|
1131
|
+
const coords = [];
|
|
1097
1132
|
normalizedStandaloneMarkers.forEach((marker) => {
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1133
|
+
coords.push({
|
|
1134
|
+
lat: marker.latitude,
|
|
1135
|
+
lng: marker.longitude
|
|
1101
1136
|
});
|
|
1102
1137
|
});
|
|
1103
1138
|
normalizedClusters.forEach((cluster) => {
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1139
|
+
coords.push({
|
|
1140
|
+
lat: cluster.latitude,
|
|
1141
|
+
lng: cluster.longitude
|
|
1107
1142
|
});
|
|
1108
1143
|
});
|
|
1109
|
-
|
|
1144
|
+
return coords;
|
|
1145
|
+
}, [normalizedStandaloneMarkers, normalizedClusters]);
|
|
1146
|
+
const properZoom = useDefaultZoom({
|
|
1147
|
+
coordinates: zoomCoordinates,
|
|
1148
|
+
mapWidth: containerDimensions.width,
|
|
1149
|
+
mapHeight: containerDimensions.height,
|
|
1150
|
+
padding: 80,
|
|
1151
|
+
// Increased padding for better framing
|
|
1152
|
+
maxZoom: 18,
|
|
1153
|
+
minZoom: 1
|
|
1154
|
+
});
|
|
1155
|
+
const calculatedZoom = React3.useMemo(() => {
|
|
1156
|
+
if (zoomCoordinates.length === 1) {
|
|
1157
|
+
return markerFocusZoom;
|
|
1158
|
+
}
|
|
1159
|
+
if (zoomCoordinates.length === 0) {
|
|
1110
1160
|
return DEFAULT_VIEW_STATE.zoom;
|
|
1111
1161
|
}
|
|
1112
|
-
const
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
const lngDiff = Math.max(...lngs) - Math.min(...lngs);
|
|
1116
|
-
const maxDiff = Math.max(latDiff, lngDiff);
|
|
1117
|
-
const heightFactor = calculatedHeight / 520;
|
|
1118
|
-
const paddingFactor = 0.85;
|
|
1119
|
-
if (maxDiff > 10) return Math.max(2, 3 * heightFactor * paddingFactor);
|
|
1120
|
-
if (maxDiff > 5) return Math.max(4, 5 * heightFactor * paddingFactor);
|
|
1121
|
-
if (maxDiff > 2) return Math.max(6, 7 * heightFactor * paddingFactor);
|
|
1122
|
-
if (maxDiff > 1) return Math.max(8, 9 * heightFactor * paddingFactor);
|
|
1123
|
-
if (maxDiff > 0.5) return Math.max(9, 10 * heightFactor * paddingFactor);
|
|
1124
|
-
if (maxDiff > 0.1) return Math.max(11, 12 * heightFactor * paddingFactor);
|
|
1125
|
-
if (maxDiff > 0.01) return Math.max(12, 13 * heightFactor * paddingFactor);
|
|
1126
|
-
return Math.max(11, 12 * heightFactor * paddingFactor);
|
|
1127
|
-
}, [normalizedClusters, normalizedStandaloneMarkers, markerFocusZoom, calculatedHeight]);
|
|
1162
|
+
const adjustedZoom = properZoom ? properZoom - 0.5 : DEFAULT_VIEW_STATE.zoom;
|
|
1163
|
+
return Math.min(adjustedZoom, 15);
|
|
1164
|
+
}, [properZoom, zoomCoordinates.length, markerFocusZoom]);
|
|
1128
1165
|
const [uncontrolledViewState, setUncontrolledViewState] = React3.useState({
|
|
1129
1166
|
latitude: defaultViewState?.latitude ?? firstCoordinate.latitude,
|
|
1130
1167
|
longitude: defaultViewState?.longitude ?? firstCoordinate.longitude,
|
|
1131
1168
|
zoom: defaultViewState?.zoom ?? calculatedZoom
|
|
1132
1169
|
});
|
|
1170
|
+
const [dynamicPanelPosition, setDynamicPanelPosition] = React3.useState(
|
|
1171
|
+
panelPosition
|
|
1172
|
+
);
|
|
1133
1173
|
React3.useEffect(() => {
|
|
1134
1174
|
if (!viewState && !defaultViewState) {
|
|
1135
1175
|
setUncontrolledViewState({
|
|
@@ -1209,6 +1249,19 @@ function GeoMap({
|
|
|
1209
1249
|
markerId: marker.id,
|
|
1210
1250
|
clusterId: marker.clusterId
|
|
1211
1251
|
});
|
|
1252
|
+
const currentCenter = resolvedViewState || {
|
|
1253
|
+
latitude: firstCoordinate.latitude,
|
|
1254
|
+
longitude: firstCoordinate.longitude
|
|
1255
|
+
};
|
|
1256
|
+
const optimalPosition = getOptimalPanelPosition(
|
|
1257
|
+
marker.latitude,
|
|
1258
|
+
marker.longitude,
|
|
1259
|
+
{
|
|
1260
|
+
latitude: currentCenter.latitude ?? firstCoordinate.latitude,
|
|
1261
|
+
longitude: currentCenter.longitude ?? firstCoordinate.longitude
|
|
1262
|
+
}
|
|
1263
|
+
);
|
|
1264
|
+
setDynamicPanelPosition(optimalPosition);
|
|
1212
1265
|
applyViewState({
|
|
1213
1266
|
latitude: marker.latitude,
|
|
1214
1267
|
longitude: marker.longitude,
|
|
@@ -1216,7 +1269,7 @@ function GeoMap({
|
|
|
1216
1269
|
});
|
|
1217
1270
|
emitSelectionChange({ type: "marker", marker });
|
|
1218
1271
|
},
|
|
1219
|
-
[applyViewState, emitSelectionChange, markerFocusZoom]
|
|
1272
|
+
[applyViewState, emitSelectionChange, markerFocusZoom, resolvedViewState, firstCoordinate]
|
|
1220
1273
|
);
|
|
1221
1274
|
const selectCluster = React3.useCallback(
|
|
1222
1275
|
(cluster) => {
|
|
@@ -1224,6 +1277,19 @@ function GeoMap({
|
|
|
1224
1277
|
type: "cluster",
|
|
1225
1278
|
clusterId: cluster.id
|
|
1226
1279
|
});
|
|
1280
|
+
const currentCenter = resolvedViewState || {
|
|
1281
|
+
latitude: firstCoordinate.latitude,
|
|
1282
|
+
longitude: firstCoordinate.longitude
|
|
1283
|
+
};
|
|
1284
|
+
const optimalPosition = getOptimalPanelPosition(
|
|
1285
|
+
cluster.latitude,
|
|
1286
|
+
cluster.longitude,
|
|
1287
|
+
{
|
|
1288
|
+
latitude: currentCenter.latitude ?? firstCoordinate.latitude,
|
|
1289
|
+
longitude: currentCenter.longitude ?? firstCoordinate.longitude
|
|
1290
|
+
}
|
|
1291
|
+
);
|
|
1292
|
+
setDynamicPanelPosition(optimalPosition);
|
|
1227
1293
|
applyViewState({
|
|
1228
1294
|
latitude: cluster.latitude,
|
|
1229
1295
|
longitude: cluster.longitude,
|
|
@@ -1231,7 +1297,7 @@ function GeoMap({
|
|
|
1231
1297
|
});
|
|
1232
1298
|
emitSelectionChange({ type: "cluster", cluster });
|
|
1233
1299
|
},
|
|
1234
|
-
[applyViewState, clusterFocusZoom, emitSelectionChange]
|
|
1300
|
+
[applyViewState, clusterFocusZoom, emitSelectionChange, resolvedViewState, firstCoordinate]
|
|
1235
1301
|
);
|
|
1236
1302
|
const clearSelection = React3.useCallback(() => {
|
|
1237
1303
|
setSelection({ type: "none" });
|
|
@@ -1450,6 +1516,7 @@ function GeoMap({
|
|
|
1450
1516
|
return /* @__PURE__ */ jsxs(
|
|
1451
1517
|
"div",
|
|
1452
1518
|
{
|
|
1519
|
+
ref: containerRef,
|
|
1453
1520
|
className: cn(
|
|
1454
1521
|
"relative rounded-2xl border border-border bg-background",
|
|
1455
1522
|
// Remove overflow-hidden from outer container to allow panel to overflow
|
|
@@ -1517,7 +1584,7 @@ function GeoMap({
|
|
|
1517
1584
|
{
|
|
1518
1585
|
className: cn(
|
|
1519
1586
|
"pointer-events-none absolute z-30",
|
|
1520
|
-
PANEL_POSITION_CLASS[
|
|
1587
|
+
PANEL_POSITION_CLASS[dynamicPanelPosition]
|
|
1521
1588
|
),
|
|
1522
1589
|
style: {
|
|
1523
1590
|
// Ensure panel can overflow and has higher z-index
|