@sanity/google-maps-input 4.1.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { useState, useEffect, PureComponent, createRef, useCallback, useId, useRef } from "react";
3
- import { Card, Box, Text, Code, TextInput, Stack, Grid, Button, Dialog } from "@sanity/ui";
3
+ import { Card, Box, Text, Code, TextInput, Stack, Grid, Button, Dialog, Label } from "@sanity/ui";
4
4
  import { EditIcon, TrashIcon } from "@sanity/icons";
5
5
  import { setIfMissing, set, unset, ChangeIndicator, useUserColor, getAnnotationAtPath, DiffTooltip, definePlugin } from "sanity";
6
6
  import { styled } from "styled-components";
@@ -33,12 +33,11 @@ function isErrorEvent(event) {
33
33
  return typeof event != "object" || event === null || !("message" in event) ? !1 : typeof event.message == "string";
34
34
  }
35
35
  function LoadError(props) {
36
- var _a;
37
36
  return /* @__PURE__ */ jsxs(Card, { tone: "critical", radius: 1, children: [
38
37
  /* @__PURE__ */ jsx(Box, { as: "header", paddingX: 4, paddingTop: 4, paddingBottom: 1, children: /* @__PURE__ */ jsx(Text, { as: "h2", weight: "bold", children: "Google Maps failed to load" }) }),
39
38
  /* @__PURE__ */ jsx(Box, { paddingX: 4, paddingTop: 4, paddingBottom: 1, children: props.isAuthError ? /* @__PURE__ */ jsx(AuthError2, {}) : /* @__PURE__ */ jsxs(Fragment, { children: [
40
39
  /* @__PURE__ */ jsx(Text, { as: "h3", children: "Error details:" }),
41
- /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx(Code, { size: 1, children: "error" in props && ((_a = props.error) == null ? void 0 : _a.message) }) })
40
+ /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx(Code, { size: 1, children: "error" in props && props.error?.message }) })
42
41
  ] }) })
43
42
  ] });
44
43
  }
@@ -56,7 +55,7 @@ function AuthError2() {
56
55
  }
57
56
  const browserLocale = typeof window < "u" && window.navigator.language || "en";
