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