@revivejs/react-google-maps 17.0.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/LICENSE +21 -0
- package/README.md +271 -0
- package/dist/index.cjs +1834 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +457 -0
- package/dist/index.d.ts +457 -0
- package/dist/index.js +1797 -0
- package/dist/index.js.map +1 -0
- package/package.json +78 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1797 @@
|
|
|
1
|
+
// src/GoogleMapsProvider.tsx
|
|
2
|
+
import { useEffect, useMemo, useState } from "react";
|
|
3
|
+
|
|
4
|
+
// src/internal.tsx
|
|
5
|
+
import { createContext, useContext } from "react";
|
|
6
|
+
var GoogleMapsApiContext = createContext({
|
|
7
|
+
status: "idle",
|
|
8
|
+
error: null,
|
|
9
|
+
google: null,
|
|
10
|
+
options: null
|
|
11
|
+
});
|
|
12
|
+
var GoogleMapContext = createContext(null);
|
|
13
|
+
var MarkerClustererContext = createContext(null);
|
|
14
|
+
function useGoogleMapsApiContext() {
|
|
15
|
+
return useContext(GoogleMapsApiContext);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/loadGoogleMapsApi.ts
|
|
19
|
+
var DEFAULT_LIBRARIES = ["marker", "places", "geometry", "visualization"];
|
|
20
|
+
var loaderPromise = null;
|
|
21
|
+
var loadedOptionsKey = null;
|
|
22
|
+
function getDefaultGoogleMapsLibraries() {
|
|
23
|
+
return [...DEFAULT_LIBRARIES];
|
|
24
|
+
}
|
|
25
|
+
function loadGoogleMapsApi(options) {
|
|
26
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
27
|
+
return Promise.reject(new Error("@revivejs/react-google-maps can only load the Google Maps API in a browser environment."));
|
|
28
|
+
}
|
|
29
|
+
if (!options.apiKey) {
|
|
30
|
+
return Promise.reject(new Error("A Google Maps API key is required to load the Google Maps JavaScript API."));
|
|
31
|
+
}
|
|
32
|
+
if (window.google?.maps) {
|
|
33
|
+
return Promise.resolve(window.google);
|
|
34
|
+
}
|
|
35
|
+
const normalizedOptions = normalizeLoaderOptions(options);
|
|
36
|
+
const nextKey = JSON.stringify(normalizedOptions);
|
|
37
|
+
if (loaderPromise) {
|
|
38
|
+
if (loadedOptionsKey && loadedOptionsKey !== nextKey) {
|
|
39
|
+
console.warn(
|
|
40
|
+
"@revivejs/react-google-maps only loads the Google Maps JavaScript API once per page. Ignoring subsequent loader options and reusing the first loaded configuration."
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return loaderPromise;
|
|
44
|
+
}
|
|
45
|
+
loadedOptionsKey = nextKey;
|
|
46
|
+
loaderPromise = new Promise((resolve, reject) => {
|
|
47
|
+
const callbackName = "__revivejsReactGoogleMapsInit";
|
|
48
|
+
const existingScript = document.querySelector('script[data-revivejs-google-maps-loader="true"]');
|
|
49
|
+
if (existingScript) {
|
|
50
|
+
existingScript.addEventListener("load", () => {
|
|
51
|
+
if (window.google?.maps) {
|
|
52
|
+
resolve(window.google);
|
|
53
|
+
} else {
|
|
54
|
+
reject(new Error("Google Maps script loaded but the google.maps namespace is still unavailable."));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
existingScript.addEventListener("error", () => reject(new Error("The Google Maps JavaScript API script failed to load.")));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const params = new URLSearchParams();
|
|
61
|
+
params.set("key", normalizedOptions.apiKey);
|
|
62
|
+
params.set("v", normalizedOptions.version);
|
|
63
|
+
params.set("loading", "async");
|
|
64
|
+
params.set("callback", callbackName);
|
|
65
|
+
if (normalizedOptions.language) {
|
|
66
|
+
params.set("language", normalizedOptions.language);
|
|
67
|
+
}
|
|
68
|
+
if (normalizedOptions.region) {
|
|
69
|
+
params.set("region", normalizedOptions.region);
|
|
70
|
+
}
|
|
71
|
+
if (normalizedOptions.libraries.length) {
|
|
72
|
+
params.set("libraries", normalizedOptions.libraries.join(","));
|
|
73
|
+
}
|
|
74
|
+
if (normalizedOptions.mapIds.length) {
|
|
75
|
+
params.set("map_ids", normalizedOptions.mapIds.join(","));
|
|
76
|
+
}
|
|
77
|
+
if (normalizedOptions.authReferrerPolicy) {
|
|
78
|
+
params.set("auth_referrer_policy", normalizedOptions.authReferrerPolicy);
|
|
79
|
+
}
|
|
80
|
+
if (normalizedOptions.channel) {
|
|
81
|
+
params.set("channel", normalizedOptions.channel);
|
|
82
|
+
}
|
|
83
|
+
if (normalizedOptions.solutionChannel) {
|
|
84
|
+
params.set("solution_channel", normalizedOptions.solutionChannel);
|
|
85
|
+
}
|
|
86
|
+
const script = document.createElement("script");
|
|
87
|
+
script.async = true;
|
|
88
|
+
script.defer = true;
|
|
89
|
+
script.dataset.revivejsGoogleMapsLoader = "true";
|
|
90
|
+
script.src = `https://maps.googleapis.com/maps/api/js?${params.toString()}`;
|
|
91
|
+
if (normalizedOptions.nonce) {
|
|
92
|
+
script.nonce = normalizedOptions.nonce;
|
|
93
|
+
}
|
|
94
|
+
window[callbackName] = () => {
|
|
95
|
+
delete window[callbackName];
|
|
96
|
+
if (window.google?.maps) {
|
|
97
|
+
resolve(window.google);
|
|
98
|
+
} else {
|
|
99
|
+
reject(new Error("Google Maps callback fired but the google.maps namespace is unavailable."));
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
script.onerror = () => {
|
|
103
|
+
loaderPromise = null;
|
|
104
|
+
loadedOptionsKey = null;
|
|
105
|
+
delete window[callbackName];
|
|
106
|
+
reject(new Error("The Google Maps JavaScript API script failed to load."));
|
|
107
|
+
};
|
|
108
|
+
document.head.appendChild(script);
|
|
109
|
+
});
|
|
110
|
+
return loaderPromise;
|
|
111
|
+
}
|
|
112
|
+
function normalizeLoaderOptions(options) {
|
|
113
|
+
return {
|
|
114
|
+
...options,
|
|
115
|
+
version: options.version || "weekly",
|
|
116
|
+
libraries: Array.from(/* @__PURE__ */ new Set([...options.libraries || [], ...DEFAULT_LIBRARIES])).sort(),
|
|
117
|
+
mapIds: Array.from(new Set(options.mapIds || [])).sort()
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/GoogleMapsProvider.tsx
|
|
122
|
+
import { jsx } from "react/jsx-runtime";
|
|
123
|
+
function GoogleMapsProvider({ children, ...options }) {
|
|
124
|
+
const [status, setStatus] = useState("idle");
|
|
125
|
+
const [error, setError] = useState(null);
|
|
126
|
+
const [googleApi, setGoogleApi] = useState(
|
|
127
|
+
() => typeof window !== "undefined" && window.google?.maps ? window.google : null
|
|
128
|
+
);
|
|
129
|
+
const serializedOptions = JSON.stringify({
|
|
130
|
+
...options,
|
|
131
|
+
libraries: options.libraries || [],
|
|
132
|
+
mapIds: options.mapIds || []
|
|
133
|
+
});
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
let cancelled = false;
|
|
136
|
+
if (!options.apiKey) {
|
|
137
|
+
setStatus("idle");
|
|
138
|
+
setError(null);
|
|
139
|
+
setGoogleApi(null);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
setStatus((current) => current === "ready" ? current : "loading");
|
|
143
|
+
setError(null);
|
|
144
|
+
loadGoogleMapsApi(options).then((googleNamespace) => {
|
|
145
|
+
if (cancelled) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
setGoogleApi(googleNamespace);
|
|
149
|
+
setStatus("ready");
|
|
150
|
+
}).catch((nextError) => {
|
|
151
|
+
if (cancelled) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
setError(nextError instanceof Error ? nextError : new Error(String(nextError)));
|
|
155
|
+
setStatus("error");
|
|
156
|
+
});
|
|
157
|
+
return () => {
|
|
158
|
+
cancelled = true;
|
|
159
|
+
};
|
|
160
|
+
}, [serializedOptions]);
|
|
161
|
+
const value = useMemo(
|
|
162
|
+
() => ({
|
|
163
|
+
status,
|
|
164
|
+
error,
|
|
165
|
+
google: googleApi,
|
|
166
|
+
options
|
|
167
|
+
}),
|
|
168
|
+
[status, error, googleApi, serializedOptions]
|
|
169
|
+
);
|
|
170
|
+
return /* @__PURE__ */ jsx(GoogleMapsApiContext.Provider, { value, children });
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/clusterRenderer.ts
|
|
174
|
+
function createClusterRenderer(options = {}) {
|
|
175
|
+
return {
|
|
176
|
+
render(cluster, stats, map) {
|
|
177
|
+
const count = cluster.count;
|
|
178
|
+
const position = cluster.position;
|
|
179
|
+
const contextBase = {
|
|
180
|
+
cluster,
|
|
181
|
+
stats,
|
|
182
|
+
map,
|
|
183
|
+
count,
|
|
184
|
+
position,
|
|
185
|
+
color: "",
|
|
186
|
+
isAdvancedMarkerAvailable: false
|
|
187
|
+
};
|
|
188
|
+
const color = typeof options.color === "function" ? options.color(contextBase) : options.color || getDefaultClusterColor(count, stats);
|
|
189
|
+
const isAdvancedMarkerAvailable = options.useAdvancedMarker !== false && !!google.maps.marker?.AdvancedMarkerElement && !!map.get("mapId");
|
|
190
|
+
const context = {
|
|
191
|
+
...contextBase,
|
|
192
|
+
color,
|
|
193
|
+
isAdvancedMarkerAvailable
|
|
194
|
+
};
|
|
195
|
+
const title = typeof options.title === "function" ? options.title(context) : options.title || `Cluster with ${count} markers`;
|
|
196
|
+
const zIndex = (options.zIndexBase || 1e3) + count;
|
|
197
|
+
if (isAdvancedMarkerAvailable) {
|
|
198
|
+
return new google.maps.marker.AdvancedMarkerElement({
|
|
199
|
+
position,
|
|
200
|
+
title,
|
|
201
|
+
zIndex,
|
|
202
|
+
content: buildAdvancedClusterContent(context, options)
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return new google.maps.Marker({
|
|
206
|
+
position,
|
|
207
|
+
title,
|
|
208
|
+
zIndex,
|
|
209
|
+
label: {
|
|
210
|
+
text: String(count),
|
|
211
|
+
color: options.fallbackTextColor || "#ffffff",
|
|
212
|
+
fontSize: "12px",
|
|
213
|
+
fontWeight: "700"
|
|
214
|
+
},
|
|
215
|
+
icon: {
|
|
216
|
+
url: buildFallbackClusterSvg(
|
|
217
|
+
color,
|
|
218
|
+
options.fallbackBorderColor || "rgba(255,255,255,0.92)"
|
|
219
|
+
),
|
|
220
|
+
scaledSize: new google.maps.Size(46, 46)
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function buildAdvancedClusterContent(context, options) {
|
|
227
|
+
const customContent = options.render?.(context);
|
|
228
|
+
if (customContent instanceof HTMLElement) {
|
|
229
|
+
return customContent;
|
|
230
|
+
}
|
|
231
|
+
const element = document.createElement("div");
|
|
232
|
+
element.className = options.className || "revivejs-cluster-badge";
|
|
233
|
+
element.style.display = "grid";
|
|
234
|
+
element.style.gap = "2px";
|
|
235
|
+
element.style.minWidth = "52px";
|
|
236
|
+
element.style.padding = "10px 12px";
|
|
237
|
+
element.style.borderRadius = "999px";
|
|
238
|
+
element.style.background = context.color;
|
|
239
|
+
element.style.color = "#ffffff";
|
|
240
|
+
element.style.boxShadow = "0 12px 24px rgba(16, 32, 51, 0.18)";
|
|
241
|
+
element.style.border = "2px solid rgba(255,255,255,0.88)";
|
|
242
|
+
element.style.textAlign = "center";
|
|
243
|
+
element.style.fontFamily = "Avenir Next, Segoe UI, sans-serif";
|
|
244
|
+
const countNode = document.createElement("strong");
|
|
245
|
+
countNode.textContent = String(context.count);
|
|
246
|
+
countNode.style.fontSize = "14px";
|
|
247
|
+
countNode.style.lineHeight = "1";
|
|
248
|
+
const labelNode = document.createElement("span");
|
|
249
|
+
labelNode.textContent = typeof customContent === "string" ? customContent : "markers";
|
|
250
|
+
labelNode.style.fontSize = "10px";
|
|
251
|
+
labelNode.style.opacity = "0.92";
|
|
252
|
+
labelNode.style.lineHeight = "1";
|
|
253
|
+
element.append(countNode, labelNode);
|
|
254
|
+
return element;
|
|
255
|
+
}
|
|
256
|
+
function getDefaultClusterColor(count, stats) {
|
|
257
|
+
return count > Math.max(10, stats.clusters.markers.mean) ? "#d94b2b" : "#0d5c9e";
|
|
258
|
+
}
|
|
259
|
+
function buildFallbackClusterSvg(fill, stroke) {
|
|
260
|
+
const svg = `
|
|
261
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
262
|
+
<circle cx="32" cy="32" r="28" fill="${fill}" stroke="${stroke}" stroke-width="4" />
|
|
263
|
+
</svg>
|
|
264
|
+
`;
|
|
265
|
+
return `data:image/svg+xml;base64,${window.btoa(svg)}`;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// src/GoogleMap.tsx
|
|
269
|
+
import {
|
|
270
|
+
forwardRef,
|
|
271
|
+
useEffect as useEffect2,
|
|
272
|
+
useImperativeHandle,
|
|
273
|
+
useMemo as useMemo2,
|
|
274
|
+
useRef as useRef2,
|
|
275
|
+
useState as useState2
|
|
276
|
+
} from "react";
|
|
277
|
+
|
|
278
|
+
// src/hooks.ts
|
|
279
|
+
import { useContext as useContext2, useRef } from "react";
|
|
280
|
+
function useGoogleMapsApi() {
|
|
281
|
+
const context = useGoogleMapsApiContext();
|
|
282
|
+
return {
|
|
283
|
+
...context,
|
|
284
|
+
isLoaded: context.status === "ready" && !!context.google
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function useGoogleMap() {
|
|
288
|
+
return useContext2(GoogleMapContext);
|
|
289
|
+
}
|
|
290
|
+
function useMapGeocoder() {
|
|
291
|
+
const { google: google2, isLoaded } = useGoogleMapsApi();
|
|
292
|
+
const geocoderRef = useRef(null);
|
|
293
|
+
if (isLoaded && google2 && !geocoderRef.current) {
|
|
294
|
+
geocoderRef.current = new google2.maps.Geocoder();
|
|
295
|
+
}
|
|
296
|
+
return geocoderRef.current;
|
|
297
|
+
}
|
|
298
|
+
function useDirectionsService() {
|
|
299
|
+
const { google: google2, isLoaded } = useGoogleMapsApi();
|
|
300
|
+
const directionsServiceRef = useRef(null);
|
|
301
|
+
if (isLoaded && google2 && !directionsServiceRef.current) {
|
|
302
|
+
directionsServiceRef.current = new google2.maps.DirectionsService();
|
|
303
|
+
}
|
|
304
|
+
return directionsServiceRef.current;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/utils.ts
|
|
308
|
+
function addListener(target, eventName, handler) {
|
|
309
|
+
if (!target || !handler) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
return google.maps.event.addListener(target, eventName, (...args) => {
|
|
313
|
+
handler(...args);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
function composeMapOptions(options, extra) {
|
|
317
|
+
return {
|
|
318
|
+
...options,
|
|
319
|
+
...removeUndefined(extra)
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function removeUndefined(input) {
|
|
323
|
+
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
|
|
324
|
+
}
|
|
325
|
+
function toLatLng(value) {
|
|
326
|
+
if (!value) {
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
if (value instanceof google.maps.LatLng) {
|
|
330
|
+
return value;
|
|
331
|
+
}
|
|
332
|
+
return new google.maps.LatLng(value);
|
|
333
|
+
}
|
|
334
|
+
function toMVCArrayPath(path) {
|
|
335
|
+
return path.map((point) => point instanceof google.maps.LatLng ? point : new google.maps.LatLng(point));
|
|
336
|
+
}
|
|
337
|
+
function shallowBoundsEqual(left, right) {
|
|
338
|
+
return left?.east === right?.east && left?.west === right?.west && left?.north === right?.north && left?.south === right?.south;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// src/GoogleMap.tsx
|
|
342
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
343
|
+
var DEFAULT_CENTER = { lat: 37.421995, lng: -122.084092 };
|
|
344
|
+
var DEFAULT_ZOOM = 13;
|
|
345
|
+
var GoogleMap = forwardRef(function GoogleMap2({
|
|
346
|
+
children,
|
|
347
|
+
center = DEFAULT_CENTER,
|
|
348
|
+
zoom = DEFAULT_ZOOM,
|
|
349
|
+
mapId,
|
|
350
|
+
options,
|
|
351
|
+
width = "100%",
|
|
352
|
+
height = 460,
|
|
353
|
+
loadingFallback,
|
|
354
|
+
errorFallback,
|
|
355
|
+
onMapLoad,
|
|
356
|
+
onMapUnmount,
|
|
357
|
+
onClick,
|
|
358
|
+
onDblClick,
|
|
359
|
+
onDrag,
|
|
360
|
+
onDragStart,
|
|
361
|
+
onDragEnd,
|
|
362
|
+
onIdle,
|
|
363
|
+
onBoundsChanged,
|
|
364
|
+
onCenterChanged,
|
|
365
|
+
onHeadingChanged,
|
|
366
|
+
onMapTypeIdChanged,
|
|
367
|
+
onMouseMove,
|
|
368
|
+
onMouseOut,
|
|
369
|
+
onMouseOver,
|
|
370
|
+
onProjectionChanged,
|
|
371
|
+
onRightClick,
|
|
372
|
+
onTilesLoaded,
|
|
373
|
+
onTiltChanged,
|
|
374
|
+
onZoomChanged,
|
|
375
|
+
className,
|
|
376
|
+
style,
|
|
377
|
+
...divProps
|
|
378
|
+
}, ref) {
|
|
379
|
+
const { isLoaded, status, error, google: google2 } = useGoogleMapsApi();
|
|
380
|
+
const containerRef = useRef2(null);
|
|
381
|
+
const [map, setMap] = useState2(null);
|
|
382
|
+
const initialMapIdRef = useRef2(mapId);
|
|
383
|
+
useImperativeHandle(
|
|
384
|
+
ref,
|
|
385
|
+
() => ({
|
|
386
|
+
map,
|
|
387
|
+
fitBounds(bounds) {
|
|
388
|
+
map?.fitBounds(bounds);
|
|
389
|
+
},
|
|
390
|
+
panBy(x, y) {
|
|
391
|
+
map?.panBy(x, y);
|
|
392
|
+
},
|
|
393
|
+
panTo(position) {
|
|
394
|
+
map?.panTo(position);
|
|
395
|
+
},
|
|
396
|
+
panToBounds(bounds, padding) {
|
|
397
|
+
map?.panToBounds(bounds, padding);
|
|
398
|
+
},
|
|
399
|
+
setZoom(nextZoom) {
|
|
400
|
+
map?.setZoom(nextZoom);
|
|
401
|
+
},
|
|
402
|
+
setCenter(position) {
|
|
403
|
+
map?.setCenter(position);
|
|
404
|
+
},
|
|
405
|
+
setOptions(nextOptions) {
|
|
406
|
+
map?.setOptions(nextOptions);
|
|
407
|
+
},
|
|
408
|
+
getBounds() {
|
|
409
|
+
return map?.getBounds() || null;
|
|
410
|
+
},
|
|
411
|
+
getCenter() {
|
|
412
|
+
return map?.getCenter();
|
|
413
|
+
},
|
|
414
|
+
getClickableIcons() {
|
|
415
|
+
return map?.getClickableIcons();
|
|
416
|
+
},
|
|
417
|
+
getHeading() {
|
|
418
|
+
return map?.getHeading();
|
|
419
|
+
},
|
|
420
|
+
getMapTypeId() {
|
|
421
|
+
return map?.getMapTypeId();
|
|
422
|
+
},
|
|
423
|
+
getProjection() {
|
|
424
|
+
return map?.getProjection() || null;
|
|
425
|
+
},
|
|
426
|
+
getStreetView() {
|
|
427
|
+
return map?.getStreetView() || null;
|
|
428
|
+
},
|
|
429
|
+
getTilt() {
|
|
430
|
+
return map?.getTilt();
|
|
431
|
+
},
|
|
432
|
+
getZoom() {
|
|
433
|
+
return map?.getZoom();
|
|
434
|
+
},
|
|
435
|
+
controls() {
|
|
436
|
+
return map?.controls || null;
|
|
437
|
+
},
|
|
438
|
+
data() {
|
|
439
|
+
return map?.data || null;
|
|
440
|
+
},
|
|
441
|
+
mapTypes() {
|
|
442
|
+
return map?.mapTypes || null;
|
|
443
|
+
},
|
|
444
|
+
overlayMapTypes() {
|
|
445
|
+
return map?.overlayMapTypes || null;
|
|
446
|
+
}
|
|
447
|
+
}),
|
|
448
|
+
[map]
|
|
449
|
+
);
|
|
450
|
+
useEffect2(() => {
|
|
451
|
+
if (!isLoaded || !google2 || !containerRef.current || map) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
const nextMap = new google2.maps.Map(
|
|
455
|
+
containerRef.current,
|
|
456
|
+
composeMapOptions(options, {
|
|
457
|
+
center,
|
|
458
|
+
zoom,
|
|
459
|
+
mapId: initialMapIdRef.current
|
|
460
|
+
})
|
|
461
|
+
);
|
|
462
|
+
setMap(nextMap);
|
|
463
|
+
onMapLoad?.(nextMap);
|
|
464
|
+
return () => {
|
|
465
|
+
onMapUnmount?.(nextMap);
|
|
466
|
+
setMap(null);
|
|
467
|
+
};
|
|
468
|
+
}, [isLoaded, google2, map]);
|
|
469
|
+
useEffect2(() => {
|
|
470
|
+
if (!map) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
map.setOptions(
|
|
474
|
+
composeMapOptions(options, {
|
|
475
|
+
center,
|
|
476
|
+
zoom
|
|
477
|
+
})
|
|
478
|
+
);
|
|
479
|
+
}, [map, options, center, zoom]);
|
|
480
|
+
useEffect2(() => {
|
|
481
|
+
if (!map || !center) {
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
const nextCenter = toLatLng(center);
|
|
485
|
+
if (nextCenter) {
|
|
486
|
+
map.setCenter(nextCenter);
|
|
487
|
+
}
|
|
488
|
+
}, [map, center]);
|
|
489
|
+
useEffect2(() => {
|
|
490
|
+
if (!map || zoom === void 0) {
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
if (map.getZoom() !== zoom) {
|
|
494
|
+
map.setZoom(zoom);
|
|
495
|
+
}
|
|
496
|
+
}, [map, zoom]);
|
|
497
|
+
useEffect2(() => {
|
|
498
|
+
if (!map) {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
const listeners = [
|
|
502
|
+
addListener(map, "click", onClick),
|
|
503
|
+
addListener(map, "dblclick", onDblClick),
|
|
504
|
+
addListener(map, "drag", onDrag),
|
|
505
|
+
addListener(map, "dragstart", onDragStart),
|
|
506
|
+
addListener(map, "dragend", onDragEnd),
|
|
507
|
+
addListener(map, "idle", onIdle),
|
|
508
|
+
addListener(map, "bounds_changed", onBoundsChanged),
|
|
509
|
+
addListener(map, "center_changed", onCenterChanged),
|
|
510
|
+
addListener(map, "heading_changed", onHeadingChanged),
|
|
511
|
+
addListener(map, "maptypeid_changed", onMapTypeIdChanged),
|
|
512
|
+
addListener(map, "mousemove", onMouseMove),
|
|
513
|
+
addListener(map, "mouseout", onMouseOut),
|
|
514
|
+
addListener(map, "mouseover", onMouseOver),
|
|
515
|
+
addListener(map, "projection_changed", onProjectionChanged),
|
|
516
|
+
addListener(map, "rightclick", onRightClick),
|
|
517
|
+
addListener(map, "tilesloaded", onTilesLoaded),
|
|
518
|
+
addListener(map, "tilt_changed", onTiltChanged),
|
|
519
|
+
addListener(map, "zoom_changed", onZoomChanged)
|
|
520
|
+
].filter(Boolean);
|
|
521
|
+
return () => {
|
|
522
|
+
listeners.forEach((listener) => listener?.remove());
|
|
523
|
+
};
|
|
524
|
+
}, [
|
|
525
|
+
map,
|
|
526
|
+
onClick,
|
|
527
|
+
onDblClick,
|
|
528
|
+
onDrag,
|
|
529
|
+
onDragStart,
|
|
530
|
+
onDragEnd,
|
|
531
|
+
onIdle,
|
|
532
|
+
onBoundsChanged,
|
|
533
|
+
onCenterChanged,
|
|
534
|
+
onHeadingChanged,
|
|
535
|
+
onMapTypeIdChanged,
|
|
536
|
+
onMouseMove,
|
|
537
|
+
onMouseOut,
|
|
538
|
+
onMouseOver,
|
|
539
|
+
onProjectionChanged,
|
|
540
|
+
onRightClick,
|
|
541
|
+
onTilesLoaded,
|
|
542
|
+
onTiltChanged,
|
|
543
|
+
onZoomChanged
|
|
544
|
+
]);
|
|
545
|
+
useEffect2(() => {
|
|
546
|
+
if (!map || !google2 || !containerRef.current || typeof ResizeObserver === "undefined") {
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
const observer = new ResizeObserver(() => {
|
|
550
|
+
const currentCenter = map.getCenter();
|
|
551
|
+
google2.maps.event.trigger(map, "resize");
|
|
552
|
+
if (currentCenter) {
|
|
553
|
+
map.setCenter(currentCenter);
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
observer.observe(containerRef.current);
|
|
557
|
+
return () => {
|
|
558
|
+
observer.disconnect();
|
|
559
|
+
};
|
|
560
|
+
}, [map, google2]);
|
|
561
|
+
const mergedStyle = useMemo2(
|
|
562
|
+
() => ({
|
|
563
|
+
width,
|
|
564
|
+
height,
|
|
565
|
+
minHeight: typeof height === "number" ? `${height}px` : void 0,
|
|
566
|
+
position: "relative",
|
|
567
|
+
overflow: "hidden",
|
|
568
|
+
...style
|
|
569
|
+
}),
|
|
570
|
+
[width, height, style]
|
|
571
|
+
);
|
|
572
|
+
return /* @__PURE__ */ jsxs("div", { ...divProps, className, style: mergedStyle, ref: containerRef, children: [
|
|
573
|
+
status === "error" ? errorFallback || /* @__PURE__ */ jsx2(MapStatus, { message: error?.message || "The Google Maps API failed to load.", tone: "error" }) : null,
|
|
574
|
+
!isLoaded && status !== "error" ? loadingFallback || /* @__PURE__ */ jsx2(MapStatus, { message: "Loading Google Maps JavaScript API\u2026", tone: "loading" }) : null,
|
|
575
|
+
map ? /* @__PURE__ */ jsx2(GoogleMapContext.Provider, { value: map, children }) : null
|
|
576
|
+
] });
|
|
577
|
+
});
|
|
578
|
+
function MapStatus({ message, tone }) {
|
|
579
|
+
return /* @__PURE__ */ jsx2(
|
|
580
|
+
"div",
|
|
581
|
+
{
|
|
582
|
+
style: {
|
|
583
|
+
position: "absolute",
|
|
584
|
+
inset: 0,
|
|
585
|
+
display: "grid",
|
|
586
|
+
placeItems: "center",
|
|
587
|
+
padding: "1rem",
|
|
588
|
+
background: tone === "error" ? "rgba(255, 245, 245, 0.9)" : "rgba(244, 249, 255, 0.9)",
|
|
589
|
+
color: tone === "error" ? "#8c2b2b" : "#24415f",
|
|
590
|
+
fontSize: "0.95rem",
|
|
591
|
+
zIndex: 0
|
|
592
|
+
},
|
|
593
|
+
children: /* @__PURE__ */ jsx2("div", { children: message })
|
|
594
|
+
}
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// src/markers.tsx
|
|
599
|
+
import { MarkerClusterer } from "@googlemaps/markerclusterer";
|
|
600
|
+
import {
|
|
601
|
+
useContext as useContext3,
|
|
602
|
+
forwardRef as forwardRef2,
|
|
603
|
+
useEffect as useEffect3,
|
|
604
|
+
useImperativeHandle as useImperativeHandle2,
|
|
605
|
+
useMemo as useMemo3,
|
|
606
|
+
useRef as useRef3,
|
|
607
|
+
useState as useState3
|
|
608
|
+
} from "react";
|
|
609
|
+
import { createPortal } from "react-dom";
|
|
610
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
611
|
+
var MapMarker = forwardRef2(function MapMarker2({
|
|
612
|
+
position,
|
|
613
|
+
title,
|
|
614
|
+
label,
|
|
615
|
+
clickable,
|
|
616
|
+
draggable,
|
|
617
|
+
icon,
|
|
618
|
+
visible,
|
|
619
|
+
zIndex,
|
|
620
|
+
animation,
|
|
621
|
+
options,
|
|
622
|
+
onLoad,
|
|
623
|
+
onUnmount,
|
|
624
|
+
onClick,
|
|
625
|
+
onDblClick,
|
|
626
|
+
onDrag,
|
|
627
|
+
onDragEnd,
|
|
628
|
+
onDragStart,
|
|
629
|
+
onMouseDown,
|
|
630
|
+
onMouseOut,
|
|
631
|
+
onMouseOver,
|
|
632
|
+
onMouseUp,
|
|
633
|
+
onRightClick
|
|
634
|
+
}, ref) {
|
|
635
|
+
const map = useGoogleMap();
|
|
636
|
+
const clustererContext = useContext3(MarkerClustererContext);
|
|
637
|
+
const [marker, setMarker] = useState3(null);
|
|
638
|
+
useImperativeHandle2(
|
|
639
|
+
ref,
|
|
640
|
+
() => ({
|
|
641
|
+
marker,
|
|
642
|
+
getAnimation() {
|
|
643
|
+
return marker?.getAnimation();
|
|
644
|
+
},
|
|
645
|
+
getClickable() {
|
|
646
|
+
return marker?.getClickable();
|
|
647
|
+
},
|
|
648
|
+
getDraggable() {
|
|
649
|
+
return marker?.getDraggable();
|
|
650
|
+
},
|
|
651
|
+
getIcon() {
|
|
652
|
+
return marker?.getIcon();
|
|
653
|
+
},
|
|
654
|
+
getLabel() {
|
|
655
|
+
return marker?.getLabel();
|
|
656
|
+
},
|
|
657
|
+
getPosition() {
|
|
658
|
+
return marker?.getPosition();
|
|
659
|
+
},
|
|
660
|
+
getTitle() {
|
|
661
|
+
return marker?.getTitle();
|
|
662
|
+
},
|
|
663
|
+
getVisible() {
|
|
664
|
+
return marker?.getVisible();
|
|
665
|
+
},
|
|
666
|
+
getZIndex() {
|
|
667
|
+
return marker?.getZIndex();
|
|
668
|
+
},
|
|
669
|
+
setAnimation(nextAnimation) {
|
|
670
|
+
marker?.setAnimation(nextAnimation);
|
|
671
|
+
},
|
|
672
|
+
setOptions(nextOptions) {
|
|
673
|
+
marker?.setOptions(nextOptions);
|
|
674
|
+
},
|
|
675
|
+
setPosition(nextPosition) {
|
|
676
|
+
marker?.setPosition(nextPosition);
|
|
677
|
+
},
|
|
678
|
+
setTitle(nextTitle) {
|
|
679
|
+
marker?.setTitle(nextTitle);
|
|
680
|
+
},
|
|
681
|
+
setVisible(nextVisible) {
|
|
682
|
+
marker?.setVisible(nextVisible);
|
|
683
|
+
},
|
|
684
|
+
setZIndex(nextZIndex) {
|
|
685
|
+
marker?.setZIndex(nextZIndex);
|
|
686
|
+
}
|
|
687
|
+
}),
|
|
688
|
+
[marker]
|
|
689
|
+
);
|
|
690
|
+
useEffect3(() => {
|
|
691
|
+
if (!map || marker) {
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
const instance = new google.maps.Marker();
|
|
695
|
+
setMarker(instance);
|
|
696
|
+
onLoad?.(instance);
|
|
697
|
+
return () => {
|
|
698
|
+
onUnmount?.(instance);
|
|
699
|
+
clustererContext?.unregisterMarker(instance);
|
|
700
|
+
instance.setMap(null);
|
|
701
|
+
};
|
|
702
|
+
}, [map, marker]);
|
|
703
|
+
useEffect3(() => {
|
|
704
|
+
if (!marker || !map) {
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
marker.setOptions({
|
|
708
|
+
...options,
|
|
709
|
+
...removeUndefined({
|
|
710
|
+
position,
|
|
711
|
+
title,
|
|
712
|
+
label,
|
|
713
|
+
clickable,
|
|
714
|
+
draggable,
|
|
715
|
+
icon,
|
|
716
|
+
visible,
|
|
717
|
+
zIndex,
|
|
718
|
+
animation
|
|
719
|
+
})
|
|
720
|
+
});
|
|
721
|
+
if (clustererContext) {
|
|
722
|
+
marker.setMap(null);
|
|
723
|
+
clustererContext.registerMarker(marker);
|
|
724
|
+
} else {
|
|
725
|
+
marker.setMap(map);
|
|
726
|
+
}
|
|
727
|
+
}, [marker, map, clustererContext, position, title, label, clickable, draggable, icon, visible, zIndex, animation, options]);
|
|
728
|
+
useEffect3(() => {
|
|
729
|
+
if (!marker) {
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
732
|
+
const listeners = [
|
|
733
|
+
addListener(marker, "click", onClick),
|
|
734
|
+
addListener(marker, "dblclick", onDblClick),
|
|
735
|
+
addListener(marker, "drag", onDrag),
|
|
736
|
+
addListener(marker, "dragend", onDragEnd),
|
|
737
|
+
addListener(marker, "dragstart", onDragStart),
|
|
738
|
+
addListener(marker, "mousedown", onMouseDown),
|
|
739
|
+
addListener(marker, "mouseout", onMouseOut),
|
|
740
|
+
addListener(marker, "mouseover", onMouseOver),
|
|
741
|
+
addListener(marker, "mouseup", onMouseUp),
|
|
742
|
+
addListener(marker, "rightclick", onRightClick)
|
|
743
|
+
].filter(Boolean);
|
|
744
|
+
return () => {
|
|
745
|
+
listeners.forEach((listener) => listener?.remove());
|
|
746
|
+
};
|
|
747
|
+
}, [marker, onClick, onDblClick, onDrag, onDragEnd, onDragStart, onMouseDown, onMouseOut, onMouseOver, onMouseUp, onRightClick]);
|
|
748
|
+
return null;
|
|
749
|
+
});
|
|
750
|
+
var MapAdvancedMarker = forwardRef2(function MapAdvancedMarker2({
|
|
751
|
+
position,
|
|
752
|
+
title,
|
|
753
|
+
zIndex,
|
|
754
|
+
gmpClickable,
|
|
755
|
+
gmpDraggable,
|
|
756
|
+
options,
|
|
757
|
+
collisionBehavior,
|
|
758
|
+
children,
|
|
759
|
+
onLoad,
|
|
760
|
+
onUnmount,
|
|
761
|
+
onClick,
|
|
762
|
+
onDragStart,
|
|
763
|
+
onDrag,
|
|
764
|
+
onDragEnd
|
|
765
|
+
}, ref) {
|
|
766
|
+
const map = useGoogleMap();
|
|
767
|
+
const { isLoaded } = useGoogleMapsApi();
|
|
768
|
+
const clustererContext = useContext3(MarkerClustererContext);
|
|
769
|
+
const [marker, setMarker] = useState3(null);
|
|
770
|
+
const [contentElement] = useState3(() => typeof document !== "undefined" ? document.createElement("div") : null);
|
|
771
|
+
useImperativeHandle2(
|
|
772
|
+
ref,
|
|
773
|
+
() => ({
|
|
774
|
+
marker,
|
|
775
|
+
content: contentElement,
|
|
776
|
+
setMap(nextMap) {
|
|
777
|
+
if (marker) {
|
|
778
|
+
marker.map = nextMap;
|
|
779
|
+
}
|
|
780
|
+
},
|
|
781
|
+
setPosition(nextPosition) {
|
|
782
|
+
if (marker) {
|
|
783
|
+
marker.position = toLatLng(nextPosition) || nextPosition;
|
|
784
|
+
}
|
|
785
|
+
},
|
|
786
|
+
setZIndex(nextZIndex) {
|
|
787
|
+
if (marker) {
|
|
788
|
+
marker.zIndex = nextZIndex;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}),
|
|
792
|
+
[marker, contentElement]
|
|
793
|
+
);
|
|
794
|
+
useEffect3(() => {
|
|
795
|
+
if (!map || !isLoaded || marker) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
if (!google.maps.marker?.AdvancedMarkerElement) {
|
|
799
|
+
throw new Error(
|
|
800
|
+
"AdvancedMarkerElement is unavailable. Make sure the marker library is enabled and the map uses a valid mapId."
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
const instance = new google.maps.marker.AdvancedMarkerElement({
|
|
804
|
+
map: clustererContext ? void 0 : map,
|
|
805
|
+
content: children && contentElement ? contentElement : options?.content,
|
|
806
|
+
...options
|
|
807
|
+
});
|
|
808
|
+
setMarker(instance);
|
|
809
|
+
onLoad?.(instance);
|
|
810
|
+
return () => {
|
|
811
|
+
onUnmount?.(instance);
|
|
812
|
+
clustererContext?.unregisterMarker(instance);
|
|
813
|
+
instance.map = null;
|
|
814
|
+
};
|
|
815
|
+
}, [map, isLoaded, marker, clustererContext, children, contentElement, options]);
|
|
816
|
+
useEffect3(() => {
|
|
817
|
+
if (!marker || !map) {
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
marker.position = toLatLng(position) || position;
|
|
821
|
+
if (title !== void 0) {
|
|
822
|
+
marker.title = title;
|
|
823
|
+
}
|
|
824
|
+
marker.zIndex = zIndex;
|
|
825
|
+
marker.gmpClickable = gmpClickable;
|
|
826
|
+
marker.gmpDraggable = gmpDraggable;
|
|
827
|
+
if (collisionBehavior !== void 0) {
|
|
828
|
+
marker.collisionBehavior = collisionBehavior;
|
|
829
|
+
}
|
|
830
|
+
if (children && contentElement) {
|
|
831
|
+
marker.content = contentElement;
|
|
832
|
+
}
|
|
833
|
+
if (clustererContext) {
|
|
834
|
+
marker.map = null;
|
|
835
|
+
clustererContext.registerMarker(marker);
|
|
836
|
+
} else {
|
|
837
|
+
marker.map = map;
|
|
838
|
+
}
|
|
839
|
+
}, [marker, map, clustererContext, position, title, zIndex, gmpClickable, gmpDraggable, collisionBehavior, children, contentElement]);
|
|
840
|
+
useEffect3(() => {
|
|
841
|
+
if (!marker) {
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
const listeners = [
|
|
845
|
+
addListener(marker, "click", onClick),
|
|
846
|
+
addListener(marker, "dragstart", onDragStart),
|
|
847
|
+
addListener(marker, "drag", onDrag),
|
|
848
|
+
addListener(marker, "dragend", onDragEnd)
|
|
849
|
+
].filter(Boolean);
|
|
850
|
+
return () => {
|
|
851
|
+
listeners.forEach((listener) => listener?.remove());
|
|
852
|
+
};
|
|
853
|
+
}, [marker, onClick, onDragStart, onDrag, onDragEnd]);
|
|
854
|
+
return children && contentElement ? createPortal(children, contentElement) : null;
|
|
855
|
+
});
|
|
856
|
+
var MapInfoWindow = forwardRef2(function MapInfoWindow2({
|
|
857
|
+
anchor,
|
|
858
|
+
open = true,
|
|
859
|
+
position,
|
|
860
|
+
zIndex,
|
|
861
|
+
options,
|
|
862
|
+
children,
|
|
863
|
+
onLoad,
|
|
864
|
+
onUnmount,
|
|
865
|
+
onCloseClick,
|
|
866
|
+
onDomReady,
|
|
867
|
+
onContentChanged,
|
|
868
|
+
onPositionChanged,
|
|
869
|
+
onZIndexChanged
|
|
870
|
+
}, ref) {
|
|
871
|
+
const map = useGoogleMap();
|
|
872
|
+
const [infoWindow, setInfoWindow] = useState3(null);
|
|
873
|
+
const [contentElement] = useState3(() => typeof document !== "undefined" ? document.createElement("div") : null);
|
|
874
|
+
useImperativeHandle2(
|
|
875
|
+
ref,
|
|
876
|
+
() => ({
|
|
877
|
+
infoWindow,
|
|
878
|
+
open(nextAnchor) {
|
|
879
|
+
if (!infoWindow) {
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
infoWindow.open({
|
|
883
|
+
map,
|
|
884
|
+
anchor: nextAnchor || anchor || void 0
|
|
885
|
+
});
|
|
886
|
+
},
|
|
887
|
+
close() {
|
|
888
|
+
infoWindow?.close();
|
|
889
|
+
},
|
|
890
|
+
getContent() {
|
|
891
|
+
return infoWindow?.getContent();
|
|
892
|
+
},
|
|
893
|
+
getPosition() {
|
|
894
|
+
return infoWindow?.getPosition() || null;
|
|
895
|
+
},
|
|
896
|
+
getZIndex() {
|
|
897
|
+
return infoWindow?.getZIndex();
|
|
898
|
+
},
|
|
899
|
+
setContent(content) {
|
|
900
|
+
infoWindow?.setContent(content);
|
|
901
|
+
},
|
|
902
|
+
setPosition(nextPosition) {
|
|
903
|
+
infoWindow?.setPosition(nextPosition);
|
|
904
|
+
},
|
|
905
|
+
setZIndex(nextZIndex) {
|
|
906
|
+
infoWindow?.setZIndex(nextZIndex);
|
|
907
|
+
}
|
|
908
|
+
}),
|
|
909
|
+
[infoWindow, map, anchor]
|
|
910
|
+
);
|
|
911
|
+
useEffect3(() => {
|
|
912
|
+
if (!map || infoWindow) {
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
const instance = new google.maps.InfoWindow({
|
|
916
|
+
...options,
|
|
917
|
+
content: contentElement || options?.content,
|
|
918
|
+
position,
|
|
919
|
+
zIndex
|
|
920
|
+
});
|
|
921
|
+
setInfoWindow(instance);
|
|
922
|
+
onLoad?.(instance);
|
|
923
|
+
return () => {
|
|
924
|
+
onUnmount?.(instance);
|
|
925
|
+
instance.close();
|
|
926
|
+
};
|
|
927
|
+
}, [map, infoWindow, options, contentElement, position, zIndex]);
|
|
928
|
+
useEffect3(() => {
|
|
929
|
+
if (!infoWindow) {
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
infoWindow.setOptions({
|
|
933
|
+
...options,
|
|
934
|
+
content: children && contentElement ? contentElement : options?.content,
|
|
935
|
+
position,
|
|
936
|
+
zIndex
|
|
937
|
+
});
|
|
938
|
+
}, [infoWindow, options, position, zIndex, children, contentElement]);
|
|
939
|
+
useEffect3(() => {
|
|
940
|
+
if (!infoWindow) {
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
if (!open) {
|
|
944
|
+
infoWindow.close();
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
infoWindow.open({
|
|
948
|
+
map,
|
|
949
|
+
anchor
|
|
950
|
+
});
|
|
951
|
+
}, [infoWindow, map, anchor, open, position]);
|
|
952
|
+
useEffect3(() => {
|
|
953
|
+
if (!infoWindow) {
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
const listeners = [
|
|
957
|
+
addListener(infoWindow, "closeclick", onCloseClick),
|
|
958
|
+
addListener(infoWindow, "domready", onDomReady),
|
|
959
|
+
addListener(infoWindow, "content_changed", onContentChanged),
|
|
960
|
+
addListener(infoWindow, "position_changed", onPositionChanged),
|
|
961
|
+
addListener(infoWindow, "zindex_changed", onZIndexChanged)
|
|
962
|
+
].filter(Boolean);
|
|
963
|
+
return () => {
|
|
964
|
+
listeners.forEach((listener) => listener?.remove());
|
|
965
|
+
};
|
|
966
|
+
}, [infoWindow, onCloseClick, onDomReady, onContentChanged, onPositionChanged, onZIndexChanged]);
|
|
967
|
+
return children && contentElement ? createPortal(children, contentElement) : null;
|
|
968
|
+
});
|
|
969
|
+
var MapMarkerClusterer = forwardRef2(function MapMarkerClusterer2({
|
|
970
|
+
children,
|
|
971
|
+
algorithm,
|
|
972
|
+
renderer,
|
|
973
|
+
onLoad,
|
|
974
|
+
onUnmount,
|
|
975
|
+
onClusterClick
|
|
976
|
+
}, ref) {
|
|
977
|
+
const map = useGoogleMap();
|
|
978
|
+
const [clusterer, setClusterer] = useState3(null);
|
|
979
|
+
const pendingMarkersRef = useRef3(/* @__PURE__ */ new Set());
|
|
980
|
+
useImperativeHandle2(
|
|
981
|
+
ref,
|
|
982
|
+
() => ({
|
|
983
|
+
clusterer,
|
|
984
|
+
addMarker(marker, noDraw) {
|
|
985
|
+
clusterer?.addMarker(marker, noDraw);
|
|
986
|
+
},
|
|
987
|
+
addMarkers(markers, noDraw) {
|
|
988
|
+
clusterer?.addMarkers(markers, noDraw);
|
|
989
|
+
},
|
|
990
|
+
removeMarker(marker, noDraw) {
|
|
991
|
+
return clusterer?.removeMarker(marker, noDraw) ?? false;
|
|
992
|
+
},
|
|
993
|
+
clearMarkers(noDraw) {
|
|
994
|
+
clusterer?.clearMarkers(noDraw);
|
|
995
|
+
},
|
|
996
|
+
render() {
|
|
997
|
+
clusterer?.render();
|
|
998
|
+
}
|
|
999
|
+
}),
|
|
1000
|
+
[clusterer]
|
|
1001
|
+
);
|
|
1002
|
+
useEffect3(() => {
|
|
1003
|
+
if (!map || clusterer) {
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
1006
|
+
const instance = new MarkerClusterer({
|
|
1007
|
+
map,
|
|
1008
|
+
markers: Array.from(pendingMarkersRef.current),
|
|
1009
|
+
algorithm,
|
|
1010
|
+
renderer,
|
|
1011
|
+
onClusterClick
|
|
1012
|
+
});
|
|
1013
|
+
setClusterer(instance);
|
|
1014
|
+
onLoad?.(instance);
|
|
1015
|
+
return () => {
|
|
1016
|
+
onUnmount?.(instance);
|
|
1017
|
+
instance.clearMarkers();
|
|
1018
|
+
instance.setMap?.(null);
|
|
1019
|
+
};
|
|
1020
|
+
}, [map, clusterer, algorithm, renderer, onClusterClick]);
|
|
1021
|
+
const contextValue = useMemo3(
|
|
1022
|
+
() => ({
|
|
1023
|
+
clusterer,
|
|
1024
|
+
registerMarker(marker) {
|
|
1025
|
+
if (clusterer) {
|
|
1026
|
+
clusterer.addMarker(marker, true);
|
|
1027
|
+
clusterer.render();
|
|
1028
|
+
} else {
|
|
1029
|
+
pendingMarkersRef.current.add(marker);
|
|
1030
|
+
}
|
|
1031
|
+
},
|
|
1032
|
+
unregisterMarker(marker) {
|
|
1033
|
+
pendingMarkersRef.current.delete(marker);
|
|
1034
|
+
if (clusterer) {
|
|
1035
|
+
clusterer.removeMarker(marker, true);
|
|
1036
|
+
clusterer.render();
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
}),
|
|
1040
|
+
[clusterer]
|
|
1041
|
+
);
|
|
1042
|
+
return /* @__PURE__ */ jsx3(MarkerClustererContext.Provider, { value: contextValue, children });
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
// src/shapes.tsx
|
|
1046
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
1047
|
+
import { forwardRef as forwardRef3, useEffect as useEffect4, useImperativeHandle as useImperativeHandle3, useState as useState4 } from "react";
|
|
1048
|
+
var MapPolyline = forwardRef3(function MapPolyline2({
|
|
1049
|
+
path,
|
|
1050
|
+
options,
|
|
1051
|
+
onLoad,
|
|
1052
|
+
onUnmount,
|
|
1053
|
+
onClick,
|
|
1054
|
+
onDblClick,
|
|
1055
|
+
onMouseDown,
|
|
1056
|
+
onMouseMove,
|
|
1057
|
+
onMouseOut,
|
|
1058
|
+
onMouseOver,
|
|
1059
|
+
onMouseUp,
|
|
1060
|
+
onRightClick,
|
|
1061
|
+
onDrag,
|
|
1062
|
+
onDragEnd,
|
|
1063
|
+
onDragStart
|
|
1064
|
+
}, ref) {
|
|
1065
|
+
const map = useGoogleMap();
|
|
1066
|
+
const [polyline, setPolyline] = useState4(null);
|
|
1067
|
+
useImperativeHandle3(
|
|
1068
|
+
ref,
|
|
1069
|
+
() => ({
|
|
1070
|
+
polyline,
|
|
1071
|
+
getPath() {
|
|
1072
|
+
return polyline?.getPath() || null;
|
|
1073
|
+
},
|
|
1074
|
+
getVisible() {
|
|
1075
|
+
return polyline?.getVisible();
|
|
1076
|
+
},
|
|
1077
|
+
getDraggable() {
|
|
1078
|
+
return polyline?.getDraggable();
|
|
1079
|
+
},
|
|
1080
|
+
getEditable() {
|
|
1081
|
+
return polyline?.getEditable();
|
|
1082
|
+
},
|
|
1083
|
+
setPath(nextPath) {
|
|
1084
|
+
polyline?.setPath(toMVCArrayPath(nextPath));
|
|
1085
|
+
},
|
|
1086
|
+
setOptions(nextOptions) {
|
|
1087
|
+
polyline?.setOptions(nextOptions);
|
|
1088
|
+
}
|
|
1089
|
+
}),
|
|
1090
|
+
[polyline]
|
|
1091
|
+
);
|
|
1092
|
+
useEffect4(() => {
|
|
1093
|
+
if (!map || polyline) {
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
const instance = new google.maps.Polyline({ map });
|
|
1097
|
+
setPolyline(instance);
|
|
1098
|
+
onLoad?.(instance);
|
|
1099
|
+
return () => {
|
|
1100
|
+
onUnmount?.(instance);
|
|
1101
|
+
instance.setMap(null);
|
|
1102
|
+
};
|
|
1103
|
+
}, [map, polyline]);
|
|
1104
|
+
useEffect4(() => {
|
|
1105
|
+
if (!polyline) {
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
polyline.setOptions({
|
|
1109
|
+
...options,
|
|
1110
|
+
path: toMVCArrayPath(path),
|
|
1111
|
+
map
|
|
1112
|
+
});
|
|
1113
|
+
}, [polyline, map, path, options]);
|
|
1114
|
+
useShapeEvents(polyline, { onClick, onDblClick, onMouseDown, onMouseMove, onMouseOut, onMouseOver, onMouseUp, onRightClick, onDrag, onDragEnd, onDragStart });
|
|
1115
|
+
return null;
|
|
1116
|
+
});
|
|
1117
|
+
var MapPolygon = forwardRef3(function MapPolygon2({
|
|
1118
|
+
paths,
|
|
1119
|
+
options,
|
|
1120
|
+
onLoad,
|
|
1121
|
+
onUnmount,
|
|
1122
|
+
onClick,
|
|
1123
|
+
onDblClick,
|
|
1124
|
+
onMouseDown,
|
|
1125
|
+
onMouseMove,
|
|
1126
|
+
onMouseOut,
|
|
1127
|
+
onMouseOver,
|
|
1128
|
+
onMouseUp,
|
|
1129
|
+
onRightClick,
|
|
1130
|
+
onDrag,
|
|
1131
|
+
onDragEnd,
|
|
1132
|
+
onDragStart
|
|
1133
|
+
}, ref) {
|
|
1134
|
+
const map = useGoogleMap();
|
|
1135
|
+
const [polygon, setPolygon] = useState4(null);
|
|
1136
|
+
useImperativeHandle3(
|
|
1137
|
+
ref,
|
|
1138
|
+
() => ({
|
|
1139
|
+
polygon,
|
|
1140
|
+
getPath() {
|
|
1141
|
+
return polygon?.getPath() || null;
|
|
1142
|
+
},
|
|
1143
|
+
getPaths() {
|
|
1144
|
+
return polygon?.getPaths() || null;
|
|
1145
|
+
},
|
|
1146
|
+
getVisible() {
|
|
1147
|
+
return polygon?.getVisible();
|
|
1148
|
+
},
|
|
1149
|
+
getDraggable() {
|
|
1150
|
+
return polygon?.getDraggable();
|
|
1151
|
+
},
|
|
1152
|
+
getEditable() {
|
|
1153
|
+
return polygon?.getEditable();
|
|
1154
|
+
},
|
|
1155
|
+
setPaths(nextPaths) {
|
|
1156
|
+
const value = Array.isArray(nextPaths[0]) ? nextPaths.map((path) => toMVCArrayPath(path)) : toMVCArrayPath(nextPaths);
|
|
1157
|
+
polygon?.setPaths(value);
|
|
1158
|
+
},
|
|
1159
|
+
setOptions(nextOptions) {
|
|
1160
|
+
polygon?.setOptions(nextOptions);
|
|
1161
|
+
}
|
|
1162
|
+
}),
|
|
1163
|
+
[polygon]
|
|
1164
|
+
);
|
|
1165
|
+
useEffect4(() => {
|
|
1166
|
+
if (!map || polygon) {
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
const instance = new google.maps.Polygon({ map });
|
|
1170
|
+
setPolygon(instance);
|
|
1171
|
+
onLoad?.(instance);
|
|
1172
|
+
return () => {
|
|
1173
|
+
onUnmount?.(instance);
|
|
1174
|
+
instance.setMap(null);
|
|
1175
|
+
};
|
|
1176
|
+
}, [map, polygon]);
|
|
1177
|
+
useEffect4(() => {
|
|
1178
|
+
if (!polygon) {
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
const nextPaths = Array.isArray(paths[0]) ? paths.map((path) => toMVCArrayPath(path)) : toMVCArrayPath(paths);
|
|
1182
|
+
polygon.setOptions({
|
|
1183
|
+
...options,
|
|
1184
|
+
paths: nextPaths,
|
|
1185
|
+
map
|
|
1186
|
+
});
|
|
1187
|
+
}, [polygon, map, paths, options]);
|
|
1188
|
+
useShapeEvents(polygon, { onClick, onDblClick, onMouseDown, onMouseMove, onMouseOut, onMouseOver, onMouseUp, onRightClick, onDrag, onDragEnd, onDragStart });
|
|
1189
|
+
return null;
|
|
1190
|
+
});
|
|
1191
|
+
var MapRectangle = forwardRef3(function MapRectangle2({
|
|
1192
|
+
bounds,
|
|
1193
|
+
options,
|
|
1194
|
+
onLoad,
|
|
1195
|
+
onUnmount,
|
|
1196
|
+
onClick,
|
|
1197
|
+
onDblClick,
|
|
1198
|
+
onMouseDown,
|
|
1199
|
+
onMouseMove,
|
|
1200
|
+
onMouseOut,
|
|
1201
|
+
onMouseOver,
|
|
1202
|
+
onMouseUp,
|
|
1203
|
+
onRightClick,
|
|
1204
|
+
onDrag,
|
|
1205
|
+
onDragEnd,
|
|
1206
|
+
onDragStart
|
|
1207
|
+
}, ref) {
|
|
1208
|
+
const map = useGoogleMap();
|
|
1209
|
+
const [rectangle, setRectangle] = useState4(null);
|
|
1210
|
+
useImperativeHandle3(
|
|
1211
|
+
ref,
|
|
1212
|
+
() => ({
|
|
1213
|
+
rectangle,
|
|
1214
|
+
getBounds() {
|
|
1215
|
+
return rectangle?.getBounds() || null;
|
|
1216
|
+
},
|
|
1217
|
+
getVisible() {
|
|
1218
|
+
return rectangle?.getVisible();
|
|
1219
|
+
},
|
|
1220
|
+
getDraggable() {
|
|
1221
|
+
return rectangle?.getDraggable();
|
|
1222
|
+
},
|
|
1223
|
+
getEditable() {
|
|
1224
|
+
return rectangle?.getEditable();
|
|
1225
|
+
},
|
|
1226
|
+
setBounds(nextBounds) {
|
|
1227
|
+
rectangle?.setBounds(nextBounds);
|
|
1228
|
+
},
|
|
1229
|
+
setOptions(nextOptions) {
|
|
1230
|
+
rectangle?.setOptions(nextOptions);
|
|
1231
|
+
}
|
|
1232
|
+
}),
|
|
1233
|
+
[rectangle]
|
|
1234
|
+
);
|
|
1235
|
+
useEffect4(() => {
|
|
1236
|
+
if (!map || rectangle) {
|
|
1237
|
+
return;
|
|
1238
|
+
}
|
|
1239
|
+
const instance = new google.maps.Rectangle({ map });
|
|
1240
|
+
setRectangle(instance);
|
|
1241
|
+
onLoad?.(instance);
|
|
1242
|
+
return () => {
|
|
1243
|
+
onUnmount?.(instance);
|
|
1244
|
+
instance.setMap(null);
|
|
1245
|
+
};
|
|
1246
|
+
}, [map, rectangle]);
|
|
1247
|
+
useEffect4(() => {
|
|
1248
|
+
if (!rectangle) {
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
if (!shallowBoundsEqual(rectangle.getBounds()?.toJSON(), bounds)) {
|
|
1252
|
+
rectangle.setBounds(bounds);
|
|
1253
|
+
}
|
|
1254
|
+
rectangle.setOptions({
|
|
1255
|
+
...options,
|
|
1256
|
+
map
|
|
1257
|
+
});
|
|
1258
|
+
}, [rectangle, map, bounds, options]);
|
|
1259
|
+
useShapeEvents(rectangle, { onClick, onDblClick, onMouseDown, onMouseMove, onMouseOut, onMouseOver, onMouseUp, onRightClick, onDrag, onDragEnd, onDragStart });
|
|
1260
|
+
return null;
|
|
1261
|
+
});
|
|
1262
|
+
var MapCircle = forwardRef3(function MapCircle2({
|
|
1263
|
+
center,
|
|
1264
|
+
radius,
|
|
1265
|
+
options,
|
|
1266
|
+
onLoad,
|
|
1267
|
+
onUnmount,
|
|
1268
|
+
onClick,
|
|
1269
|
+
onDblClick,
|
|
1270
|
+
onMouseDown,
|
|
1271
|
+
onMouseMove,
|
|
1272
|
+
onMouseOut,
|
|
1273
|
+
onMouseOver,
|
|
1274
|
+
onMouseUp,
|
|
1275
|
+
onRightClick,
|
|
1276
|
+
onDrag,
|
|
1277
|
+
onDragEnd,
|
|
1278
|
+
onDragStart
|
|
1279
|
+
}, ref) {
|
|
1280
|
+
const map = useGoogleMap();
|
|
1281
|
+
const [circle, setCircle] = useState4(null);
|
|
1282
|
+
useImperativeHandle3(
|
|
1283
|
+
ref,
|
|
1284
|
+
() => ({
|
|
1285
|
+
circle,
|
|
1286
|
+
getBounds() {
|
|
1287
|
+
return circle?.getBounds() || null;
|
|
1288
|
+
},
|
|
1289
|
+
getCenter() {
|
|
1290
|
+
return circle?.getCenter() || null;
|
|
1291
|
+
},
|
|
1292
|
+
getRadius() {
|
|
1293
|
+
return circle?.getRadius();
|
|
1294
|
+
},
|
|
1295
|
+
getVisible() {
|
|
1296
|
+
return circle?.getVisible();
|
|
1297
|
+
},
|
|
1298
|
+
getDraggable() {
|
|
1299
|
+
return circle?.getDraggable();
|
|
1300
|
+
},
|
|
1301
|
+
getEditable() {
|
|
1302
|
+
return circle?.getEditable();
|
|
1303
|
+
},
|
|
1304
|
+
setCenter(nextCenter) {
|
|
1305
|
+
circle?.setCenter(nextCenter);
|
|
1306
|
+
},
|
|
1307
|
+
setRadius(nextRadius) {
|
|
1308
|
+
circle?.setRadius(nextRadius);
|
|
1309
|
+
},
|
|
1310
|
+
setOptions(nextOptions) {
|
|
1311
|
+
circle?.setOptions(nextOptions);
|
|
1312
|
+
}
|
|
1313
|
+
}),
|
|
1314
|
+
[circle]
|
|
1315
|
+
);
|
|
1316
|
+
useEffect4(() => {
|
|
1317
|
+
if (!map || circle) {
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1320
|
+
const instance = new google.maps.Circle({ map });
|
|
1321
|
+
setCircle(instance);
|
|
1322
|
+
onLoad?.(instance);
|
|
1323
|
+
return () => {
|
|
1324
|
+
onUnmount?.(instance);
|
|
1325
|
+
instance.setMap(null);
|
|
1326
|
+
};
|
|
1327
|
+
}, [map, circle]);
|
|
1328
|
+
useEffect4(() => {
|
|
1329
|
+
if (!circle) {
|
|
1330
|
+
return;
|
|
1331
|
+
}
|
|
1332
|
+
circle.setOptions({
|
|
1333
|
+
...options,
|
|
1334
|
+
center,
|
|
1335
|
+
radius,
|
|
1336
|
+
map
|
|
1337
|
+
});
|
|
1338
|
+
}, [circle, map, center, radius, options]);
|
|
1339
|
+
useShapeEvents(circle, { onClick, onDblClick, onMouseDown, onMouseMove, onMouseOut, onMouseOver, onMouseUp, onRightClick, onDrag, onDragEnd, onDragStart });
|
|
1340
|
+
return null;
|
|
1341
|
+
});
|
|
1342
|
+
var MapGroundOverlay = forwardRef3(function MapGroundOverlay2({ url, bounds, opacity, clickable, onLoad, onUnmount, onClick }, ref) {
|
|
1343
|
+
const map = useGoogleMap();
|
|
1344
|
+
const [overlay, setOverlay] = useState4(null);
|
|
1345
|
+
useImperativeHandle3(
|
|
1346
|
+
ref,
|
|
1347
|
+
() => ({
|
|
1348
|
+
overlay,
|
|
1349
|
+
getBounds() {
|
|
1350
|
+
return overlay?.getBounds() || null;
|
|
1351
|
+
},
|
|
1352
|
+
getOpacity() {
|
|
1353
|
+
return overlay?.getOpacity();
|
|
1354
|
+
},
|
|
1355
|
+
getUrl() {
|
|
1356
|
+
return overlay?.getUrl();
|
|
1357
|
+
},
|
|
1358
|
+
setOpacity(nextOpacity) {
|
|
1359
|
+
overlay?.setOpacity(nextOpacity);
|
|
1360
|
+
},
|
|
1361
|
+
setMap(nextMap) {
|
|
1362
|
+
overlay?.setMap(nextMap);
|
|
1363
|
+
}
|
|
1364
|
+
}),
|
|
1365
|
+
[overlay]
|
|
1366
|
+
);
|
|
1367
|
+
useEffect4(() => {
|
|
1368
|
+
if (!map) {
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
const instance = new google.maps.GroundOverlay(url, bounds, removeUndefined({ opacity, clickable }));
|
|
1372
|
+
instance.setMap(map);
|
|
1373
|
+
setOverlay(instance);
|
|
1374
|
+
onLoad?.(instance);
|
|
1375
|
+
return () => {
|
|
1376
|
+
onUnmount?.(instance);
|
|
1377
|
+
instance.setMap(null);
|
|
1378
|
+
};
|
|
1379
|
+
}, [map, url, JSON.stringify(bounds), opacity, clickable]);
|
|
1380
|
+
useEffect4(() => {
|
|
1381
|
+
if (!overlay) {
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1384
|
+
const listener = addListener(overlay, "click", onClick);
|
|
1385
|
+
return () => {
|
|
1386
|
+
listener?.remove();
|
|
1387
|
+
};
|
|
1388
|
+
}, [overlay, onClick]);
|
|
1389
|
+
return null;
|
|
1390
|
+
});
|
|
1391
|
+
function MapControl({ position, children, index }) {
|
|
1392
|
+
const map = useGoogleMap();
|
|
1393
|
+
const [element] = useState4(() => typeof document !== "undefined" ? document.createElement("div") : null);
|
|
1394
|
+
useEffect4(() => {
|
|
1395
|
+
if (!map || !element) {
|
|
1396
|
+
return;
|
|
1397
|
+
}
|
|
1398
|
+
const controls = map.controls[position];
|
|
1399
|
+
if (typeof index === "number" && index >= 0 && index < controls.getLength()) {
|
|
1400
|
+
controls.insertAt(index, element);
|
|
1401
|
+
} else {
|
|
1402
|
+
controls.push(element);
|
|
1403
|
+
}
|
|
1404
|
+
return () => {
|
|
1405
|
+
const nextControls = map.controls[position];
|
|
1406
|
+
for (let currentIndex = 0; currentIndex < nextControls.getLength(); currentIndex += 1) {
|
|
1407
|
+
if (nextControls.getAt(currentIndex) === element) {
|
|
1408
|
+
nextControls.removeAt(currentIndex);
|
|
1409
|
+
break;
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
};
|
|
1413
|
+
}, [map, element, position, index]);
|
|
1414
|
+
return element ? createPortal2(children, element) : null;
|
|
1415
|
+
}
|
|
1416
|
+
function useShapeEvents(shape, handlers) {
|
|
1417
|
+
useEffect4(() => {
|
|
1418
|
+
if (!shape) {
|
|
1419
|
+
return;
|
|
1420
|
+
}
|
|
1421
|
+
const listeners = [
|
|
1422
|
+
addListener(shape, "click", handlers.onClick),
|
|
1423
|
+
addListener(shape, "dblclick", handlers.onDblClick),
|
|
1424
|
+
addListener(shape, "mousedown", handlers.onMouseDown),
|
|
1425
|
+
addListener(shape, "mousemove", handlers.onMouseMove),
|
|
1426
|
+
addListener(shape, "mouseout", handlers.onMouseOut),
|
|
1427
|
+
addListener(shape, "mouseover", handlers.onMouseOver),
|
|
1428
|
+
addListener(shape, "mouseup", handlers.onMouseUp),
|
|
1429
|
+
addListener(shape, "rightclick", handlers.onRightClick),
|
|
1430
|
+
addListener(shape, "drag", handlers.onDrag),
|
|
1431
|
+
addListener(shape, "dragend", handlers.onDragEnd),
|
|
1432
|
+
addListener(shape, "dragstart", handlers.onDragStart)
|
|
1433
|
+
].filter(Boolean);
|
|
1434
|
+
return () => {
|
|
1435
|
+
listeners.forEach((listener) => listener?.remove());
|
|
1436
|
+
};
|
|
1437
|
+
}, [shape, handlers.onClick, handlers.onDblClick, handlers.onMouseDown, handlers.onMouseMove, handlers.onMouseOut, handlers.onMouseOver, handlers.onMouseUp, handlers.onRightClick, handlers.onDrag, handlers.onDragEnd, handlers.onDragStart]);
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
// src/layers.tsx
|
|
1441
|
+
import { forwardRef as forwardRef4, useEffect as useEffect5, useImperativeHandle as useImperativeHandle4, useState as useState5 } from "react";
|
|
1442
|
+
var MapTrafficLayer = forwardRef4(function MapTrafficLayer2({ options, onLoad, onUnmount }, ref) {
|
|
1443
|
+
const map = useGoogleMap();
|
|
1444
|
+
const [layer, setLayer] = useState5(null);
|
|
1445
|
+
useImperativeHandle4(
|
|
1446
|
+
ref,
|
|
1447
|
+
() => ({
|
|
1448
|
+
layer,
|
|
1449
|
+
setMap(nextMap) {
|
|
1450
|
+
layer?.setMap(nextMap);
|
|
1451
|
+
},
|
|
1452
|
+
setOptions(nextOptions) {
|
|
1453
|
+
layer?.setOptions(nextOptions);
|
|
1454
|
+
}
|
|
1455
|
+
}),
|
|
1456
|
+
[layer]
|
|
1457
|
+
);
|
|
1458
|
+
useEffect5(() => {
|
|
1459
|
+
if (!map || layer) {
|
|
1460
|
+
return;
|
|
1461
|
+
}
|
|
1462
|
+
const instance = new google.maps.TrafficLayer(options);
|
|
1463
|
+
instance.setMap(map);
|
|
1464
|
+
setLayer(instance);
|
|
1465
|
+
onLoad?.(instance);
|
|
1466
|
+
return () => {
|
|
1467
|
+
onUnmount?.(instance);
|
|
1468
|
+
instance.setMap(null);
|
|
1469
|
+
};
|
|
1470
|
+
}, [map, layer]);
|
|
1471
|
+
useEffect5(() => {
|
|
1472
|
+
if (layer && options) {
|
|
1473
|
+
layer.setOptions(options);
|
|
1474
|
+
}
|
|
1475
|
+
}, [layer, options]);
|
|
1476
|
+
return null;
|
|
1477
|
+
});
|
|
1478
|
+
var MapTransitLayer = forwardRef4(function MapTransitLayer2({ onLoad, onUnmount }, ref) {
|
|
1479
|
+
const map = useGoogleMap();
|
|
1480
|
+
const [layer, setLayer] = useState5(null);
|
|
1481
|
+
useImperativeHandle4(
|
|
1482
|
+
ref,
|
|
1483
|
+
() => ({
|
|
1484
|
+
layer,
|
|
1485
|
+
setMap(nextMap) {
|
|
1486
|
+
layer?.setMap(nextMap);
|
|
1487
|
+
}
|
|
1488
|
+
}),
|
|
1489
|
+
[layer]
|
|
1490
|
+
);
|
|
1491
|
+
useEffect5(() => {
|
|
1492
|
+
if (!map) {
|
|
1493
|
+
return;
|
|
1494
|
+
}
|
|
1495
|
+
const layer2 = new google.maps.TransitLayer();
|
|
1496
|
+
layer2.setMap(map);
|
|
1497
|
+
setLayer(layer2);
|
|
1498
|
+
onLoad?.(layer2);
|
|
1499
|
+
return () => {
|
|
1500
|
+
onUnmount?.(layer2);
|
|
1501
|
+
layer2.setMap(null);
|
|
1502
|
+
};
|
|
1503
|
+
}, [map]);
|
|
1504
|
+
return null;
|
|
1505
|
+
});
|
|
1506
|
+
var MapBicyclingLayer = forwardRef4(function MapBicyclingLayer2({ onLoad, onUnmount }, ref) {
|
|
1507
|
+
const map = useGoogleMap();
|
|
1508
|
+
const [layer, setLayer] = useState5(null);
|
|
1509
|
+
useImperativeHandle4(
|
|
1510
|
+
ref,
|
|
1511
|
+
() => ({
|
|
1512
|
+
layer,
|
|
1513
|
+
setMap(nextMap) {
|
|
1514
|
+
layer?.setMap(nextMap);
|
|
1515
|
+
}
|
|
1516
|
+
}),
|
|
1517
|
+
[layer]
|
|
1518
|
+
);
|
|
1519
|
+
useEffect5(() => {
|
|
1520
|
+
if (!map) {
|
|
1521
|
+
return;
|
|
1522
|
+
}
|
|
1523
|
+
const layer2 = new google.maps.BicyclingLayer();
|
|
1524
|
+
layer2.setMap(map);
|
|
1525
|
+
setLayer(layer2);
|
|
1526
|
+
onLoad?.(layer2);
|
|
1527
|
+
return () => {
|
|
1528
|
+
onUnmount?.(layer2);
|
|
1529
|
+
layer2.setMap(null);
|
|
1530
|
+
};
|
|
1531
|
+
}, [map]);
|
|
1532
|
+
return null;
|
|
1533
|
+
});
|
|
1534
|
+
var MapKmlLayer = forwardRef4(function MapKmlLayer2({
|
|
1535
|
+
url,
|
|
1536
|
+
options,
|
|
1537
|
+
onLoad,
|
|
1538
|
+
onUnmount
|
|
1539
|
+
}, ref) {
|
|
1540
|
+
const map = useGoogleMap();
|
|
1541
|
+
const [layer, setLayer] = useState5(null);
|
|
1542
|
+
useImperativeHandle4(
|
|
1543
|
+
ref,
|
|
1544
|
+
() => ({
|
|
1545
|
+
layer,
|
|
1546
|
+
getDefaultViewport() {
|
|
1547
|
+
return layer?.getDefaultViewport() || null;
|
|
1548
|
+
},
|
|
1549
|
+
getMetadata() {
|
|
1550
|
+
return layer?.getMetadata() || null;
|
|
1551
|
+
},
|
|
1552
|
+
getStatus() {
|
|
1553
|
+
return layer?.getStatus() || null;
|
|
1554
|
+
},
|
|
1555
|
+
getUrl() {
|
|
1556
|
+
return layer?.getUrl() || null;
|
|
1557
|
+
},
|
|
1558
|
+
setMap(nextMap) {
|
|
1559
|
+
layer?.setMap(nextMap);
|
|
1560
|
+
},
|
|
1561
|
+
setOptions(nextOptions) {
|
|
1562
|
+
layer?.setOptions(nextOptions);
|
|
1563
|
+
},
|
|
1564
|
+
setUrl(nextUrl) {
|
|
1565
|
+
layer?.setUrl(nextUrl);
|
|
1566
|
+
}
|
|
1567
|
+
}),
|
|
1568
|
+
[layer]
|
|
1569
|
+
);
|
|
1570
|
+
useEffect5(() => {
|
|
1571
|
+
if (!map) {
|
|
1572
|
+
return;
|
|
1573
|
+
}
|
|
1574
|
+
const instance = new google.maps.KmlLayer({
|
|
1575
|
+
...options,
|
|
1576
|
+
map,
|
|
1577
|
+
url
|
|
1578
|
+
});
|
|
1579
|
+
setLayer(instance);
|
|
1580
|
+
onLoad?.(instance);
|
|
1581
|
+
return () => {
|
|
1582
|
+
onUnmount?.(instance);
|
|
1583
|
+
instance.setMap(null);
|
|
1584
|
+
};
|
|
1585
|
+
}, [map, url]);
|
|
1586
|
+
useEffect5(() => {
|
|
1587
|
+
if (!layer) {
|
|
1588
|
+
return;
|
|
1589
|
+
}
|
|
1590
|
+
layer.setOptions({
|
|
1591
|
+
...options,
|
|
1592
|
+
map
|
|
1593
|
+
});
|
|
1594
|
+
layer.setUrl(url);
|
|
1595
|
+
}, [layer, options, map, url]);
|
|
1596
|
+
return null;
|
|
1597
|
+
});
|
|
1598
|
+
var MapHeatmapLayer = forwardRef4(function MapHeatmapLayer2({
|
|
1599
|
+
data,
|
|
1600
|
+
options,
|
|
1601
|
+
onLoad,
|
|
1602
|
+
onUnmount
|
|
1603
|
+
}, ref) {
|
|
1604
|
+
const map = useGoogleMap();
|
|
1605
|
+
const [layer, setLayer] = useState5(null);
|
|
1606
|
+
useImperativeHandle4(
|
|
1607
|
+
ref,
|
|
1608
|
+
() => ({
|
|
1609
|
+
layer,
|
|
1610
|
+
getData() {
|
|
1611
|
+
return layer?.getData() || null;
|
|
1612
|
+
},
|
|
1613
|
+
setData(nextData) {
|
|
1614
|
+
layer?.setData(normalizeHeatmapData(nextData));
|
|
1615
|
+
},
|
|
1616
|
+
setMap(nextMap) {
|
|
1617
|
+
layer?.setMap(nextMap);
|
|
1618
|
+
},
|
|
1619
|
+
setOptions(nextOptions) {
|
|
1620
|
+
layer?.setOptions(nextOptions);
|
|
1621
|
+
}
|
|
1622
|
+
}),
|
|
1623
|
+
[layer]
|
|
1624
|
+
);
|
|
1625
|
+
useEffect5(() => {
|
|
1626
|
+
if (!map) {
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1629
|
+
if (!google.maps.visualization?.HeatmapLayer) {
|
|
1630
|
+
throw new Error("HeatmapLayer is unavailable. Make sure the visualization library is enabled.");
|
|
1631
|
+
}
|
|
1632
|
+
const instance = new google.maps.visualization.HeatmapLayer({
|
|
1633
|
+
...options,
|
|
1634
|
+
map,
|
|
1635
|
+
data: normalizeHeatmapData(data)
|
|
1636
|
+
});
|
|
1637
|
+
setLayer(instance);
|
|
1638
|
+
onLoad?.(instance);
|
|
1639
|
+
return () => {
|
|
1640
|
+
onUnmount?.(instance);
|
|
1641
|
+
instance.setMap(null);
|
|
1642
|
+
};
|
|
1643
|
+
}, [map]);
|
|
1644
|
+
useEffect5(() => {
|
|
1645
|
+
if (!layer) {
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
layer.setOptions({
|
|
1649
|
+
...options,
|
|
1650
|
+
data: normalizeHeatmapData(data),
|
|
1651
|
+
map
|
|
1652
|
+
});
|
|
1653
|
+
}, [layer, options, data, map]);
|
|
1654
|
+
return null;
|
|
1655
|
+
});
|
|
1656
|
+
function normalizeHeatmapData(data) {
|
|
1657
|
+
return data.map((entry) => {
|
|
1658
|
+
if ("location" in entry) {
|
|
1659
|
+
const weighted = entry;
|
|
1660
|
+
return {
|
|
1661
|
+
location: toLatLng(weighted.location),
|
|
1662
|
+
weight: weighted.weight
|
|
1663
|
+
};
|
|
1664
|
+
}
|
|
1665
|
+
return toLatLng(entry);
|
|
1666
|
+
});
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
// src/directions.tsx
|
|
1670
|
+
import { forwardRef as forwardRef5, useEffect as useEffect6, useImperativeHandle as useImperativeHandle5, useRef as useRef4, useState as useState6 } from "react";
|
|
1671
|
+
var MapDirectionsRenderer = forwardRef5(function MapDirectionsRenderer2({
|
|
1672
|
+
directions,
|
|
1673
|
+
options,
|
|
1674
|
+
onLoad,
|
|
1675
|
+
onUnmount,
|
|
1676
|
+
onDirectionsChanged
|
|
1677
|
+
}, ref) {
|
|
1678
|
+
const map = useGoogleMap();
|
|
1679
|
+
const [renderer, setRenderer] = useState6(null);
|
|
1680
|
+
useImperativeHandle5(
|
|
1681
|
+
ref,
|
|
1682
|
+
() => ({
|
|
1683
|
+
renderer,
|
|
1684
|
+
getDirections() {
|
|
1685
|
+
return renderer?.getDirections() || null;
|
|
1686
|
+
},
|
|
1687
|
+
getPanel() {
|
|
1688
|
+
return renderer?.getPanel() || null;
|
|
1689
|
+
},
|
|
1690
|
+
getRouteIndex() {
|
|
1691
|
+
return renderer?.getRouteIndex();
|
|
1692
|
+
},
|
|
1693
|
+
setDirections(nextDirections) {
|
|
1694
|
+
renderer?.setDirections(nextDirections);
|
|
1695
|
+
},
|
|
1696
|
+
setOptions(nextOptions) {
|
|
1697
|
+
renderer?.setOptions(nextOptions);
|
|
1698
|
+
},
|
|
1699
|
+
setRouteIndex(nextRouteIndex) {
|
|
1700
|
+
renderer?.setRouteIndex(nextRouteIndex);
|
|
1701
|
+
}
|
|
1702
|
+
}),
|
|
1703
|
+
[renderer]
|
|
1704
|
+
);
|
|
1705
|
+
useEffect6(() => {
|
|
1706
|
+
if (!map || renderer) {
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
const instance = new google.maps.DirectionsRenderer({
|
|
1710
|
+
...options,
|
|
1711
|
+
map
|
|
1712
|
+
});
|
|
1713
|
+
setRenderer(instance);
|
|
1714
|
+
onLoad?.(instance);
|
|
1715
|
+
return () => {
|
|
1716
|
+
onUnmount?.(instance);
|
|
1717
|
+
instance.setMap(null);
|
|
1718
|
+
};
|
|
1719
|
+
}, [map, renderer]);
|
|
1720
|
+
useEffect6(() => {
|
|
1721
|
+
if (!renderer) {
|
|
1722
|
+
return;
|
|
1723
|
+
}
|
|
1724
|
+
renderer.setOptions({
|
|
1725
|
+
...options,
|
|
1726
|
+
directions: directions || void 0,
|
|
1727
|
+
map
|
|
1728
|
+
});
|
|
1729
|
+
}, [renderer, directions, options, map]);
|
|
1730
|
+
useEffect6(() => {
|
|
1731
|
+
if (!renderer) {
|
|
1732
|
+
return;
|
|
1733
|
+
}
|
|
1734
|
+
const listener = addListener(renderer, "directions_changed", onDirectionsChanged);
|
|
1735
|
+
return () => {
|
|
1736
|
+
listener?.remove();
|
|
1737
|
+
};
|
|
1738
|
+
}, [renderer, onDirectionsChanged]);
|
|
1739
|
+
return null;
|
|
1740
|
+
});
|
|
1741
|
+
function MapDirectionsService({
|
|
1742
|
+
request,
|
|
1743
|
+
onResult,
|
|
1744
|
+
onError
|
|
1745
|
+
}) {
|
|
1746
|
+
const service = useDirectionsService();
|
|
1747
|
+
const requestIdRef = useRef4(0);
|
|
1748
|
+
useEffect6(() => {
|
|
1749
|
+
if (!service || !request) {
|
|
1750
|
+
return;
|
|
1751
|
+
}
|
|
1752
|
+
requestIdRef.current += 1;
|
|
1753
|
+
const currentRequestId = requestIdRef.current;
|
|
1754
|
+
service.route(request, (result, status) => {
|
|
1755
|
+
if (currentRequestId !== requestIdRef.current) {
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1758
|
+
if (status === google.maps.DirectionsStatus.OK && result) {
|
|
1759
|
+
onResult({ status, result });
|
|
1760
|
+
} else {
|
|
1761
|
+
const error = new Error(`Directions request failed with status ${status}.`);
|
|
1762
|
+
onResult({ status, result: result || null });
|
|
1763
|
+
onError?.(error);
|
|
1764
|
+
}
|
|
1765
|
+
});
|
|
1766
|
+
}, [service, request, onResult, onError]);
|
|
1767
|
+
return null;
|
|
1768
|
+
}
|
|
1769
|
+
export {
|
|
1770
|
+
GoogleMap,
|
|
1771
|
+
GoogleMapsProvider,
|
|
1772
|
+
MapAdvancedMarker,
|
|
1773
|
+
MapBicyclingLayer,
|
|
1774
|
+
MapCircle,
|
|
1775
|
+
MapControl,
|
|
1776
|
+
MapDirectionsRenderer,
|
|
1777
|
+
MapDirectionsService,
|
|
1778
|
+
MapGroundOverlay,
|
|
1779
|
+
MapHeatmapLayer,
|
|
1780
|
+
MapInfoWindow,
|
|
1781
|
+
MapKmlLayer,
|
|
1782
|
+
MapMarker,
|
|
1783
|
+
MapMarkerClusterer,
|
|
1784
|
+
MapPolygon,
|
|
1785
|
+
MapPolyline,
|
|
1786
|
+
MapRectangle,
|
|
1787
|
+
MapTrafficLayer,
|
|
1788
|
+
MapTransitLayer,
|
|
1789
|
+
createClusterRenderer,
|
|
1790
|
+
getDefaultGoogleMapsLibraries,
|
|
1791
|
+
loadGoogleMapsApi,
|
|
1792
|
+
useDirectionsService,
|
|
1793
|
+
useGoogleMap,
|
|
1794
|
+
useGoogleMapsApi,
|
|
1795
|
+
useMapGeocoder
|
|
1796
|
+
};
|
|
1797
|
+
//# sourceMappingURL=index.js.map
|