strapi-plugin-map-box 0.0.2 → 0.0.4

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.
@@ -38,56 +38,298 @@ const ControlsContainer = styled__default.default.div`
38
38
  position: absolute;
39
39
  top: 1rem;
40
40
  left: 1rem;
41
- z-index: 1;
42
- width: 300px;
41
+ right: 1rem;
42
+ z-index: 10;
43
43
  `;
44
- const ControlsWrapper = styled__default.default.div`
44
+ const SearchRow = styled__default.default.div`
45
45
  display: flex;
46
- gap: 0.5rem;
46
+ align-items: flex-start;
47
+ gap: 8px;
47
48
  `;
48
- const SearchInput = styled__default.default.input`
49
+ const SearchWrapper = styled__default.default.div`
50
+ position: relative;
49
51
  flex: 1;
50
- padding: 0.5rem;
52
+ max-width: 350px;
53
+ `;
54
+ const SearchInputContainer = styled__default.default.div`
55
+ display: flex;
56
+ align-items: center;
57
+ background: white;
51
58
  border: 1px solid #dcdce4;
52
- border-radius: 4px;
59
+ border-radius: 8px;
60
+ overflow: hidden;
61
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
62
+
63
+ &:focus-within {
64
+ border-color: #4945ff;
65
+ box-shadow: 0 0 0 2px rgba(73, 69, 255, 0.2);
66
+ }
67
+ `;
68
+ const SearchIcon = styled__default.default.div`
69
+ padding: 0 12px;
70
+ color: #8e8e93;
71
+ display: flex;
72
+ align-items: center;
73
+ `;
74
+ const SearchInput = styled__default.default.input`
75
+ flex: 1;
76
+ padding: 12px 0;
77
+ border: none;
53
78
  font-size: 14px;
79
+ outline: none;
80
+ background: transparent;
81
+
82
+ &::placeholder {
83
+ color: #8e8e93;
84
+ }
54
85
  `;
55
- const SearchButton = styled__default.default.button`
56
- padding: 0.5rem 1rem;
57
- background-color: #4945ff;
58
- color: white;
86
+ const ClearButton = styled__default.default.button`
87
+ padding: 8px 12px;
88
+ background: none;
59
89
  border: none;
60
- border-radius: 4px;
61
90
  cursor: pointer;
62
- font-size: 14px;
91
+ color: #8e8e93;
92
+ display: flex;
93
+ align-items: center;
63
94
 
64
95
  &:hover {
96
+ color: #666;
97
+ }
98
+ `;
99
+ const LoadingSpinner = styled__default.default.div`
100
+ padding: 8px 12px;
101
+ color: #4945ff;
102
+
103
+ @keyframes spin {
104
+ to {
105
+ transform: rotate(360deg);
106
+ }
107
+ }
108
+
109
+ svg {
110
+ animation: spin 1s linear infinite;
111
+ }
112
+ `;
113
+ const RefreshButton = styled__default.default.button`
114
+ width: 44px;
115
+ height: 44px;
116
+ border-radius: 8px;
117
+ background-color: ${(props) => props.$isRefreshing ? "#6c63ff" : "#4945ff"};
118
+ border: none;
119
+ cursor: pointer;
120
+ display: flex;
121
+ align-items: center;
122
+ justify-content: center;
123
+ color: white;
124
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
125
+ transition: all 0.15s ease;
126
+ flex-shrink: 0;
127
+
128
+ &:hover:not(:disabled) {
65
129
  background-color: #3832e0;
66
130
  }