58
57
  function useLoadGoogleMapsApi(config2) {
59
- const locale = config2.defaultLocale || browserLocale || "en-US", [state, setState] = useState({ type: "loading" });
58
+ const locale = config2.defaultLocale || browserLocale, [state, setState] = useState({ type: "loading" });
60
59
  return useEffect(() => {
61
60
  typeof window > "u" || loadGoogleMapsApi({ locale, apiKey: config2.apiKey }).then(
62
61
  (api) => setState({ type: "loaded", api }),
@@ -99,13 +98,12 @@ const PreviewImage = styled.img`
99
98
  top: 10px;
100
99
  width: 220px;
101
100
  `;
102
- var __defProp$5 = Object.defineProperty, __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __publicField$3 = (obj, key, value) => __defNormalProp$5(obj, typeof key != "symbol" ? key + "" : key, value);
103
101
  class SearchInput extends PureComponent {
104
- constructor() {
105
- super(...arguments), __publicField$3(this, "searchInputRef", createRef()), __publicField$3(this, "autoComplete"), __publicField$3(this, "handleChange", () => {
106
- this.autoComplete && (this.props.onChange(this.autoComplete.getPlace()), this.searchInputRef.current && (this.searchInputRef.current.value = ""));
107
- });
108
- }
102
+ searchInputRef = createRef();
103
+ autoComplete;
104
+ handleChange = () => {
105
+ this.autoComplete && (this.props.onChange(this.autoComplete.getPlace()), this.searchInputRef.current && (this.searchInputRef.current.value = ""));
106
+ };
109
107
  componentDidMount() {
110
108
  const input = this.searchInputRef.current;
111
109
  if (!input)
@@ -141,26 +139,25 @@ const MapContainer = styled.div`
141
139
  width: 100%;
142
140
  box-sizing: border-box;
143
141
  `;
144
- var __defProp$4 = Object.defineProperty, __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __publicField$2 = (obj, key, value) => __defNormalProp$4(obj, typeof key != "symbol" ? key + "" : key, value);
145
142
  class GoogleMap extends PureComponent {
146
- constructor() {
147
- super(...arguments), __publicField$2(this, "state", { map: void 0 }), __publicField$2(this, "clickHandler"), __publicField$2(this, "mapRef", createRef()), __publicField$2(this, "mapEl", null), __publicField$2(this, "attachClickHandler", () => {
148
- const map = this.state.map;
149
- if (!map)
150
- return;
151
- const { api, onClick } = this.props, { event } = api;
152
- this.clickHandler && this.clickHandler.remove(), onClick && (this.clickHandler = event.addListener(map, "click", onClick));
153
- }), __publicField$2(this, "setMapElement", (element) => {
154
- if (element && element !== this.mapEl) {
155
- const map = this.constructMap(element);
156
- this.setState({ map }, this.attachClickHandler);
157
- }
158
- this.mapEl = element;
159
- });
160
- }
143
+ static defaultProps = {
144
+ defaultZoom: 8,
145
+ scrollWheel: !0
146
+ };
147
+ state = { map: void 0 };
148
+ clickHandler;
149
+ mapRef = createRef();
150
+ mapEl = null;
161
151
  componentDidMount() {
162
152
  this.attachClickHandler();
163
153
  }
154
+ attachClickHandler = () => {
155
+ const map = this.state.map;
156
+ if (!map)
157
+ return;
158
+ const { api, onClick } = this.props, { event } = api;
159
+ this.clickHandler && this.clickHandler.remove(), onClick && (this.clickHandler = event.addListener(map, "click", onClick));
160
+ };
164
161
  componentDidUpdate(prevProps) {
165
162
  const map = this.state.map;
166
163
  if (!map)
@@ -186,6 +183,13 @@ class GoogleMap extends PureComponent {
186
183
  });
187
184
  return bounds && map.fitBounds(bounds), map;
188
185
  }
186
+ setMapElement = (element) => {
187
+ if (element && element !== this.mapEl) {
188
+ const map = this.constructMap(element);
189
+ this.setState({ map }, this.attachClickHandler);
190
+ }
191
+ this.mapEl = element;
192
+ };
189
193
  render() {
190
194
  const { children } = this.props, { map } = this.state;
191
195
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -194,16 +198,10 @@ class GoogleMap extends PureComponent {
194
198
  ] });
195
199
  }
196
200
  }
197
- __publicField$2(GoogleMap, "defaultProps", {
198
- defaultZoom: 8,
199
- scrollWheel: !0
200
- });
201
- var __defProp$3 = Object.defineProperty, __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __publicField$1 = (obj, key, value) => __defNormalProp$3(obj, typeof key != "symbol" ? key + "" : key, value);
202
201
  const markerPath = "M 3.052 3.7 C 1.56 5.293 0.626 7.612 0.663 9.793 C 0.738 14.352 2.793 16.077 6.078 22.351 C 7.263 25.111 8.497 28.032 9.672 32.871 C 9.835 33.584 9.994 34.246 10.069 34.305 C 10.143 34.362 10.301 33.697 10.465 32.983 C 11.639 28.145 12.875 25.226 14.059 22.466 C 17.344 16.192 19.398 14.466 19.474 9.908 C 19.511 7.727 18.574 5.405 17.083 3.814 C 15.379 1.994 12.809 0.649 10.069 0.593 C 7.328 0.536 4.756 1.882 3.052 3.7 Z";
203
202
  class Marker extends PureComponent {
204
- constructor() {
205
- super(...arguments), __publicField$1(this, "marker"), __publicField$1(this, "eventHandlers", {});
206
- }
203
+ marker;
204
+ eventHandlers = {};
207
205
  componentDidMount() {
208
206
  const { position, api, map, onMove, zIndex, opacity, label, markerRef, color } = this.props, { Marker: GMarker } = api;
209
207
  let icon;
@@ -247,30 +245,21 @@ class Marker extends PureComponent {
247
245
  return null;
248
246
  }
249
247
  }
250
- var __defProp$2 = Object.defineProperty, __getOwnPropSymbols$1 = Object.getOwnPropertySymbols, __hasOwnProp$1 = Object.prototype.hasOwnProperty, __propIsEnum$1 = Object.prototype.propertyIsEnumerable, __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues$1 = (a, b) => {
251
- for (var prop in b || (b = {}))
252
- __hasOwnProp$1.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
253
- if (__getOwnPropSymbols$1)
254
- for (var prop of __getOwnPropSymbols$1(b))
255
- __propIsEnum$1.call(b, prop) && __defNormalProp$2(a, prop, b[prop]);
256
- return a;
257
- };
258
- const fallbackLatLng = { lat: 40.7058254, lng: -74.1180863 }, GeopointSelect = ({
248
+ const fallbackLatLng$1 = { lat: 40.7058254, lng: -74.1180863 }, GeopointSelect = ({
259
249
  api,
260
250
  value,
261
251
  onChange,
262
252
  defaultLocation = { lng: 10.74609, lat: 59.91273 },
263
253
  defaultZoom = 8
264
254
  }) => {
265
- const getCenter2 = useCallback(() => __spreadValues$1(__spreadValues$1(__spreadValues$1({}, fallbackLatLng), defaultLocation), value), [value, defaultLocation]), setValue = useCallback(
255
+ const getCenter2 = useCallback(() => ({ ...fallbackLatLng$1, ...defaultLocation, ...value }), [value, defaultLocation]), setValue = useCallback(
266
256
  (geoPoint) => {
267
257
  onChange && onChange(geoPoint);
268
258
  },
269
259
  [onChange]
270
260
  ), handlePlaceChanged = useCallback(
271
261
  (place) => {
272
- var _a;
273
- (_a = place.geometry) != null && _a.location && setValue(place.geometry.location);
262
+ place.geometry?.location && setValue(place.geometry.location);
274
263
  },
275
264
  [setValue]
276
265
  ), handleMarkerDragEnd = useCallback(
@@ -296,7 +285,7 @@ const fallbackLatLng = { lat: 40.7058254, lng: -74.1180863 }, GeopointSelect = (
296
285
  }
297
286
  )
298
287
  ] }) });
299
- }, EMPTY_PATH = [], getStaticImageUrl = (value, apiKey) => {
288
+ }, EMPTY_PATH$1 = [], getStaticImageUrl$1 = (value, apiKey) => {
300
289
  const loc = `${value.lat},${value.lng}`;
301
290
  return `https://maps.googleapis.com/maps/api/staticmap?${new URLSearchParams({
302
291
  key: apiKey,
@@ -325,10 +314,7 @@ function GeopointInput(props) {
325
314
  onBlur: handleBlur,
326
315
  onFocus: handleFocus,
327
316
  "aria-describedby": ariaDescribedBy
328
- } = elementProps, schemaTypeName = schemaType.name, dialogId = useId(), dialogRef = useRef(null), handleFocusButton = useCallback(() => {
329
- var _a;
330
- return (_a = inputRef == null ? void 0 : inputRef.current) == null ? void 0 : _a.focus();
331
- }, [inputRef]), [modalOpen, setModalOpen] = useState(!1), handleCloseModal = useCallback(() => {
317
+ } = elementProps, schemaTypeName = schemaType.name, dialogId = useId(), dialogRef = useRef(null), handleFocusButton = useCallback(() => inputRef?.current?.focus(), [inputRef]), [modalOpen, setModalOpen] = useState(!1), handleCloseModal = useCallback(() => {
332
318
  dialogRef.current && dialogRef.current.blur(), setModalOpen(!1), handleFocusButton();
333
319
  }, [setModalOpen, handleFocusButton]), handleToggleModal = useCallback(
334
320
  () => setModalOpen((currentState) => !currentState),
@@ -346,7 +332,7 @@ function GeopointInput(props) {
346
332
  onChange(unset());
347
333
  }, [onChange]);
348
334
  return useEffect(() => {
349
- modalOpen && onPathFocus(EMPTY_PATH);
335
+ modalOpen && onPathFocus(EMPTY_PATH$1);
350
336
  }, [modalOpen, onPathFocus]), !config2 || !config2.apiKey ? /* @__PURE__ */ jsxs("div", { children: [
351
337
  /* @__PURE__ */ jsxs("p", { children: [
352
338
  "The ",
@@ -363,7 +349,7 @@ function GeopointInput(props) {
363
349
  value && /* @__PURE__ */ jsx(ChangeIndicator, { path, isChanged: changed, hasFocus: !!focused, children: /* @__PURE__ */ jsx(
364
350
  PreviewImage,
365
351
  {
366
- src: getStaticImageUrl(value, config2.apiKey),
352
+ src: getStaticImageUrl$1(value, config2.apiKey),
367
353
  alt: "Map location",
368
354
  onClick: handleFocusButton,
369
355
  onDoubleClick: handleToggleModal
@@ -421,11 +407,274 @@ function GeopointInput(props) {
421
407
  )
422
408
  ] });
423
409
  }
424
- var __defProp$1 = Object.defineProperty, __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __publicField = (obj, key, value) => __defNormalProp$1(obj, typeof key != "symbol" ? key + "" : key, value);
425
- class Arrow extends PureComponent {
426
- constructor() {
427
- super(...arguments), __publicField(this, "line"), __publicField(this, "eventHandlers", {});
410
+ const fallbackLatLng = { lat: 40.7058254, lng: -74.1180863 }, MarkerDragSync = ({ api, marker, circleRef, isMarkerDragging }) => (useEffect(() => {
411
+ const handleDrag = () => {
412
+ isMarkerDragging.current = !0;
413
+ }, handleDragEnd = () => {
414
+ isMarkerDragging.current = !1;
415
+ }, dragListener = api.event.addListener(marker, "drag", handleDrag), dragEndListener = api.event.addListener(marker, "dragend", handleDragEnd);
416
+ return () => {
417
+ api.event.removeListener(dragListener), api.event.removeListener(dragEndListener);
418
+ };
419
+ }, [api, marker, circleRef, isMarkerDragging]), null), GeopointRadiusSelect = ({
420
+ api,
421
+ value,
422
+ onChange,
423
+ defaultLocation = { lng: 10.74609, lat: 59.91273 },
424
+ defaultRadiusZoom = 12,
425
+ defaultRadius = 1e3
426
+ }) => {
427
+ const circleRef = useRef(null), markerRef = useRef(), isMarkerDragging = useRef(!1), getCenter2 = useCallback(() => ({ ...fallbackLatLng, ...defaultLocation, ...value }), [value, defaultLocation]), setValue = useCallback(
428
+ (geoPoint, radius) => {
429
+ if (onChange) {
430
+ const roundedRadius = radius ? Math.round(radius) : void 0;
431
+ onChange(geoPoint, roundedRadius);
432
+ }
433
+ },
434
+ [onChange]
435
+ ), handlePlaceChanged = useCallback(
436
+ (place) => {
437
+ place.geometry?.location && setValue(place.geometry.location, value?.radius || defaultRadius);
438
+ },
439
+ [setValue, value?.radius, defaultRadius]
440
+ ), handleMarkerDragEnd = useCallback(
441
+ (event) => {
442
+ event.latLng && (circleRef.current && circleRef.current.setCenter(event.latLng), setValue(event.latLng, value?.radius || defaultRadius));
443
+ },
444
+ [setValue, value?.radius, defaultRadius]
445
+ ), handleMapClick = useCallback(
446
+ (event) => {
447
+ event.latLng && setValue(event.latLng, value?.radius || defaultRadius);
448
+ },
449
+ [setValue, value?.radius, defaultRadius]
450
+ );
451
+ return useEffect(() => {
452
+ value && circleRef.current && (circleRef.current.setCenter({ lat: value.lat, lng: value.lng }), circleRef.current.setRadius(value.radius));
453
+ }, [value]), /* @__PURE__ */ jsx(
454
+ GoogleMap,
455
+ {
456
+ api,
457
+ location: getCenter2(),
458
+ onClick: handleMapClick,
459
+ defaultZoom: defaultRadiusZoom,
460
+ children: (map) => (value && !circleRef.current && (circleRef.current = new api.Circle({
461
+ map,
462
+ center: { lat: value.lat, lng: value.lng },
463
+ radius: value.radius,
464
+ fillColor: "#4285F4",
465
+ fillOpacity: 0.2,
466
+ strokeColor: "#4285F4",
467
+ strokeOpacity: 0.8,
468
+ strokeWeight: 2,
469
+ editable: !0
470
+ }), circleRef.current.addListener("center_changed", () => {
471
+ if (circleRef.current && markerRef.current && !isMarkerDragging.current) {
472
+ const circleCenter = circleRef.current.getCenter();
473
+ circleCenter && markerRef.current.setPosition(circleCenter);
474
+ }
475
+ }), circleRef.current.addListener("radius_changed", () => {
476
+ if (circleRef.current) {
477
+ const center = circleRef.current.getCenter(), radius = circleRef.current.getRadius();
478
+ center && setValue(center, Math.round(radius));
479
+ }
480
+ }), circleRef.current.addListener("dragend", () => {
481
+ if (circleRef.current) {
482
+ const center = circleRef.current.getCenter(), radius = circleRef.current.getRadius();
483
+ center && setValue(center, Math.round(radius));
484
+ }
485
+ })), /* @__PURE__ */ jsxs(Fragment, { children: [
486
+ /* @__PURE__ */ jsx(SearchInput, { api, map, onChange: handlePlaceChanged }),
487
+ value && /* @__PURE__ */ jsx(
488
+ Marker,
489
+ {
490
+ api,
491
+ map,
492
+ position: value,
493
+ onMove: onChange ? handleMarkerDragEnd : void 0,
494
+ markerRef
495
+ }
496
+ ),
497
+ value && markerRef.current && /* @__PURE__ */ jsx(
498
+ MarkerDragSync,
499
+ {
500
+ api,
501
+ marker: markerRef.current,
502
+ circleRef,
503
+ isMarkerDragging
504
+ }
505
+ )
506
+ ] }))
507
+ }
508
+ );
509
+ }, EMPTY_PATH = [], generateCirclePoints = (lat, lng, radius) => {
510
+ const points = [];
511
+ for (let i = 0; i <= 32; i++) {
512
+ const angle = i / 32 * 2 * Math.PI, latOffset = radius / 111e3 * Math.cos(angle), lngOffset = radius / (111e3 * Math.cos(lat * Math.PI / 180)) * Math.sin(angle);
513
+ points.push({
514
+ lat: lat + latOffset,
515
+ lng: lng + lngOffset
516
+ });
517
+ }
518
+ return points;
519
+ }, getStaticImageUrl = (value, apiKey) => {
520
+ const loc = `${value.lat},${value.lng}`;
521
+ let zoom = 13;
522
+ if (value.radius) {
523
+ const scale = (value.radius + value.radius / 2) / 500, calculatedZoom = 16 - Math.log(scale) / Math.log(2);
524
+ zoom = Math.max(8, Math.min(16, Math.round(calculatedZoom - 0.4)));
428
525
  }
526
+ const qs = new URLSearchParams({
527
+ key: apiKey,
528
+ center: loc,
529
+ markers: loc,
530
+ zoom: zoom.toString(),
531
+ scale: "2",
532
+ size: "640x300"
533
+ });
534
+ if (value.radius) {
535
+ const path = generateCirclePoints(value.lat, value.lng, value.radius).map((p) => `${p.lat},${p.lng}`).join("|");
536
+ qs.append("path", `fillcolor:0x4285F480|color:0x4285F4|weight:2|${path}`);
537
+ }
538
+ return `https://maps.googleapis.com/maps/api/staticmap?${qs.toString()}`;
539
+ };
540
+ function GeopointRadiusInput(props) {
541
+ const {
542
+ changed,
543
+ elementProps,
544
+ focused,
545
+ geoConfig: config2,
546
+ onChange,
547
+ onPathFocus,
548
+ path,
549
+ readOnly,
550
+ schemaType,
551
+ value
552
+ } = props, {
553
+ id,
554
+ ref: inputRef,
555
+ onBlur: handleBlur,
556
+ onFocus: handleFocus,
557
+ "aria-describedby": ariaDescribedBy
558
+ } = elementProps, schemaTypeName = schemaType.name, dialogId = useId(), dialogRef = useRef(null), handleFocusButton = useCallback(() => inputRef?.current?.focus(), [inputRef]), [modalOpen, setModalOpen] = useState(!1), handleCloseModal = useCallback(() => {
559
+ dialogRef.current && dialogRef.current.blur(), setModalOpen(!1), handleFocusButton();
560
+ }, [setModalOpen, handleFocusButton]), handleToggleModal = useCallback(
561
+ () => setModalOpen((currentState) => !currentState),
562
+ [setModalOpen]
563
+ ), handleChange = useCallback(
564
+ (latLng, radius) => {
565
+ const currentRadius = radius ?? value?.radius ?? config2.defaultRadius ?? 1e3;
566
+ onChange([
567
+ setIfMissing({ _type: schemaTypeName }),
568
+ set(latLng.lat(), ["lat"]),
569
+ set(latLng.lng(), ["lng"]),
570
+ set(currentRadius, ["radius"])
571
+ ]);
572
+ },
573
+ [schemaTypeName, onChange, value?.radius, config2.defaultRadius]
574
+ ), handleRadiusChange = useCallback(
575
+ (event) => {
576
+ value && onChange([set(Math.round(Number(event.currentTarget.value)), ["radius"])]);
577
+ },
578
+ [onChange, value]
579
+ ), handleClear = useCallback(() => {
580
+ onChange(unset());
581
+ }, [onChange]);
582
+ return useEffect(() => {
583
+ modalOpen && onPathFocus(EMPTY_PATH);
584
+ }, [modalOpen, onPathFocus]), !config2 || !config2.apiKey ? /* @__PURE__ */ jsxs("div", { children: [
585
+ /* @__PURE__ */ jsxs("p", { children: [
586
+ "The ",
587
+ /* @__PURE__ */ jsx("a", { href: "https://sanity.io/docs/schema-types/geopoint-type", children: "Geopoint Radius type" }),
588
+ " ",
589
+ "needs a Google Maps API key with access to:"
590
+ ] }),
591
+ /* @__PURE__ */ jsxs("ul", { children: [
592
+ /* @__PURE__ */ jsx("li", { children: "Google Maps JavaScript API" }),
593
+ /* @__PURE__ */ jsx("li", { children: "Google Places API Web Service" }),
594
+ /* @__PURE__ */ jsx("li", { children: "Google Static Maps API" })
595
+ ] }),
596
+ /* @__PURE__ */ jsx("p", { children: "Please enter the API key with access to these services in your googleMapsInput plugin config." })
597
+ ] }) : /* @__PURE__ */ jsxs(Stack, { space: 3, children: [
598
+ value && /* @__PURE__ */ jsx(ChangeIndicator, { path, isChanged: changed, hasFocus: !!focused, children: /* @__PURE__ */ jsx(
599
+ PreviewImage,
600
+ {
601
+ src: getStaticImageUrl(value, config2.apiKey),
602
+ alt: "Map location with radius",
603
+ onClick: handleFocusButton,
604
+ onDoubleClick: handleToggleModal
605
+ }
606
+ ) }),
607
+ value && /* @__PURE__ */ jsxs(Stack, { space: 2, children: [
608
+ /* @__PURE__ */ jsx(Label, { children: "Radius (meters)" }),
609
+ /* @__PURE__ */ jsx(
610
+ TextInput,
611
+ {
612
+ type: "number",
613
+ value: Math.round(value.radius || config2.defaultRadius || 1e3),
614
+ onChange: handleRadiusChange,
615
+ disabled: readOnly,
616
+ min: 1,
617
+ max: 5e4,
618
+ step: 1
619
+ }
620
+ )
621
+ ] }),
622
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Grid, { columns: value ? 2 : 1, gap: 3, children: [
623
+ /* @__PURE__ */ jsx(
624
+ Button,
625
+ {
626
+ "aria-describedby": ariaDescribedBy,
627
+ disabled: readOnly,
628
+ icon: value && EditIcon,
629
+ id,
630
+ mode: "ghost",
631
+ onClick: handleToggleModal,
632
+ onFocus: handleFocus,
633
+ padding: 3,
634
+ ref: inputRef,
635
+ text: value ? "Edit" : "Set location and radius"
636
+ }
637
+ ),
638
+ value && /* @__PURE__ */ jsx(
639
+ Button,
640
+ {
641
+ disabled: readOnly,
642
+ icon: TrashIcon,
643
+ mode: "ghost",
644
+ onClick: handleClear,
645
+ padding: 3,
646
+ text: "Remove",
647
+ tone: "critical"
648
+ }
649
+ )
650
+ ] }) }),
651
+ modalOpen && /* @__PURE__ */ jsx(
652
+ Dialog,
653
+ {
654
+ header: "Place the marker and set radius on the map",
655
+ id: `${dialogId}_dialog`,
656
+ onBlur: handleBlur,
657
+ onClose: handleCloseModal,
658
+ ref: dialogRef,
659
+ width: 1,
660
+ children: /* @__PURE__ */ jsx(DialogInnerContainer, { children: /* @__PURE__ */ jsx(GoogleMapsLoadProxy, { config: getGeoConfig(), children: (api) => /* @__PURE__ */ jsx(
661
+ GeopointRadiusSelect,
662
+ {
663
+ api,
664
+ value: value || void 0,
665
+ onChange: readOnly ? void 0 : handleChange,
666
+ defaultLocation: config2.defaultLocation,
667
+ defaultRadiusZoom: config2.defaultRadiusZoom,
668
+ defaultRadius: config2.defaultRadius
669
+ }
670
+ ) }) })
671
+ }
672
+ )
673
+ ] });
674
+ }
675
+ class Arrow extends PureComponent {
676
+ line;
677
+ eventHandlers = {};
429
678
  componentDidMount() {
430
679
  const { from, to, api, map, zIndex, onClick, color, arrowRef } = this.props, lineSymbol = {
431
680
  path: api.SymbolPath.FORWARD_OPEN_ARROW
@@ -508,7 +757,7 @@ function GeopointDiff$1({ api, diff }) {
508
757
  const fromValue = (diff.fromValue || []).filter(hasCoordinates), toValue = (diff.toValue || []).filter(hasCoordinates);
509
758
  if (fromValue.length === 0 && toValue.length === 0)
510
759
  return null;
511
- const bounds = getBounds$1(fromValue, toValue, api);
760
+ const bounds = getBounds$2(fromValue, toValue, api);
512
761
  return /* @__PURE__ */ jsx(
513
762
  GoogleMap,
514
763
  {
@@ -536,7 +785,7 @@ function isChangeDiff(diff) {
536
785
  function hasCoordinates(point) {
537
786
  return typeof point.lat == "number" && typeof point.lng == "number";
538
787
  }
539
- function getBounds$1(fromValue, toValue, api) {
788
+ function getBounds$2(fromValue, toValue, api) {
540
789
  const bounds = new api.LatLngBounds();
541
790
  return [...fromValue || [], ...toValue || []].forEach((point) => bounds.extend(point)), bounds;
542
791
  }
@@ -545,8 +794,8 @@ const GeopointFieldDiff = ({
545
794
  schemaType
546
795
  }) => /* @__PURE__ */ jsx(RootContainer, { children: /* @__PURE__ */ jsx(GoogleMapsLoadProxy, { config: getGeoConfig(), children: (api) => /* @__PURE__ */ jsx(GeopointDiff, { api, diff, schemaType }) }) });
547
796
  function GeopointDiff({ api, diff }) {
548
- const { fromValue, toValue } = diff, annotation = getAnnotationAtPath(diff, ["lat"]) || getAnnotationAtPath(diff, ["lng"]) || getAnnotationAtPath(diff, []), center = getCenter(diff, api), bounds = fromValue && toValue ? getBounds(fromValue, toValue, api) : void 0;
549
- return /* @__PURE__ */ jsx(DiffTooltip, { annotations: annotation ? [annotation] : [], description: getAction(diff), children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
797
+ const { fromValue, toValue } = diff, annotation = getAnnotationAtPath(diff, ["lat"]) || getAnnotationAtPath(diff, ["lng"]) || getAnnotationAtPath(diff, []), center = getCenter$1(diff, api), bounds = fromValue && toValue ? getBounds$1(fromValue, toValue, api) : void 0;
798
+ return /* @__PURE__ */ jsx(DiffTooltip, { annotations: annotation ? [annotation] : [], description: getAction$1(diff), children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
550
799
  GoogleMap,
551
800
  {
552
801
  api,
@@ -559,9 +808,117 @@ function GeopointDiff({ api, diff }) {
559
808
  }
560
809
  ) }) });
561
810
  }
562
- function getBounds(fromValue, toValue, api) {
811
+ function getBounds$1(fromValue, toValue, api) {
563
812
  return new api.LatLngBounds().extend(fromValue).extend(toValue);
564
813
  }
814
+ function getCenter$1(diff, api) {
815
+ const { fromValue, toValue } = diff;
816
+ if (fromValue && toValue)
817
+ return getBounds$1(fromValue, toValue, api).getCenter().toJSON();
818
+ if (fromValue)
819
+ return fromValue;
820
+ if (toValue)
821
+ return toValue;
822
+ throw new Error("Neither a from or a to value present");
823
+ }
824
+ function getAction$1(diff) {
825
+ const { fromValue, toValue } = diff;
826
+ return fromValue && toValue ? "Moved" : fromValue ? "Removed" : toValue ? "Added" : "Unchanged";
827
+ }
828
+ function GeopointRadiusMove({ diff, api, map, label }) {
829
+ const { fromValue: from, toValue: to } = diff, annotation = diff.isChanged ? diff.annotation : void 0, userColor = useUserColor(annotation ? annotation.author : null) || void 0, fromRef = useRef(), toRef = useRef(), fromCircleRef = useRef(), toCircleRef = useRef();
830
+ return useEffect(() => {
831
+ const color = userColor?.background || "#4285F4";
832
+ return from && from.radius && (fromCircleRef.current = new api.Circle({
833
+ map,
834
+ center: { lat: from.lat, lng: from.lng },
835
+ radius: from.radius,
836
+ fillColor: color,
837
+ fillOpacity: 0.1,
838
+ strokeColor: color,
839
+ strokeOpacity: 0.3,
840
+ strokeWeight: 1,
841
+ zIndex: 0
842
+ })), to && to.radius && (toCircleRef.current = new api.Circle({
843
+ map,
844
+ center: { lat: to.lat, lng: to.lng },
845
+ radius: to.radius,
846
+ fillColor: color,
847
+ fillOpacity: 0.2,
848
+ strokeColor: color,
849
+ strokeOpacity: 0.8,
850
+ strokeWeight: 2,
851
+ zIndex: 2
852
+ })), () => {
853
+ fromCircleRef.current && fromCircleRef.current.setMap(null), toCircleRef.current && toCircleRef.current.setMap(null);
854
+ };
855
+ }, [api, map, from, to, userColor]), /* @__PURE__ */ jsxs(Fragment, { children: [
856
+ from && /* @__PURE__ */ jsx(
857
+ Marker,
858
+ {
859
+ api,
860
+ map,
861
+ position: from,
862
+ zIndex: 0,
863
+ opacity: 0.55,
864
+ markerRef: fromRef,
865
+ color: userColor
866
+ }
867
+ ),
868
+ from && to && /* @__PURE__ */ jsx(Arrow, { api, map, from, to, zIndex: 1, color: userColor }),
869
+ to && /* @__PURE__ */ jsx(
870
+ Marker,
871
+ {
872
+ api,
873
+ map,
874
+ position: to,
875
+ zIndex: 2,
876
+ markerRef: toRef,
877
+ label,
878
+ color: userColor
879
+ }
880
+ )
881
+ ] });
882
+ }
883
+ const GeopointRadiusFieldDiff = ({
884
+ diff,
885
+ schemaType
886
+ }) => /* @__PURE__ */ jsx(RootContainer, { children: /* @__PURE__ */ jsx(GoogleMapsLoadProxy, { config: getGeoConfig(), children: (api) => /* @__PURE__ */ jsx(GeopointRadiusDiff, { api, diff, schemaType }) }) });
887
+ function GeopointRadiusDiff({ api, diff }) {
888
+ const { fromValue, toValue } = diff, annotation = getAnnotationAtPath(diff, ["lat"]) || getAnnotationAtPath(diff, ["lng"]) || getAnnotationAtPath(diff, ["radius"]) || getAnnotationAtPath(diff, []), center = getCenter(diff, api), bounds = fromValue && toValue ? getBounds(fromValue, toValue, api) : void 0;
889
+ return /* @__PURE__ */ jsx(DiffTooltip, { annotations: annotation ? [annotation] : [], description: getAction(diff), children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
890
+ GoogleMap,
891
+ {
892
+ api,
893
+ location: center,
894
+ mapTypeControl: !1,
895
+ controlSize: 20,
896
+ bounds,
897
+ scrollWheel: !1,
898
+ children: (map) => /* @__PURE__ */ jsx(GeopointRadiusMove, { api, map, diff })
899
+ }
900
+ ) }) });
901
+ }
902
+ function getBounds(fromValue, toValue, api) {
903
+ const bounds = new api.LatLngBounds().extend(fromValue).extend(toValue), fromRadius = fromValue.radius || 0, toRadius = toValue.radius || 0, maxRadius = Math.max(fromRadius, toRadius);
904
+ if (maxRadius > 0) {
905
+ const radiusInDegrees = maxRadius / 111e3;
906
+ bounds.extend({
907
+ lat: fromValue.lat + radiusInDegrees,
908
+ lng: fromValue.lng + radiusInDegrees
909
+ }), bounds.extend({
910
+ lat: fromValue.lat - radiusInDegrees,
911
+ lng: fromValue.lng - radiusInDegrees
912
+ }), bounds.extend({
913
+ lat: toValue.lat + radiusInDegrees,
914
+ lng: toValue.lng + radiusInDegrees
915
+ }), bounds.extend({
916
+ lat: toValue.lat - radiusInDegrees,
917
+ lng: toValue.lng - radiusInDegrees
918
+ });
919
+ }
920
+ return bounds;
921
+ }
565
922
  function getCenter(diff, api) {
566
923
  const { fromValue, toValue } = diff;
567
924
  if (fromValue && toValue)
@@ -574,22 +931,70 @@ function getCenter(diff, api) {
574
931
  }
575
932
  function getAction(diff) {
576
933
  const { fromValue, toValue } = diff;
577
- return fromValue && toValue ? "Moved" : fromValue ? "Removed" : toValue ? "Added" : "Unchanged";
934
+ if (fromValue && toValue) {
935
+ const latChanged = fromValue.lat !== toValue.lat || fromValue.lng !== toValue.lng, radiusChanged = fromValue.radius !== toValue.radius;
936
+ return latChanged && radiusChanged ? "Moved and radius changed" : latChanged ? "Moved" : radiusChanged ? "Radius changed" : "Unchanged";
937
+ } else {
938
+ if (fromValue)
939
+ return "Removed";
940
+ if (toValue)
941
+ return "Added";
942
+ }
943
+ return "Unchanged";
578
944
  }
579
- var __defProp = Object.defineProperty, __defProps = Object.defineProperties, __getOwnPropDescs = Object.getOwnPropertyDescriptors, __getOwnPropSymbols = Object.getOwnPropertySymbols, __hasOwnProp = Object.prototype.hasOwnProperty, __propIsEnum = Object.prototype.propertyIsEnumerable, __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value, __spreadValues = (a, b) => {
580
- for (var prop in b || (b = {}))
581
- __hasOwnProp.call(b, prop) && __defNormalProp(a, prop, b[prop]);
582
- if (__getOwnPropSymbols)
583
- for (var prop of __getOwnPropSymbols(b))
584
- __propIsEnum.call(b, prop) && __defNormalProp(a, prop, b[prop]);
585
- return a;
586
- }, __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
587
945
  const googleMapsInput = definePlugin((config2) => (setGeoConfig(config2), {
588
946
  name: "google-maps-input",
947
+ schema: {
948
+ types: [
949
+ {
950
+ name: "geopointRadius",
951
+ title: "Geopoint with Radius",
952
+ type: "object",
953
+ fields: [
954
+ {
955
+ name: "lat",
956
+ title: "Latitude",
957
+ type: "number",
958
+ validation: (Rule) => Rule.required().min(-90).max(90)
959
+ },
960
+ {
961
+ name: "lng",
962
+ title: "Longitude",
963
+ type: "number",
964
+ validation: (Rule) => Rule.required().min(-180).max(180)
965
+ },
966
+ {
967
+ name: "alt",
968
+ title: "Altitude",
969
+ type: "number"
970
+ },
971
+ {
972
+ name: "radius",
973
+ title: "Radius (meters)",
974
+ type: "number",
975
+ validation: (Rule) => Rule.required().min(1).max(5e4)
976
+ }
977
+ ],
978
+ preview: {
979
+ select: {
980
+ lat: "lat",
981
+ lng: "lng",
982
+ radius: "radius"
983
+ },
984
+ prepare({ lat, lng, radius }) {
985
+ return {
986
+ title: `${lat.toFixed(6)}, ${lng.toFixed(6)}`,
987
+ subtitle: radius ? `Radius: ${radius}m` : "No radius set"
988
+ };
989
+ }
990
+ }
991
+ }
992
+ ]
993
+ },
589
994
  form: {
590
995
  components: {
591
996
  input(props) {
592
- return isGeopoint(props.schemaType) ? /* @__PURE__ */ jsx(GeopointInput, __spreadProps(__spreadValues({}, props), { geoConfig: config2 })) : props.renderDefault(props);
997
+ return isGeopoint(props.schemaType) ? /* @__PURE__ */ jsx(GeopointInput, { ...props, geoConfig: config2 }) : isGeopointRadius(props.schemaType) ? /* @__PURE__ */ jsx(GeopointRadiusInput, { ...props, geoConfig: config2 }) : props.renderDefault(props);
593
998
  }
594
999
  }
595
1000
  }
@@ -597,13 +1002,18 @@ const googleMapsInput = definePlugin((config2) => (setGeoConfig(config2), {
597
1002
  function isGeopoint(schemaType) {
598
1003
  return isType("geopoint", schemaType);
599
1004
  }
1005
+ function isGeopointRadius(schemaType) {
1006
+ return isType("geopointRadius", schemaType);
1007
+ }
600
1008
  function isType(name, schema) {
601
- return (schema == null ? void 0 : schema.name) === name ? !0 : schema != null && schema.name ? isType(name, schema == null ? void 0 : schema.type) : !1;
1009
+ return schema?.name === name ? !0 : schema?.name ? isType(name, schema?.type) : !1;
602
1010
  }
603
1011
  export {
604
1012
  GeopointArrayDiff,
605
1013
  GeopointFieldDiff,
606
1014
  GeopointInput,
1015
+ GeopointRadiusFieldDiff,
1016
+ GeopointRadiusInput,
607
1017
  googleMapsInput
608
1018
  };
609
1019
  //# sourceMappingURL=index.js.map