@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.cjs
CHANGED
|
@@ -770,6 +770,19 @@ var PANEL_POSITION_CLASS = {
|
|
|
770
770
|
"bottom-left": "bottom-4 left-4",
|
|
771
771
|
"bottom-right": "bottom-4 right-4"
|
|
772
772
|
};
|
|
773
|
+
function getOptimalPanelPosition(markerLat, markerLng, mapCenter) {
|
|
774
|
+
const isNorth = markerLat >= mapCenter.latitude;
|
|
775
|
+
const isEast = markerLng >= mapCenter.longitude;
|
|
776
|
+
if (isNorth && isEast) {
|
|
777
|
+
return "bottom-left";
|
|
778
|
+
} else if (isNorth && !isEast) {
|
|
779
|
+
return "bottom-right";
|
|
780
|
+
} else if (!isNorth && isEast) {
|
|
781
|
+
return "top-left";
|
|
782
|
+
} else {
|
|
783
|
+
return "top-right";
|
|
784
|
+
}
|
|
785
|
+
}
|
|
773
786
|
var DEFAULT_VIEW_STATE = {
|
|
774
787
|
latitude: 39.5,
|
|
775
788
|
longitude: -98.35,
|
|
@@ -1012,6 +1025,13 @@ function GeoMap({
|
|
|
1012
1025
|
IconComponent = FallbackIcon,
|
|
1013
1026
|
ImgComponent = FallbackImg
|
|
1014
1027
|
}) {
|
|
1028
|
+
const containerRef = React3__namespace.useRef(null);
|
|
1029
|
+
const [containerDimensions, setContainerDimensions] = React3__namespace.useState({
|
|
1030
|
+
width: 800,
|
|
1031
|
+
// Default width
|
|
1032
|
+
height: 520
|
|
1033
|
+
// Default height
|
|
1034
|
+
});
|
|
1015
1035
|
const [isMobile, setIsMobile] = React3__namespace.useState(false);
|
|
1016
1036
|
React3__namespace.useEffect(() => {
|
|
1017
1037
|
const checkMobile = () => {
|
|
@@ -1027,6 +1047,24 @@ function GeoMap({
|
|
|
1027
1047
|
}
|
|
1028
1048
|
return isMobile ? 420 : 520;
|
|
1029
1049
|
}, [mapSize, isMobile]);
|
|
1050
|
+
React3__namespace.useEffect(() => {
|
|
1051
|
+
if (!containerRef.current) return;
|
|
1052
|
+
const updateDimensions = () => {
|
|
1053
|
+
if (containerRef.current) {
|
|
1054
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
1055
|
+
setContainerDimensions({
|
|
1056
|
+
width: rect.width || 800,
|
|
1057
|
+
height: rect.height || calculatedHeight
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
};
|
|
1061
|
+
updateDimensions();
|
|
1062
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
1063
|
+
const resizeObserver = new ResizeObserver(updateDimensions);
|
|
1064
|
+
resizeObserver.observe(containerRef.current);
|
|
1065
|
+
return () => resizeObserver.disconnect();
|
|
1066
|
+
}
|
|
1067
|
+
}, [calculatedHeight]);
|
|
1030
1068
|
const normalizedStandaloneMarkers = React3__namespace.useMemo(
|
|
1031
1069
|
() => markers.map((marker, index) => ({
|
|
1032
1070
|
...marker,
|
|
@@ -1110,47 +1148,49 @@ function GeoMap({
|
|
|
1110
1148
|
longitude: DEFAULT_VIEW_STATE.longitude
|
|
1111
1149
|
};
|
|
1112
1150
|
}, [normalizedClusters, normalizedStandaloneMarkers]);
|
|
1113
|
-
const
|
|
1114
|
-
|
|
1115
|
-
return markerFocusZoom;
|
|
1116
|
-
}
|
|
1117
|
-
const allCoords = [];
|
|
1151
|
+
const zoomCoordinates = React3__namespace.useMemo(() => {
|
|
1152
|
+
const coords = [];
|
|
1118
1153
|
normalizedStandaloneMarkers.forEach((marker) => {
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1154
|
+
coords.push({
|
|
1155
|
+
lat: marker.latitude,
|
|
1156
|
+
lng: marker.longitude
|
|
1122
1157
|
});
|
|
1123
1158
|
});
|
|
1124
1159
|
normalizedClusters.forEach((cluster) => {
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1160
|
+
coords.push({
|
|
1161
|
+
lat: cluster.latitude,
|
|
1162
|
+
lng: cluster.longitude
|
|
1128
1163
|
});
|
|
1129
1164
|
});
|
|
1130
|
-
|
|
1165
|
+
return coords;
|
|
1166
|
+
}, [normalizedStandaloneMarkers, normalizedClusters]);
|
|
1167
|
+
const properZoom = useDefaultZoom({
|
|
1168
|
+
coordinates: zoomCoordinates,
|
|
1169
|
+
mapWidth: containerDimensions.width,
|
|
1170
|
+
mapHeight: containerDimensions.height,
|
|
1171
|
+
padding: 80,
|
|
1172
|
+
// Increased padding for better framing
|
|
1173
|
+
maxZoom: 18,
|
|
1174
|
+
minZoom: 1
|
|
1175
|
+
});
|
|
1176
|
+
const calculatedZoom = React3__namespace.useMemo(() => {
|
|
1177
|
+
if (zoomCoordinates.length === 1) {
|
|
1178
|
+
return markerFocusZoom;
|
|
1179
|
+
}
|
|
1180
|
+
if (zoomCoordinates.length === 0) {
|
|
1131
1181
|
return DEFAULT_VIEW_STATE.zoom;
|
|
1132
1182
|
}
|
|
1133
|
-
const
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
const lngDiff = Math.max(...lngs) - Math.min(...lngs);
|
|
1137
|
-
const maxDiff = Math.max(latDiff, lngDiff);
|
|
1138
|
-
const heightFactor = calculatedHeight / 520;
|
|
1139
|
-
const paddingFactor = 0.85;
|
|
1140
|
-
if (maxDiff > 10) return Math.max(2, 3 * heightFactor * paddingFactor);
|
|
1141
|
-
if (maxDiff > 5) return Math.max(4, 5 * heightFactor * paddingFactor);
|
|
1142
|
-
if (maxDiff > 2) return Math.max(6, 7 * heightFactor * paddingFactor);
|
|
1143
|
-
if (maxDiff > 1) return Math.max(8, 9 * heightFactor * paddingFactor);
|
|
1144
|
-
if (maxDiff > 0.5) return Math.max(9, 10 * heightFactor * paddingFactor);
|
|
1145
|
-
if (maxDiff > 0.1) return Math.max(11, 12 * heightFactor * paddingFactor);
|
|
1146
|
-
if (maxDiff > 0.01) return Math.max(12, 13 * heightFactor * paddingFactor);
|
|
1147
|
-
return Math.max(11, 12 * heightFactor * paddingFactor);
|
|
1148
|
-
}, [normalizedClusters, normalizedStandaloneMarkers, markerFocusZoom, calculatedHeight]);
|
|
1183
|
+
const adjustedZoom = properZoom ? properZoom - 0.5 : DEFAULT_VIEW_STATE.zoom;
|
|
1184
|
+
return Math.min(adjustedZoom, 15);
|
|
1185
|
+
}, [properZoom, zoomCoordinates.length, markerFocusZoom]);
|
|
1149
1186
|
const [uncontrolledViewState, setUncontrolledViewState] = React3__namespace.useState({
|
|
1150
1187
|
latitude: defaultViewState?.latitude ?? firstCoordinate.latitude,
|
|
1151
1188
|
longitude: defaultViewState?.longitude ?? firstCoordinate.longitude,
|
|
1152
1189
|
zoom: defaultViewState?.zoom ?? calculatedZoom
|
|
1153
1190
|
});
|
|
1191
|
+
const [dynamicPanelPosition, setDynamicPanelPosition] = React3__namespace.useState(
|
|
1192
|
+
panelPosition
|
|
1193
|
+
);
|
|
1154
1194
|
React3__namespace.useEffect(() => {
|
|
1155
1195
|
if (!viewState && !defaultViewState) {
|
|
1156
1196
|
setUncontrolledViewState({
|
|
@@ -1230,6 +1270,19 @@ function GeoMap({
|
|
|
1230
1270
|
markerId: marker.id,
|
|
1231
1271
|
clusterId: marker.clusterId
|
|
1232
1272
|
});
|
|
1273
|
+
const currentCenter = resolvedViewState || {
|
|
1274
|
+
latitude: firstCoordinate.latitude,
|
|
1275
|
+
longitude: firstCoordinate.longitude
|
|
1276
|
+
};
|
|
1277
|
+
const optimalPosition = getOptimalPanelPosition(
|
|
1278
|
+
marker.latitude,
|
|
1279
|
+
marker.longitude,
|
|
1280
|
+
{
|
|
1281
|
+
latitude: currentCenter.latitude ?? firstCoordinate.latitude,
|
|
1282
|
+
longitude: currentCenter.longitude ?? firstCoordinate.longitude
|
|
1283
|
+
}
|
|
1284
|
+
);
|
|
1285
|
+
setDynamicPanelPosition(optimalPosition);
|
|
1233
1286
|
applyViewState({
|
|
1234
1287
|
latitude: marker.latitude,
|
|
1235
1288
|
longitude: marker.longitude,
|
|
@@ -1237,7 +1290,7 @@ function GeoMap({
|
|
|
1237
1290
|
});
|
|
1238
1291
|
emitSelectionChange({ type: "marker", marker });
|
|
1239
1292
|
},
|
|
1240
|
-
[applyViewState, emitSelectionChange, markerFocusZoom]
|
|
1293
|
+
[applyViewState, emitSelectionChange, markerFocusZoom, resolvedViewState, firstCoordinate]
|
|
1241
1294
|
);
|
|
1242
1295
|
const selectCluster = React3__namespace.useCallback(
|
|
1243
1296
|
(cluster) => {
|
|
@@ -1245,6 +1298,19 @@ function GeoMap({
|
|
|
1245
1298
|
type: "cluster",
|
|
1246
1299
|
clusterId: cluster.id
|
|
1247
1300
|
});
|
|
1301
|
+
const currentCenter = resolvedViewState || {
|
|
1302
|
+
latitude: firstCoordinate.latitude,
|
|
1303
|
+
longitude: firstCoordinate.longitude
|
|
1304
|
+
};
|
|
1305
|
+
const optimalPosition = getOptimalPanelPosition(
|
|
1306
|
+
cluster.latitude,
|
|
1307
|
+
cluster.longitude,
|
|
1308
|
+
{
|
|
1309
|
+
latitude: currentCenter.latitude ?? firstCoordinate.latitude,
|
|
1310
|
+
longitude: currentCenter.longitude ?? firstCoordinate.longitude
|
|
1311
|
+
}
|
|
1312
|
+
);
|
|
1313
|
+
setDynamicPanelPosition(optimalPosition);
|
|
1248
1314
|
applyViewState({
|
|
1249
1315
|
latitude: cluster.latitude,
|
|
1250
1316
|
longitude: cluster.longitude,
|
|
@@ -1252,7 +1318,7 @@ function GeoMap({
|
|
|
1252
1318
|
});
|
|
1253
1319
|
emitSelectionChange({ type: "cluster", cluster });
|
|
1254
1320
|
},
|
|
1255
|
-
[applyViewState, clusterFocusZoom, emitSelectionChange]
|
|
1321
|
+
[applyViewState, clusterFocusZoom, emitSelectionChange, resolvedViewState, firstCoordinate]
|
|
1256
1322
|
);
|
|
1257
1323
|
const clearSelection = React3__namespace.useCallback(() => {
|
|
1258
1324
|
setSelection({ type: "none" });
|
|
@@ -1471,6 +1537,7 @@ function GeoMap({
|
|
|
1471
1537
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1472
1538
|
"div",
|
|
1473
1539
|
{
|
|
1540
|
+
ref: containerRef,
|
|
1474
1541
|
className: cn(
|
|
1475
1542
|
"relative rounded-2xl border border-border bg-background",
|
|
1476
1543
|
// Remove overflow-hidden from outer container to allow panel to overflow
|
|
@@ -1538,7 +1605,7 @@ function GeoMap({
|
|
|
1538
1605
|
{
|
|
1539
1606
|
className: cn(
|
|
1540
1607
|
"pointer-events-none absolute z-30",
|
|
1541
|
-
PANEL_POSITION_CLASS[
|
|
1608
|
+
PANEL_POSITION_CLASS[dynamicPanelPosition]
|
|
1542
1609
|
),
|
|
1543
1610
|
style: {
|
|
1544
1611
|
// Ensure panel can overflow and has higher z-index
|