131
+
132
+ &:active:not(:disabled) {
133
+ transform: scale(0.95);
134
+ }
135
+
136
+ &:disabled {
137
+ cursor: not-allowed;
138
+ }
139
+
140
+ @keyframes spin {
141
+ to {
142
+ transform: rotate(360deg);
143
+ }
144
+ }
145
+
146
+ svg.spinning {
147
+ animation: spin 1s linear infinite;
148
+ }
67
149
  `;
150
+ const ResultsDropdown = styled__default.default.div`
151
+ position: absolute;
152
+ top: calc(100% + 4px);
153
+ left: 0;
154
+ right: 0;
155
+ background: white;
156
+ border: 1px solid #dcdce4;
157
+ border-radius: 8px;
158
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
159
+ max-height: 300px;
160
+ overflow-y: auto;
161
+ `;
162
+ const ResultItem = styled__default.default.button`
163
+ width: 100%;
164
+ padding: 12px;
165
+ display: flex;
166
+ align-items: flex-start;
167
+ gap: 12px;
168
+ background: none;
169
+ border: none;
170
+ border-bottom: 1px solid #f0f0f0;
171
+ cursor: pointer;
172
+ text-align: left;
173
+ transition: background-color 0.15s;
174
+
175
+ &:last-child {
176
+ border-bottom: none;
177
+ }
178
+
179
+ &:hover {
180
+ background-color: #f6f6f9;
181
+ }
182
+ `;
183
+ const ResultIcon = styled__default.default.div`
184
+ width: 32px;
185
+ height: 32px;
186
+ border-radius: 6px;
187
+ background-color: rgba(73, 69, 255, 0.1);
188
+ display: flex;
189
+ align-items: center;
190
+ justify-content: center;
191
+ flex-shrink: 0;
192
+ color: #4945ff;
193
+ `;
194
+ const ResultTextContainer = styled__default.default.div`
195
+ flex: 1;
196
+ min-width: 0;
197
+ `;
198
+ const ResultTitle = styled__default.default.div`
199
+ font-size: 14px;
200
+ font-weight: 500;
201
+ color: #32324d;
202
+ white-space: nowrap;
203
+ overflow: hidden;
204
+ text-overflow: ellipsis;
205
+ `;
206
+ const ResultSubtitle = styled__default.default.div`
207
+ font-size: 12px;
208
+ color: #8e8e93;
209
+ white-space: nowrap;
210
+ overflow: hidden;
211
+ text-overflow: ellipsis;
212
+ margin-top: 2px;
213
+ `;
214
+ const NoResults = styled__default.default.div`
215
+ padding: 16px;
216
+ text-align: center;
217
+ color: #8e8e93;
218
+ font-size: 14px;
219
+ `;
220
+ const getPlaceIcon = (placeType) => {
221
+ if (placeType.includes("poi")) {
222
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" }) });
223
+ }
224
+ if (placeType.includes("address")) {
225
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" }) });
226
+ }
227
+ if (placeType.includes("place") || placeType.includes("locality")) {
228
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z" }) });
229
+ }
230
+ if (placeType.includes("region") || placeType.includes("country")) {
231
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z" }) });
232
+ }
233
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" }) });
234
+ };
68
235
  const MapSearch = ({
69
- onSearch,
70
236
  searchQuery,
71
237
  setSearchQuery,
72
- handleKeyDown
238
+ searchResults,
239
+ isSearching,
240
+ onSelectResult,
241
+ onClear,
242
+ showResults,
243
+ setShowResults,
244
+ onRefresh,
245
+ isRefreshing = false
73
246
  }) => {
74
- return /* @__PURE__ */ jsxRuntime.jsx(ControlsContainer, { children: /* @__PURE__ */ jsxRuntime.jsxs(ControlsWrapper, { children: [
75
- /* @__PURE__ */ jsxRuntime.jsx(
76
- SearchInput,
77
- {
78
- type: "text",
79
- value: searchQuery,
80
- onChange: (e) => setSearchQuery(e.target.value),
81
- onKeyDown: handleKeyDown,
82
- placeholder: "Search for a location..."
83
- }
84
- ),
85
- /* @__PURE__ */ jsxRuntime.jsx(
86
- SearchButton,
247
+ const handleInputChange = (e) => {
248
+ setSearchQuery(e.target.value);
249
+ setShowResults(true);
250
+ };
251
+ const handleResultClick = (result) => {
252
+ onSelectResult(result);
253
+ setShowResults(false);
254
+ };
255
+ const handleClear = () => {
256
+ onClear();
257
+ setShowResults(false);
258
+ };
259
+ return /* @__PURE__ */ jsxRuntime.jsx(ControlsContainer, { children: /* @__PURE__ */ jsxRuntime.jsxs(SearchRow, { children: [
260
+ /* @__PURE__ */ jsxRuntime.jsxs(SearchWrapper, { children: [
261
+ /* @__PURE__ */ jsxRuntime.jsxs(SearchInputContainer, { children: [
262
+ /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" }) }) }),
263
+ /* @__PURE__ */ jsxRuntime.jsx(
264
+ SearchInput,
265
+ {
266
+ type: "text",
267
+ value: searchQuery,
268
+ onChange: handleInputChange,
269
+ onFocus: () => setShowResults(true),
270
+ placeholder: "Search for a location..."
271
+ }
272
+ ),
273
+ isSearching && /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 4V2A10 10 0 0 0 2 12h2a8 8 0 0 1 8-8z" }) }) }),
274
+ searchQuery && !isSearching && /* @__PURE__ */ jsxRuntime.jsx(ClearButton, { onClick: handleClear, type: "button", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) }) })
275
+ ] }),
276
+ showResults && searchQuery.length > 2 && /* @__PURE__ */ jsxRuntime.jsx(ResultsDropdown, { children: searchResults.length > 0 ? searchResults.map((result) => {
277
+ const [title, ...rest] = result.place_name.split(",");
278
+ const subtitle = rest.join(",").trim();
279
+ return /* @__PURE__ */ jsxRuntime.jsxs(
280
+ ResultItem,
281
+ {
282
+ onClick: () => handleResultClick(result),
283
+ type: "button",
284
+ children: [
285
+ /* @__PURE__ */ jsxRuntime.jsx(ResultIcon, { children: getPlaceIcon(result.place_type) }),
286
+ /* @__PURE__ */ jsxRuntime.jsxs(ResultTextContainer, { children: [
287
+ /* @__PURE__ */ jsxRuntime.jsx(ResultTitle, { children: title }),
288
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(ResultSubtitle, { children: subtitle })
289
+ ] })
290
+ ]
291
+ },
292
+ result.id
293
+ );
294
+ }) : !isSearching ? /* @__PURE__ */ jsxRuntime.jsx(NoResults, { children: "No results found" }) : null })
295
+ ] }),
296
+ onRefresh && /* @__PURE__ */ jsxRuntime.jsx(
297
+ RefreshButton,
87
298
  {
299
+ onClick: onRefresh,
300
+ disabled: isRefreshing,
301
+ $isRefreshing: isRefreshing,
88
302
  type: "button",
89
- onClick: onSearch,
90
- children: "Search"
303
+ title: "Refresh to original location",
304
+ children: isRefreshing ? /* @__PURE__ */ jsxRuntime.jsx(
305
+ "svg",
306
+ {
307
+ className: "spinning",
308
+ width: "18",
309
+ height: "18",
310
+ viewBox: "0 0 24 24",
311
+ fill: "currentColor",
312
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 4V2A10 10 0 0 0 2 12h2a8 8 0 0 1 8-8z" })
313
+ }
314
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
315
+ "svg",
316
+ {
317
+ width: "18",
318
+ height: "18",
319
+ viewBox: "0 0 24 24",
320
+ fill: "none",
321
+ stroke: "currentColor",
322
+ strokeWidth: "2",
323
+ strokeLinecap: "round",
324
+ strokeLinejoin: "round",
325
+ children: [
326
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 12a9 9 0 0 0-9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" }),
327
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 3v5h5" }),
328
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 12a9 9 0 0 0 9 9 9.75 9.75 0 0 0 6.74-2.74L21 16" }),
329
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 21h5v-5" })
330
+ ]
331
+ }
332
+ )
91
333
  }
92
334
  )
93
335
  ] }) });
@@ -223,54 +465,125 @@ function MapBoxField({ name, onChange, value, intlLabel, required }) {
223
465
  const { viewState, markerPosition, setViewState, setMarkerPosition } = useMapLocationHook(value);
224
466
  const { accessToken, debugMode } = config || {};
225
467
  const [searchQuery, setSearchQuery] = react.useState("");
226
- const [searchResults, setSearchResults] = react.useState(null);
468
+ const [searchResults, setSearchResults] = react.useState([]);
469
+ const [isSearching, setIsSearching] = react.useState(false);
470
+ const [showResults, setShowResults] = react.useState(false);
227
471
  const [searchError, setSearchError] = react.useState(null);
228
- const updateMarkerPosition = (lng, lat, address) => {
229
- setMarkerPosition({ longitude: lng, latitude: lat });
230
- const newValue = {
231
- longitude: lng,
232
- latitude: lat,
233
- address: address || "Selected location",
234
- zoom: viewState.zoom,
235
- pitch: viewState.pitch,
236
- bearing: viewState.bearing
237
- };
238
- onChange({ target: { name, value: newValue, type: "json" } });
239
- };
240
- const handleSearch = async () => {
241
- if (!searchQuery.trim()) return;
242
- try {
243
- setSearchError(null);
244
- const encodedQuery = encodeURIComponent(searchQuery.trim());
245
- const url = `/map-box/location-search/${encodedQuery}`;
246
- const { data } = await get(url);
247
- setSearchResults(data);
248
- if (data.features && data.features[0]) {
249
- const [longitude, latitude] = data.features[0].center;
250
- setViewState((prev) => ({
251
- ...prev,
252
- longitude,
253
- latitude,
254
- zoom: 14,
255
- transitionDuration: 1e3
256
- }));
257
- updateMarkerPosition(longitude, latitude, data.features[0].place_name);
258
- } else if (data.error) {
259
- setSearchError(data.error);
260
- } else {
261
- setSearchError("No results found");
262
- }
263
- } catch (error2) {
264
- console.error("Error searching location:", error2);
265
- setSearchError(error2 instanceof Error ? error2.message : "An error occurred");
472
+ const [isRefreshing, setIsRefreshing] = react.useState(false);
473
+ const searchTimeoutRef = react.useRef(null);
474
+ const initialValueRef = react.useRef(null);
475
+ react.useEffect(() => {
476
+ if (value && initialValueRef.current === null) {
477
+ initialValueRef.current = { ...value };
266
478
  }
267
- };
268
- const handleKeyDown = (e) => {
269
- if (e.key === "Enter") {
270
- e.preventDefault();
271
- handleSearch();
479
+ }, [value]);
480
+ const updateMarkerPosition = react.useCallback(
481
+ (lng, lat, address) => {
482
+ setMarkerPosition({ longitude: lng, latitude: lat });
483
+ const newValue = {
484
+ longitude: lng,
485
+ latitude: lat,
486
+ address: address || "Selected location",
487
+ zoom: viewState.zoom,
488
+ pitch: viewState.pitch,
489
+ bearing: viewState.bearing
490
+ };
491
+ onChange({ target: { name, value: newValue, type: "json" } });
492
+ },
493
+ [name, onChange, setMarkerPosition, viewState.zoom, viewState.pitch, viewState.bearing]
494
+ );
495
+ react.useEffect(() => {
496
+ if (searchTimeoutRef.current) {
497
+ clearTimeout(searchTimeoutRef.current);
272
498
  }
273
- };
499
+ if (searchQuery.trim().length <= 2) {
500
+ setSearchResults([]);
501
+ setIsSearching(false);
502
+ return;
503
+ }
504
+ setIsSearching(true);
505
+ searchTimeoutRef.current = setTimeout(async () => {
506
+ try {
507
+ setSearchError(null);
508
+ const encodedQuery = encodeURIComponent(searchQuery.trim());
509
+ const url = `/map-box/location-search/${encodedQuery}`;
510
+ const { data } = await get(url);
511
+ if (data.features) {
512
+ setSearchResults(
513
+ data.features.slice(0, 5).map((feature) => ({
514
+ id: feature.id,
515
+ place_name: feature.place_name,
516
+ center: feature.center,
517
+ place_type: feature.place_type
518
+ }))
519
+ );
520
+ } else if (data.error) {
521
+ setSearchError(data.error);
522
+ setSearchResults([]);
523
+ } else {
524
+ setSearchResults([]);
525
+ }
526
+ } catch (error2) {
527
+ console.error("Error searching location:", error2);
528
+ setSearchError(error2 instanceof Error ? error2.message : "An error occurred");
529
+ setSearchResults([]);
530
+ } finally {
531
+ setIsSearching(false);
532
+ }
533
+ }, 300);
534
+ return () => {
535
+ if (searchTimeoutRef.current) {
536
+ clearTimeout(searchTimeoutRef.current);
537
+ }
538
+ };
539
+ }, [searchQuery, get]);
540
+ const handleSelectResult = react.useCallback(
541
+ (result) => {
542
+ const [longitude, latitude] = result.center;
543
+ setViewState((prev) => ({
544
+ ...prev,
545
+ longitude,
546
+ latitude,
547
+ zoom: 14,
548
+ transitionDuration: 1e3
549
+ }));
550
+ updateMarkerPosition(longitude, latitude, result.place_name);
551
+ setSearchQuery(result.place_name.split(",")[0]);
552
+ setSearchResults([]);
553
+ setShowResults(false);
554
+ },
555
+ [setViewState, updateMarkerPosition]
556
+ );
557
+ const handleClearSearch = react.useCallback(() => {
558
+ setSearchQuery("");
559
+ setSearchResults([]);
560
+ setShowResults(false);
561
+ }, []);
562
+ const handleRefresh = react.useCallback(() => {
563
+ setIsRefreshing(true);
564
+ const originalValue = initialValueRef.current;
565
+ if (originalValue) {
566
+ setViewState((prev) => ({
567
+ ...prev,
568
+ longitude: originalValue.longitude,
569
+ latitude: originalValue.latitude,
570
+ zoom: originalValue.zoom || 12,
571
+ pitch: originalValue.pitch || 0,
572
+ bearing: originalValue.bearing || 0
573
+ }));
574
+ setMarkerPosition({
575
+ longitude: originalValue.longitude,
576
+ latitude: originalValue.latitude
577
+ });
578
+ onChange({ target: { name, value: originalValue, type: "json" } });
579
+ }
580
+ setSearchQuery("");
581
+ setSearchResults([]);
582
+ setShowResults(false);
583
+ setTimeout(() => {
584
+ setIsRefreshing(false);
585
+ }, 500);
586
+ }, [name, onChange, setViewState, setMarkerPosition]);
274
587
  const handleMapClick = (event) => {
275
588
  const { lngLat } = event;
276
589
  updateMarkerPosition(lngLat.lng, lngLat.lat);
@@ -278,6 +591,18 @@ function MapBoxField({ name, onChange, value, intlLabel, required }) {
278
591
  const handleMapMove = (evt) => {
279
592
  setViewState(evt.viewState);
280
593
  };
594
+ const handleMapMoveEnd = (evt) => {
595
+ const { longitude, latitude, zoom, pitch, bearing } = evt.viewState;
596
+ const newValue = {
597
+ longitude: markerPosition.longitude,
598
+ latitude: markerPosition.latitude,
599
+ address: value?.address || "Selected location",
600
+ zoom,
601
+ pitch,
602
+ bearing
603
+ };
604
+ onChange({ target: { name, value: newValue, type: "json" } });
605
+ };
281
606
  const handleMarkerDragEnd = (event) => {
282
607
  const { lngLat } = event;
283
608
  updateMarkerPosition(lngLat.lng, lngLat.lat);
@@ -324,10 +649,16 @@ function MapBoxField({ name, onChange, value, intlLabel, required }) {
324
649
  /* @__PURE__ */ jsxRuntime.jsx(
325
650
  MapSearch,
326
651
  {
327
- onSearch: handleSearch,
328
652
  searchQuery,
329
653
  setSearchQuery,
330
- handleKeyDown
654
+ searchResults,
655
+ isSearching,
656
+ onSelectResult: handleSelectResult,
657
+ onClear: handleClearSearch,
658
+ showResults,
659
+ setShowResults,
660
+ onRefresh: handleRefresh,
661
+ isRefreshing
331
662
  }
332
663
  ),
333
664
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -335,6 +666,7 @@ function MapBoxField({ name, onChange, value, intlLabel, required }) {
335
666
  {
336
667
  ...viewState,
337
668
  onMove: handleMapMove,
669
+ onMoveEnd: handleMapMoveEnd,
338
670
  onClick: handleMapClick,
339
671
  mapStyle: "mapbox://styles/mapbox/streets-v12",
340
672
  mapboxAccessToken: accessToken,