strapi-plugin-map-box 0.0.2 → 0.0.3

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,58 +38,213 @@ 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
+ z-index: 10;
42
+ width: 350px;
43
43
  `;
44
- const ControlsWrapper = styled__default.default.div`
44
+ const SearchWrapper = styled__default.default.div`
45
+ position: relative;
46
+ `;
47
+ const SearchInputContainer = styled__default.default.div`
45
48
  display: flex;
46
- gap: 0.5rem;
49
+ align-items: center;
50
+ background: white;
51
+ border: 1px solid #dcdce4;
52
+ border-radius: 4px;
53
+ overflow: hidden;
54
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
55
+
56
+ &:focus-within {
57
+ border-color: #4945ff;
58
+ box-shadow: 0 0 0 2px rgba(73, 69, 255, 0.2);
59
+ }
60
+ `;
61
+ const SearchIcon = styled__default.default.div`
62
+ padding: 0 12px;
63
+ color: #8e8e93;
64
+ display: flex;
65
+ align-items: center;
47
66
  `;
48
67
  const SearchInput = styled__default.default.input`
49
68
  flex: 1;
50
- padding: 0.5rem;
51
- border: 1px solid #dcdce4;
52
- border-radius: 4px;
69
+ padding: 10px 0;
70
+ border: none;
53
71
  font-size: 14px;
72
+ outline: none;
73
+ background: transparent;
74
+
75
+ &::placeholder {
76
+ color: #8e8e93;
77
+ }
54
78
  `;
55
- const SearchButton = styled__default.default.button`
56
- padding: 0.5rem 1rem;
57
- background-color: #4945ff;
58
- color: white;
79
+ const ClearButton = styled__default.default.button`
80
+ padding: 8px 12px;
81
+ background: none;
59
82
  border: none;
83
+ cursor: pointer;
84
+ color: #8e8e93;
85
+ display: flex;
86
+ align-items: center;
87
+
88
+ &:hover {
89
+ color: #666;
90
+ }
91
+ `;
92
+ const LoadingSpinner = styled__default.default.div`
93
+ padding: 8px 12px;
94
+ color: #4945ff;
95
+
96
+ @keyframes spin {
97
+ to {
98
+ transform: rotate(360deg);
99
+ }
100
+ }
101
+
102
+ svg {
103
+ animation: spin 1s linear infinite;
104
+ }
105
+ `;
106
+ const ResultsDropdown = styled__default.default.div`
107
+ position: absolute;
108
+ top: calc(100% + 4px);
109
+ left: 0;
110
+ right: 0;
111
+ background: white;
112
+ border: 1px solid #dcdce4;
60
113
  border-radius: 4px;
114
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
115
+ max-height: 300px;
116
+ overflow-y: auto;
117
+ `;
118
+ const ResultItem = styled__default.default.button`
119
+ width: 100%;
120
+ padding: 12px;
121
+ display: flex;
122
+ align-items: flex-start;
123
+ gap: 12px;
124
+ background: none;
125
+ border: none;
126
+ border-bottom: 1px solid #f0f0f0;
61
127
  cursor: pointer;
62
- font-size: 14px;
128
+ text-align: left;
129
+ transition: background-color 0.15s;
130
+
131
+ &:last-child {
132
+ border-bottom: none;
133
+ }
63
134
 
64
135
  &:hover {
65
- background-color: #3832e0;
136
+ background-color: #f6f6f9;
66
137
  }
67
138
  `;
139
+ const ResultIcon = styled__default.default.div`
140
+ width: 32px;
141
+ height: 32px;
142
+ border-radius: 6px;
143
+ background-color: rgba(73, 69, 255, 0.1);
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: center;
147
+ flex-shrink: 0;
148
+ color: #4945ff;
149
+ `;
150
+ const ResultTextContainer = styled__default.default.div`
151
+ flex: 1;
152
+ min-width: 0;
153
+ `;
154
+ const ResultTitle = styled__default.default.div`
155
+ font-size: 14px;
156
+ font-weight: 500;
157
+ color: #32324d;
158
+ white-space: nowrap;
159
+ overflow: hidden;
160
+ text-overflow: ellipsis;
161
+ `;
162
+ const ResultSubtitle = styled__default.default.div`
163
+ font-size: 12px;
164
+ color: #8e8e93;
165
+ white-space: nowrap;
166
+ overflow: hidden;
167
+ text-overflow: ellipsis;
168
+ margin-top: 2px;
169
+ `;
170
+ const NoResults = styled__default.default.div`
171
+ padding: 16px;
172
+ text-align: center;
173
+ color: #8e8e93;
174
+ font-size: 14px;
175
+ `;
176
+ const getPlaceIcon = (placeType) => {
177
+ if (placeType.includes("poi")) {
178
+ 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" }) });
179
+ }
180
+ if (placeType.includes("address")) {
181
+ 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" }) });
182
+ }
183
+ if (placeType.includes("place") || placeType.includes("locality")) {
184
+ 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" }) });
185
+ }
186
+ if (placeType.includes("region") || placeType.includes("country")) {
187
+ 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" }) });
188
+ }
189
+ 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" }) });
190
+ };
68
191
  const MapSearch = ({
69
- onSearch,
70
192
  searchQuery,
71
193
  setSearchQuery,
72
- handleKeyDown
194
+ searchResults,
195
+ isSearching,
196
+ onSelectResult,
197
+ onClear,
198
+ showResults,
199
+ setShowResults
73
200
  }) => {
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,
87
- {
88
- type: "button",
89
- onClick: onSearch,
90
- children: "Search"
91
- }
92
- )
201
+ const handleInputChange = (e) => {
202
+ setSearchQuery(e.target.value);
203
+ setShowResults(true);
204
+ };
205
+ const handleResultClick = (result) => {
206
+ onSelectResult(result);
207
+ setShowResults(false);
208
+ };
209
+ const handleClear = () => {
210
+ onClear();
211
+ setShowResults(false);
212
+ };
213
+ return /* @__PURE__ */ jsxRuntime.jsx(ControlsContainer, { children: /* @__PURE__ */ jsxRuntime.jsxs(SearchWrapper, { children: [
214
+ /* @__PURE__ */ jsxRuntime.jsxs(SearchInputContainer, { children: [
215
+ /* @__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" }) }) }),
216
+ /* @__PURE__ */ jsxRuntime.jsx(
217
+ SearchInput,
218
+ {
219
+ type: "text",
220
+ value: searchQuery,
221
+ onChange: handleInputChange,
222
+ onFocus: () => setShowResults(true),
223
+ placeholder: "Search for a location..."
224
+ }
225
+ ),
226
+ 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" }) }) }),
227
+ 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" }) }) })
228
+ ] }),
229
+ showResults && searchQuery.length > 2 && /* @__PURE__ */ jsxRuntime.jsx(ResultsDropdown, { children: searchResults.length > 0 ? searchResults.map((result) => {
230
+ const [title, ...rest] = result.place_name.split(",");
231
+ const subtitle = rest.join(",").trim();
232
+ return /* @__PURE__ */ jsxRuntime.jsxs(
233
+ ResultItem,
234
+ {
235
+ onClick: () => handleResultClick(result),
236
+ type: "button",
237
+ children: [
238
+ /* @__PURE__ */ jsxRuntime.jsx(ResultIcon, { children: getPlaceIcon(result.place_type) }),
239
+ /* @__PURE__ */ jsxRuntime.jsxs(ResultTextContainer, { children: [
240
+ /* @__PURE__ */ jsxRuntime.jsx(ResultTitle, { children: title }),
241
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(ResultSubtitle, { children: subtitle })
242
+ ] })
243
+ ]
244
+ },
245
+ result.id
246
+ );
247
+ }) : !isSearching ? /* @__PURE__ */ jsxRuntime.jsx(NoResults, { children: "No results found" }) : null })
93
248
  ] }) });
94
249
  };
95
250
  const DEFAULT_VIEW_STATE = {
@@ -223,54 +378,93 @@ function MapBoxField({ name, onChange, value, intlLabel, required }) {
223
378
  const { viewState, markerPosition, setViewState, setMarkerPosition } = useMapLocationHook(value);
224
379
  const { accessToken, debugMode } = config || {};
225
380
  const [searchQuery, setSearchQuery] = react.useState("");
226
- const [searchResults, setSearchResults] = react.useState(null);
381
+ const [searchResults, setSearchResults] = react.useState([]);
382
+ const [isSearching, setIsSearching] = react.useState(false);
383
+ const [showResults, setShowResults] = react.useState(false);
227
384
  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");
385
+ const searchTimeoutRef = react.useRef(null);
386
+ const updateMarkerPosition = react.useCallback(
387
+ (lng, lat, address) => {
388
+ setMarkerPosition({ longitude: lng, latitude: lat });
389
+ const newValue = {
390
+ longitude: lng,
391
+ latitude: lat,
392
+ address: address || "Selected location",
393
+ zoom: viewState.zoom,
394
+ pitch: viewState.pitch,
395
+ bearing: viewState.bearing
396
+ };
397
+ onChange({ target: { name, value: newValue, type: "json" } });
398
+ },
399
+ [name, onChange, setMarkerPosition, viewState.zoom, viewState.pitch, viewState.bearing]
400
+ );
401
+ react.useEffect(() => {
402
+ if (searchTimeoutRef.current) {
403
+ clearTimeout(searchTimeoutRef.current);
266
404
  }
267
- };
268
- const handleKeyDown = (e) => {
269
- if (e.key === "Enter") {
270
- e.preventDefault();
271
- handleSearch();
405
+ if (searchQuery.trim().length <= 2) {
406
+ setSearchResults([]);
407
+ setIsSearching(false);
408
+ return;
272
409
  }
273
- };
410
+ setIsSearching(true);
411
+ searchTimeoutRef.current = setTimeout(async () => {
412
+ try {
413
+ setSearchError(null);
414
+ const encodedQuery = encodeURIComponent(searchQuery.trim());
415
+ const url = `/map-box/location-search/${encodedQuery}`;
416
+ const { data } = await get(url);
417
+ if (data.features) {
418
+ setSearchResults(
419
+ data.features.slice(0, 5).map((feature) => ({
420
+ id: feature.id,
421
+ place_name: feature.place_name,
422
+ center: feature.center,
423
+ place_type: feature.place_type
424
+ }))
425
+ );
426
+ } else if (data.error) {
427
+ setSearchError(data.error);
428
+ setSearchResults([]);
429
+ } else {
430
+ setSearchResults([]);
431
+ }
432
+ } catch (error2) {
433
+ console.error("Error searching location:", error2);
434
+ setSearchError(error2 instanceof Error ? error2.message : "An error occurred");
435
+ setSearchResults([]);
436
+ } finally {
437
+ setIsSearching(false);
438
+ }
439
+ }, 300);
440
+ return () => {
441
+ if (searchTimeoutRef.current) {
442
+ clearTimeout(searchTimeoutRef.current);
443
+ }
444
+ };
445
+ }, [searchQuery, get]);
446
+ const handleSelectResult = react.useCallback(
447
+ (result) => {
448
+ const [longitude, latitude] = result.center;
449
+ setViewState((prev) => ({
450
+ ...prev,
451
+ longitude,
452
+ latitude,
453
+ zoom: 14,
454
+ transitionDuration: 1e3
455
+ }));
456
+ updateMarkerPosition(longitude, latitude, result.place_name);
457
+ setSearchQuery(result.place_name.split(",")[0]);
458
+ setSearchResults([]);
459
+ setShowResults(false);
460
+ },
461
+ [setViewState, updateMarkerPosition]
462
+ );
463
+ const handleClearSearch = react.useCallback(() => {
464
+ setSearchQuery("");
465
+ setSearchResults([]);
466
+ setShowResults(false);
467
+ }, []);
274
468
  const handleMapClick = (event) => {
275
469
  const { lngLat } = event;
276
470
  updateMarkerPosition(lngLat.lng, lngLat.lat);
@@ -278,6 +472,18 @@ function MapBoxField({ name, onChange, value, intlLabel, required }) {
278
472
  const handleMapMove = (evt) => {
279
473
  setViewState(evt.viewState);
280
474
  };
475
+ const handleMapMoveEnd = (evt) => {
476
+ const { longitude, latitude, zoom, pitch, bearing } = evt.viewState;
477
+ const newValue = {
478
+ longitude: markerPosition.longitude,
479
+ latitude: markerPosition.latitude,
480
+ address: value?.address || "Selected location",
481
+ zoom,
482
+ pitch,
483
+ bearing
484
+ };
485
+ onChange({ target: { name, value: newValue, type: "json" } });
486
+ };
281
487
  const handleMarkerDragEnd = (event) => {
282
488
  const { lngLat } = event;
283
489
  updateMarkerPosition(lngLat.lng, lngLat.lat);
@@ -324,10 +530,14 @@ function MapBoxField({ name, onChange, value, intlLabel, required }) {
324
530
  /* @__PURE__ */ jsxRuntime.jsx(
325
531
  MapSearch,
326
532
  {
327
- onSearch: handleSearch,
328
533
  searchQuery,
329
534
  setSearchQuery,
330
- handleKeyDown
535
+ searchResults,
536
+ isSearching,
537
+ onSelectResult: handleSelectResult,
538
+ onClear: handleClearSearch,
539
+ showResults,
540
+ setShowResults
331
541
  }
332
542
  ),
333
543
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -335,6 +545,7 @@ function MapBoxField({ name, onChange, value, intlLabel, required }) {
335
545
  {
336
546
  ...viewState,
337
547
  onMove: handleMapMove,
548
+ onMoveEnd: handleMapMoveEnd,
338
549
  onClick: handleMapClick,
339
550
  mapStyle: "mapbox://styles/mapbox/streets-v12",
340
551
  mapboxAccessToken: accessToken,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../admin/src/pluginId.ts","../../admin/src/components/Initializer.tsx","../../admin/src/components/custom-field/MapBoxField/MapSearch.tsx","../../admin/src/components/custom-field/MapBoxField/types.ts","../../admin/src/components/custom-field/MapBoxField/hooks.ts","../../admin/src/components/custom-field/MapBoxField/DebugInfo.tsx","../../admin/src/components/custom-field/MapBoxField/index.tsx","../../admin/src/index.ts"],"sourcesContent":["export const PLUGIN_ID = 'map-box';\n","import { useEffect, useRef } from 'react';\n\nimport { PLUGIN_ID } from '../pluginId';\n\ntype InitializerProps = {\n setPlugin: (id: string) => void;\n};\n\nconst Initializer = ({ setPlugin }: InitializerProps) => {\n const ref = useRef(setPlugin);\n\n useEffect(() => {\n ref.current(PLUGIN_ID);\n }, []);\n\n return null;\n};\n\nexport { Initializer };\n","import React from 'react';\nimport styled from 'styled-components';\n\nconst ControlsContainer = styled.div`\n position: absolute;\n top: 1rem;\n left: 1rem;\n z-index: 1;\n width: 300px;\n`;\n\nconst ControlsWrapper = styled.div`\n display: flex;\n gap: 0.5rem;\n`;\n\nconst SearchInput = styled.input`\n flex: 1;\n padding: 0.5rem;\n border: 1px solid #dcdce4;\n border-radius: 4px;\n font-size: 14px;\n`;\n\nconst SearchButton = styled.button`\n padding: 0.5rem 1rem;\n background-color: #4945ff;\n color: white;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 14px;\n\n &:hover {\n background-color: #3832e0;\n }\n`;\n\ninterface MapSearchProps {\n onSearch: () => void;\n searchQuery: string;\n setSearchQuery: (query: string) => void;\n handleKeyDown: (e: React.KeyboardEvent) => void;\n}\n\nexport const MapSearch: React.FC<MapSearchProps> = ({\n onSearch,\n searchQuery,\n setSearchQuery,\n handleKeyDown\n}) => {\n return (\n <ControlsContainer>\n <ControlsWrapper>\n <SearchInput\n type=\"text\"\n value={searchQuery}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchQuery(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Search for a location...\"\n />\n <SearchButton\n type=\"button\"\n onClick={onSearch}\n >\n Search\n </SearchButton>\n </ControlsWrapper>\n </ControlsContainer>\n );\n};","export type MapBoxValue = {\n longitude: number;\n latitude: number;\n zoom: number;\n pitch: number;\n bearing: number;\n address: string;\n}\n\n\nexport interface ViewState {\n longitude: number;\n latitude: number;\n zoom: number;\n pitch: number;\n bearing: number;\n padding?: {\n top: number;\n bottom: number;\n left: number;\n right: number;\n };\n}\n\nexport const DEFAULT_VIEW_STATE: ViewState = {\n longitude: -122.4194,\n latitude: 37.7749,\n zoom: 13,\n pitch: 0,\n bearing: 0,\n padding: {\n top: 0,\n bottom: 0,\n left: 0,\n right: 0\n }\n};","import { type MapBoxValue, type ViewState, DEFAULT_VIEW_STATE } from './types';\n\nimport { useEffect, useState } from 'react';\nimport { useFetchClient } from '@strapi/strapi/admin';\n\ntype config = {\n accessToken: string;\n debugMode: boolean;\n};\n\nexport const useMapBoxSettings = () => {\n const { get } = useFetchClient();\n const [config, setConfig] = useState<config | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchSettings = async () => {\n try {\n setIsLoading(true);\n const { data } = await get('/map-box/get-settings');\n console.log('data from getSettings', data);\n setConfig(data);\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to fetch MapBox settings');\n } finally {\n setIsLoading(false);\n }\n };\n fetchSettings();\n }, []);\n\n return { config, isLoading, error };\n};\n\nexport const useMapLocationHook = (initialValue?: MapBoxValue) => {\n const [viewState, setViewState] = useState<ViewState>(DEFAULT_VIEW_STATE);\n const [markerPosition, setMarkerPosition] = useState({\n longitude: DEFAULT_VIEW_STATE.longitude,\n latitude: DEFAULT_VIEW_STATE.latitude,\n });\n\n useEffect(() => {\n if (initialValue) {\n console.log('Initializing from previous value:', initialValue);\n const previousValue = initialValue;\n\n setViewState((prev) => ({\n ...prev,\n longitude: previousValue.longitude,\n latitude: previousValue.latitude,\n zoom: previousValue.zoom,\n pitch: previousValue.pitch,\n bearing: previousValue.bearing,\n }));\n\n setMarkerPosition({\n longitude: previousValue.longitude,\n latitude: previousValue.latitude,\n });\n }\n }, []);\n\n return { viewState, setViewState, markerPosition, setMarkerPosition };\n};\n\nexport const useLocationService = () => {\n const { get } = useFetchClient();\n const [searchError, setSearchError] = useState<string | null>(null);\n const [searchResults, setSearchResults] = useState<any>(null);\n\n const searchLocation = async (query: string) => {\n try {\n setSearchError(null);\n const encodedQuery = encodeURIComponent(query.trim());\n const { data } = await get(`/strapi-plugin-map-box/location-search/${encodedQuery}`);\n setSearchResults(data);\n return data;\n } catch (error) {\n setSearchError(error instanceof Error ? error.message : 'An error occurred');\n return null;\n }\n };\n\n return { searchLocation, searchError, searchResults };\n};\n","import styled from 'styled-components';\nimport { ViewState } from './types';\n\n\ninterface DebugInfoProps {\n searchResults: any;\n searchError: string | null;\n viewState: ViewState;\n markerPosition: { longitude: number; latitude: number };\n searchQuery: string;\n value?: any;\n}\n\nexport function DebugInfo({ \n searchResults, \n searchError, \n viewState,\n markerPosition,\n searchQuery,\n value \n}: DebugInfoProps) {\n return (\n <DebugContainer>\n <h4>Debug Information:</h4>\n \n <DebugSection>\n <strong>Search Results:</strong>\n <DebugPre>\n {searchResults ? JSON.stringify(searchResults, null, 2) : 'No search results yet'}\n </DebugPre>\n </DebugSection>\n\n {searchError && (\n <ErrorMessage>\n <strong>Error:</strong> {searchError}\n </ErrorMessage>\n )}\n\n <DebugSection>\n <strong>Current View State:</strong>\n <DebugPre>\n {JSON.stringify(viewState, null, 2)}\n </DebugPre>\n </DebugSection>\n\n <DebugSection>\n <strong>Marker Position:</strong>\n <DebugPre>\n {JSON.stringify(markerPosition, null, 2)}\n </DebugPre>\n </DebugSection>\n\n <DebugSection>\n <strong>Search Query:</strong>\n <DebugPre>\n {searchQuery || 'No search query'}\n </DebugPre>\n </DebugSection>\n\n <DebugSection>\n <strong>Current Value:</strong>\n <DebugPre>\n {value ? JSON.stringify(value, null, 2) : 'No value set'}\n </DebugPre>\n </DebugSection>\n </DebugContainer>\n );\n}\n\nconst DebugContainer = styled.div`\n margin-top: 20px;\n padding: 1rem;\n background-color: #f5f5f5;\n border-radius: 4px;\n`;\n\nconst DebugSection = styled.div`\n margin-bottom: 10px;\n`;\n\nconst DebugPre = styled.pre`\n background: #ffffff;\n padding: 10px;\n border-radius: 4px;\n max-height: 200px;\n overflow: auto;\n margin: 5px 0;\n border: 1px solid #dcdce4;\n`;\n\nconst ErrorMessage = styled.div`\n color: #d02b20;\n margin-bottom: 10px;\n padding: 10px;\n background-color: #fff5f5;\n border: 1px solid #ffd7d5;\n border-radius: 4px;\n`;","import { MapBoxValue } from './types';\nimport { Field, JSONInput } from '@strapi/design-system';\n\nimport Map, {\n FullscreenControl,\n GeolocateControl,\n Marker,\n NavigationControl,\n} from 'react-map-gl/mapbox';\n\nimport 'mapbox-gl/dist/mapbox-gl.css';\nimport { useState } from 'react';\nimport { useFetchClient } from '@strapi/strapi/admin';\nimport { MapSearch } from './MapSearch';\n\nimport { useMapBoxSettings, useMapLocationHook } from './hooks';\nimport { DebugInfo } from './DebugInfo';\n\ninterface MapBoxFieldProps {\n name: string;\n onChange: (event: { target: { name: string; value: object; type: string } }) => void;\n value?: MapBoxValue;\n intlLabel?: {\n defaultMessage: string;\n };\n required?: boolean;\n}\n\n// #endregion\n\nexport function MapBoxField({ name, onChange, value, intlLabel, required }: MapBoxFieldProps) {\n const { get } = useFetchClient();\n const { config, isLoading, error } = useMapBoxSettings();\n const { viewState, markerPosition, setViewState, setMarkerPosition } = useMapLocationHook(value);\n\n const { accessToken, debugMode } = config || {};\n\n const [searchQuery, setSearchQuery] = useState('');\n const [searchResults, setSearchResults] = useState<any>(null);\n const [searchError, setSearchError] = useState<string | null>(null);\n\n const updateMarkerPosition = (lng: number, lat: number, address?: string) => {\n setMarkerPosition({ longitude: lng, latitude: lat });\n\n // Update the JSON value with all necessary data\n const newValue = {\n longitude: lng,\n latitude: lat,\n address: address || 'Selected location',\n zoom: viewState.zoom,\n pitch: viewState.pitch,\n bearing: viewState.bearing,\n };\n\n onChange({ target: { name, value: newValue, type: 'json' } });\n };\n\n const handleSearch = async () => {\n if (!searchQuery.trim()) return;\n\n try {\n setSearchError(null);\n const encodedQuery = encodeURIComponent(searchQuery.trim());\n const url = `/map-box/location-search/${encodedQuery}`;\n const { data } = await get(url);\n\n setSearchResults(data);\n\n if (data.features && data.features[0]) {\n const [longitude, latitude] = data.features[0].center;\n // Update both the view and marker position\n setViewState((prev) => ({\n ...prev,\n longitude,\n latitude,\n zoom: 14,\n transitionDuration: 1000,\n }));\n updateMarkerPosition(longitude, latitude, data.features[0].place_name);\n } else if (data.error) {\n setSearchError(data.error);\n } else {\n setSearchError('No results found');\n }\n } catch (error) {\n console.error('Error searching location:', error);\n setSearchError(error instanceof Error ? error.message : 'An error occurred');\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleSearch();\n }\n };\n\n const handleMapClick = (event: any) => {\n const { lngLat } = event;\n updateMarkerPosition(lngLat.lng, lngLat.lat);\n };\n\n const handleMapMove = (evt: any) => {\n setViewState(evt.viewState);\n };\n\n const handleMarkerDragEnd = (event: any) => {\n const { lngLat } = event;\n updateMarkerPosition(lngLat.lng, lngLat.lat);\n };\n\n const handlePositionChange = (input: string) => {\n try {\n const value = JSON.parse(input);\n setViewState((prev) => ({\n ...prev,\n longitude: value.longitude,\n latitude: value.latitude,\n zoom: value.zoom || prev.zoom,\n pitch: value.pitch || prev.pitch,\n bearing: value.bearing || prev.bearing,\n }));\n setMarkerPosition({\n longitude: value.longitude,\n latitude: value.latitude,\n });\n onChange({ target: { name, value, type: 'json' } });\n } catch {\n // Handle invalid JSON\n }\n };\n\n // Construct the final JSON value to be saved\n const finalValue: MapBoxValue = {\n longitude: markerPosition.longitude,\n latitude: markerPosition.latitude,\n zoom: viewState.zoom,\n pitch: viewState.pitch,\n bearing: viewState.bearing,\n address: (value as MapBoxValue)?.address || 'Selected location',\n };\n\n const strValue = JSON.stringify(value || finalValue, null, 2);\n\n if (!accessToken || isLoading) {\n return <div>Loading...</div>;\n }\n\n if (error) {\n return <div>Error: {error}</div>;\n }\n\n return (\n <div>\n <div style={{ position: 'relative', height: '500px', width: '100%' }}>\n <MapSearch\n onSearch={handleSearch}\n searchQuery={searchQuery}\n setSearchQuery={setSearchQuery}\n handleKeyDown={handleKeyDown}\n />\n <Map\n {...viewState}\n onMove={handleMapMove}\n onClick={handleMapClick}\n mapStyle=\"mapbox://styles/mapbox/streets-v12\"\n // mapStyle=\"mapbox://styles/mapbox/light-v11\"\n mapboxAccessToken={accessToken}\n attributionControl={false}\n style={{ height: '100%', width: '100%' }}\n >\n <FullscreenControl />\n <NavigationControl />\n <GeolocateControl />\n <Marker\n longitude={markerPosition.longitude}\n latitude={markerPosition.latitude}\n color=\"#4945ff\"\n draggable\n onDragEnd={handleMarkerDragEnd}\n />\n </Map>\n </div>\n {debugMode && (\n <Field.Root name={name} required={required}>\n <Field.Label>{intlLabel?.defaultMessage ?? 'Location'}</Field.Label>\n <JSONInput value={strValue} onChange={handlePositionChange}></JSONInput>\n <Field.Error />\n <Field.Hint />\n </Field.Root>\n )}\n\n {debugMode && (\n <DebugInfo\n viewState={viewState}\n searchResults={searchResults}\n searchError={searchError}\n markerPosition={markerPosition}\n searchQuery={searchQuery}\n value={value}\n />\n )}\n </div>\n );\n}\n","import { getTranslation } from './utils/getTranslation';\nimport { PLUGIN_ID } from './pluginId';\nimport { Initializer } from './components/Initializer';\nimport { PinMap } from '@strapi/icons';\nimport { MapBoxField } from './components/custom-field/MapBoxField/index';\n\nexport default {\n register(app: any) {\n \n app.customFields.register({\n name: 'map-box',\n type: 'json',\n icon: PinMap,\n intlLabel: {\n id: 'custom.fields.map-box.label',\n defaultMessage: 'Map Box',\n },\n intlDescription: {\n id: 'custom.fields.map-box.description',\n defaultMessage: 'Enter geographic coordinates',\n },\n components: {\n Input: () => ({ default: MapBoxField as React.ComponentType }) as any,\n },\n });\n\n app.registerPlugin({\n id: PLUGIN_ID,\n initializer: Initializer,\n isReady: false,\n name: PLUGIN_ID,\n });\n },\n\n async registerTrads({ locales }: { locales: string[] }) {\n return Promise.all(\n locales.map(async (locale) => {\n try {\n const { default: data } = await import(`./translations/${locale}.json`);\n\n return { data, locale };\n } catch {\n return { data: {}, locale };\n }\n })\n );\n },\n};\n"],"names":["useRef","useEffect","styled","jsx","jsxs","useFetchClient","useState","error","value","Map","FullscreenControl","NavigationControl","GeolocateControl","Marker","Field","JSONInput","PinMap"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../admin/src/pluginId.ts","../../admin/src/components/Initializer.tsx","../../admin/src/components/custom-field/MapBoxField/MapSearch.tsx","../../admin/src/components/custom-field/MapBoxField/types.ts","../../admin/src/components/custom-field/MapBoxField/hooks.ts","../../admin/src/components/custom-field/MapBoxField/DebugInfo.tsx","../../admin/src/components/custom-field/MapBoxField/index.tsx","../../admin/src/index.ts"],"sourcesContent":["export const PLUGIN_ID = 'map-box';\n","import { useEffect, useRef } from 'react';\n\nimport { PLUGIN_ID } from '../pluginId';\n\ntype InitializerProps = {\n setPlugin: (id: string) => void;\n};\n\nconst Initializer = ({ setPlugin }: InitializerProps) => {\n const ref = useRef(setPlugin);\n\n useEffect(() => {\n ref.current(PLUGIN_ID);\n }, []);\n\n return null;\n};\n\nexport { Initializer };\n","import React from 'react';\nimport styled from 'styled-components';\n\nconst ControlsContainer = styled.div`\n position: absolute;\n top: 1rem;\n left: 1rem;\n z-index: 10;\n width: 350px;\n`;\n\nconst SearchWrapper = styled.div`\n position: relative;\n`;\n\nconst SearchInputContainer = styled.div`\n display: flex;\n align-items: center;\n background: white;\n border: 1px solid #dcdce4;\n border-radius: 4px;\n overflow: hidden;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n\n &:focus-within {\n border-color: #4945ff;\n box-shadow: 0 0 0 2px rgba(73, 69, 255, 0.2);\n }\n`;\n\nconst SearchIcon = styled.div`\n padding: 0 12px;\n color: #8e8e93;\n display: flex;\n align-items: center;\n`;\n\nconst SearchInput = styled.input`\n flex: 1;\n padding: 10px 0;\n border: none;\n font-size: 14px;\n outline: none;\n background: transparent;\n\n &::placeholder {\n color: #8e8e93;\n }\n`;\n\nconst ClearButton = styled.button`\n padding: 8px 12px;\n background: none;\n border: none;\n cursor: pointer;\n color: #8e8e93;\n display: flex;\n align-items: center;\n\n &:hover {\n color: #666;\n }\n`;\n\nconst LoadingSpinner = styled.div`\n padding: 8px 12px;\n color: #4945ff;\n\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n svg {\n animation: spin 1s linear infinite;\n }\n`;\n\nconst ResultsDropdown = styled.div`\n position: absolute;\n top: calc(100% + 4px);\n left: 0;\n right: 0;\n background: white;\n border: 1px solid #dcdce4;\n border-radius: 4px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n max-height: 300px;\n overflow-y: auto;\n`;\n\nconst ResultItem = styled.button`\n width: 100%;\n padding: 12px;\n display: flex;\n align-items: flex-start;\n gap: 12px;\n background: none;\n border: none;\n border-bottom: 1px solid #f0f0f0;\n cursor: pointer;\n text-align: left;\n transition: background-color 0.15s;\n\n &:last-child {\n border-bottom: none;\n }\n\n &:hover {\n background-color: #f6f6f9;\n }\n`;\n\nconst ResultIcon = styled.div`\n width: 32px;\n height: 32px;\n border-radius: 6px;\n background-color: rgba(73, 69, 255, 0.1);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n color: #4945ff;\n`;\n\nconst ResultTextContainer = styled.div`\n flex: 1;\n min-width: 0;\n`;\n\nconst ResultTitle = styled.div`\n font-size: 14px;\n font-weight: 500;\n color: #32324d;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n`;\n\nconst ResultSubtitle = styled.div`\n font-size: 12px;\n color: #8e8e93;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin-top: 2px;\n`;\n\nconst NoResults = styled.div`\n padding: 16px;\n text-align: center;\n color: #8e8e93;\n font-size: 14px;\n`;\n\nexport interface SearchResult {\n id: string;\n place_name: string;\n center: [number, number];\n place_type: string[];\n}\n\ninterface MapSearchProps {\n searchQuery: string;\n setSearchQuery: (query: string) => void;\n searchResults: SearchResult[];\n isSearching: boolean;\n onSelectResult: (result: SearchResult) => void;\n onClear: () => void;\n showResults: boolean;\n setShowResults: (show: boolean) => void;\n}\n\nconst getPlaceIcon = (placeType: string[]) => {\n if (placeType.includes('poi')) {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <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\" />\n </svg>\n );\n }\n if (placeType.includes('address')) {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z\" />\n </svg>\n );\n }\n if (placeType.includes('place') || placeType.includes('locality')) {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <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\" />\n </svg>\n );\n }\n if (placeType.includes('region') || placeType.includes('country')) {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <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\" />\n </svg>\n );\n }\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <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\" />\n </svg>\n );\n};\n\nexport const MapSearch: React.FC<MapSearchProps> = ({\n searchQuery,\n setSearchQuery,\n searchResults,\n isSearching,\n onSelectResult,\n onClear,\n showResults,\n setShowResults,\n}) => {\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setSearchQuery(e.target.value);\n setShowResults(true);\n };\n\n const handleResultClick = (result: SearchResult) => {\n onSelectResult(result);\n setShowResults(false);\n };\n\n const handleClear = () => {\n onClear();\n setShowResults(false);\n };\n\n return (\n <ControlsContainer>\n <SearchWrapper>\n <SearchInputContainer>\n <SearchIcon>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <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\" />\n </svg>\n </SearchIcon>\n <SearchInput\n type=\"text\"\n value={searchQuery}\n onChange={handleInputChange}\n onFocus={() => setShowResults(true)}\n placeholder=\"Search for a location...\"\n />\n {isSearching && (\n <LoadingSpinner>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 4V2A10 10 0 0 0 2 12h2a8 8 0 0 1 8-8z\" />\n </svg>\n </LoadingSpinner>\n )}\n {searchQuery && !isSearching && (\n <ClearButton onClick={handleClear} type=\"button\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <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\" />\n </svg>\n </ClearButton>\n )}\n </SearchInputContainer>\n\n {showResults && searchQuery.length > 2 && (\n <ResultsDropdown>\n {searchResults.length > 0 ? (\n searchResults.map((result) => {\n const [title, ...rest] = result.place_name.split(',');\n const subtitle = rest.join(',').trim();\n return (\n <ResultItem\n key={result.id}\n onClick={() => handleResultClick(result)}\n type=\"button\"\n >\n <ResultIcon>{getPlaceIcon(result.place_type)}</ResultIcon>\n <ResultTextContainer>\n <ResultTitle>{title}</ResultTitle>\n {subtitle && <ResultSubtitle>{subtitle}</ResultSubtitle>}\n </ResultTextContainer>\n </ResultItem>\n );\n })\n ) : !isSearching ? (\n <NoResults>No results found</NoResults>\n ) : null}\n </ResultsDropdown>\n )}\n </SearchWrapper>\n </ControlsContainer>\n );\n};\n","export type MapBoxValue = {\n longitude: number;\n latitude: number;\n zoom: number;\n pitch: number;\n bearing: number;\n address: string;\n}\n\n\nexport interface ViewState {\n longitude: number;\n latitude: number;\n zoom: number;\n pitch: number;\n bearing: number;\n padding?: {\n top: number;\n bottom: number;\n left: number;\n right: number;\n };\n}\n\nexport const DEFAULT_VIEW_STATE: ViewState = {\n longitude: -122.4194,\n latitude: 37.7749,\n zoom: 13,\n pitch: 0,\n bearing: 0,\n padding: {\n top: 0,\n bottom: 0,\n left: 0,\n right: 0\n }\n};","import { type MapBoxValue, type ViewState, DEFAULT_VIEW_STATE } from './types';\n\nimport { useEffect, useState } from 'react';\nimport { useFetchClient } from '@strapi/strapi/admin';\n\ntype config = {\n accessToken: string;\n debugMode: boolean;\n};\n\nexport const useMapBoxSettings = () => {\n const { get } = useFetchClient();\n const [config, setConfig] = useState<config | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchSettings = async () => {\n try {\n setIsLoading(true);\n const { data } = await get('/map-box/get-settings');\n console.log('data from getSettings', data);\n setConfig(data);\n setError(null);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to fetch MapBox settings');\n } finally {\n setIsLoading(false);\n }\n };\n fetchSettings();\n }, []);\n\n return { config, isLoading, error };\n};\n\nexport const useMapLocationHook = (initialValue?: MapBoxValue) => {\n const [viewState, setViewState] = useState<ViewState>(DEFAULT_VIEW_STATE);\n const [markerPosition, setMarkerPosition] = useState({\n longitude: DEFAULT_VIEW_STATE.longitude,\n latitude: DEFAULT_VIEW_STATE.latitude,\n });\n\n useEffect(() => {\n if (initialValue) {\n console.log('Initializing from previous value:', initialValue);\n const previousValue = initialValue;\n\n setViewState((prev) => ({\n ...prev,\n longitude: previousValue.longitude,\n latitude: previousValue.latitude,\n zoom: previousValue.zoom,\n pitch: previousValue.pitch,\n bearing: previousValue.bearing,\n }));\n\n setMarkerPosition({\n longitude: previousValue.longitude,\n latitude: previousValue.latitude,\n });\n }\n }, []);\n\n return { viewState, setViewState, markerPosition, setMarkerPosition };\n};\n\nexport const useLocationService = () => {\n const { get } = useFetchClient();\n const [searchError, setSearchError] = useState<string | null>(null);\n const [searchResults, setSearchResults] = useState<any>(null);\n\n const searchLocation = async (query: string) => {\n try {\n setSearchError(null);\n const encodedQuery = encodeURIComponent(query.trim());\n const { data } = await get(`/strapi-plugin-map-box/location-search/${encodedQuery}`);\n setSearchResults(data);\n return data;\n } catch (error) {\n setSearchError(error instanceof Error ? error.message : 'An error occurred');\n return null;\n }\n };\n\n return { searchLocation, searchError, searchResults };\n};\n","import styled from 'styled-components';\nimport { ViewState } from './types';\n\n\ninterface DebugInfoProps {\n searchResults: any;\n searchError: string | null;\n viewState: ViewState;\n markerPosition: { longitude: number; latitude: number };\n searchQuery: string;\n value?: any;\n}\n\nexport function DebugInfo({ \n searchResults, \n searchError, \n viewState,\n markerPosition,\n searchQuery,\n value \n}: DebugInfoProps) {\n return (\n <DebugContainer>\n <h4>Debug Information:</h4>\n \n <DebugSection>\n <strong>Search Results:</strong>\n <DebugPre>\n {searchResults ? JSON.stringify(searchResults, null, 2) : 'No search results yet'}\n </DebugPre>\n </DebugSection>\n\n {searchError && (\n <ErrorMessage>\n <strong>Error:</strong> {searchError}\n </ErrorMessage>\n )}\n\n <DebugSection>\n <strong>Current View State:</strong>\n <DebugPre>\n {JSON.stringify(viewState, null, 2)}\n </DebugPre>\n </DebugSection>\n\n <DebugSection>\n <strong>Marker Position:</strong>\n <DebugPre>\n {JSON.stringify(markerPosition, null, 2)}\n </DebugPre>\n </DebugSection>\n\n <DebugSection>\n <strong>Search Query:</strong>\n <DebugPre>\n {searchQuery || 'No search query'}\n </DebugPre>\n </DebugSection>\n\n <DebugSection>\n <strong>Current Value:</strong>\n <DebugPre>\n {value ? JSON.stringify(value, null, 2) : 'No value set'}\n </DebugPre>\n </DebugSection>\n </DebugContainer>\n );\n}\n\nconst DebugContainer = styled.div`\n margin-top: 20px;\n padding: 1rem;\n background-color: #f5f5f5;\n border-radius: 4px;\n`;\n\nconst DebugSection = styled.div`\n margin-bottom: 10px;\n`;\n\nconst DebugPre = styled.pre`\n background: #ffffff;\n padding: 10px;\n border-radius: 4px;\n max-height: 200px;\n overflow: auto;\n margin: 5px 0;\n border: 1px solid #dcdce4;\n`;\n\nconst ErrorMessage = styled.div`\n color: #d02b20;\n margin-bottom: 10px;\n padding: 10px;\n background-color: #fff5f5;\n border: 1px solid #ffd7d5;\n border-radius: 4px;\n`;","import { MapBoxValue } from './types';\nimport { Field, JSONInput } from '@strapi/design-system';\n\nimport Map, {\n FullscreenControl,\n GeolocateControl,\n Marker,\n NavigationControl,\n} from 'react-map-gl/mapbox';\n\nimport 'mapbox-gl/dist/mapbox-gl.css';\nimport { useState, useEffect, useCallback, useRef } from 'react';\nimport { useFetchClient } from '@strapi/strapi/admin';\nimport { MapSearch, SearchResult } from './MapSearch';\n\nimport { useMapBoxSettings, useMapLocationHook } from './hooks';\nimport { DebugInfo } from './DebugInfo';\n\ninterface MapBoxFieldProps {\n name: string;\n onChange: (event: { target: { name: string; value: object; type: string } }) => void;\n value?: MapBoxValue;\n intlLabel?: {\n defaultMessage: string;\n };\n required?: boolean;\n}\n\nexport function MapBoxField({ name, onChange, value, intlLabel, required }: MapBoxFieldProps) {\n const { get } = useFetchClient();\n const { config, isLoading, error } = useMapBoxSettings();\n const { viewState, markerPosition, setViewState, setMarkerPosition } = useMapLocationHook(value);\n\n const { accessToken, debugMode } = config || {};\n\n const [searchQuery, setSearchQuery] = useState('');\n const [searchResults, setSearchResults] = useState<SearchResult[]>([]);\n const [isSearching, setIsSearching] = useState(false);\n const [showResults, setShowResults] = useState(false);\n const [searchError, setSearchError] = useState<string | null>(null);\n const searchTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n const updateMarkerPosition = useCallback(\n (lng: number, lat: number, address?: string) => {\n setMarkerPosition({ longitude: lng, latitude: lat });\n\n const newValue = {\n longitude: lng,\n latitude: lat,\n address: address || 'Selected location',\n zoom: viewState.zoom,\n pitch: viewState.pitch,\n bearing: viewState.bearing,\n };\n\n onChange({ target: { name, value: newValue, type: 'json' } });\n },\n [name, onChange, setMarkerPosition, viewState.zoom, viewState.pitch, viewState.bearing]\n );\n\n // Debounced search as user types\n useEffect(() => {\n if (searchTimeoutRef.current) {\n clearTimeout(searchTimeoutRef.current);\n }\n\n if (searchQuery.trim().length <= 2) {\n setSearchResults([]);\n setIsSearching(false);\n return;\n }\n\n setIsSearching(true);\n\n searchTimeoutRef.current = setTimeout(async () => {\n try {\n setSearchError(null);\n const encodedQuery = encodeURIComponent(searchQuery.trim());\n const url = `/map-box/location-search/${encodedQuery}`;\n const { data } = await get(url);\n\n if (data.features) {\n setSearchResults(\n data.features.slice(0, 5).map((feature: any) => ({\n id: feature.id,\n place_name: feature.place_name,\n center: feature.center,\n place_type: feature.place_type,\n }))\n );\n } else if (data.error) {\n setSearchError(data.error);\n setSearchResults([]);\n } else {\n setSearchResults([]);\n }\n } catch (error) {\n console.error('Error searching location:', error);\n setSearchError(error instanceof Error ? error.message : 'An error occurred');\n setSearchResults([]);\n } finally {\n setIsSearching(false);\n }\n }, 300);\n\n return () => {\n if (searchTimeoutRef.current) {\n clearTimeout(searchTimeoutRef.current);\n }\n };\n }, [searchQuery, get]);\n\n const handleSelectResult = useCallback(\n (result: SearchResult) => {\n const [longitude, latitude] = result.center;\n\n setViewState((prev) => ({\n ...prev,\n longitude,\n latitude,\n zoom: 14,\n transitionDuration: 1000,\n }));\n\n updateMarkerPosition(longitude, latitude, result.place_name);\n setSearchQuery(result.place_name.split(',')[0]);\n setSearchResults([]);\n setShowResults(false);\n },\n [setViewState, updateMarkerPosition]\n );\n\n const handleClearSearch = useCallback(() => {\n setSearchQuery('');\n setSearchResults([]);\n setShowResults(false);\n }, []);\n\n const handleMapClick = (event: any) => {\n const { lngLat } = event;\n updateMarkerPosition(lngLat.lng, lngLat.lat);\n };\n\n const handleMapMove = (evt: any) => {\n setViewState(evt.viewState);\n };\n\n const handleMapMoveEnd = (evt: any) => {\n const { longitude, latitude, zoom, pitch, bearing } = evt.viewState;\n\n // Save the current view state including zoom level\n const newValue = {\n longitude: markerPosition.longitude,\n latitude: markerPosition.latitude,\n address: (value as MapBoxValue)?.address || 'Selected location',\n zoom,\n pitch,\n bearing,\n };\n\n onChange({ target: { name, value: newValue, type: 'json' } });\n };\n\n const handleMarkerDragEnd = (event: any) => {\n const { lngLat } = event;\n updateMarkerPosition(lngLat.lng, lngLat.lat);\n };\n\n const handlePositionChange = (input: string) => {\n try {\n const value = JSON.parse(input);\n setViewState((prev) => ({\n ...prev,\n longitude: value.longitude,\n latitude: value.latitude,\n zoom: value.zoom || prev.zoom,\n pitch: value.pitch || prev.pitch,\n bearing: value.bearing || prev.bearing,\n }));\n setMarkerPosition({\n longitude: value.longitude,\n latitude: value.latitude,\n });\n onChange({ target: { name, value, type: 'json' } });\n } catch {\n // Handle invalid JSON\n }\n };\n\n // Construct the final JSON value to be saved\n const finalValue: MapBoxValue = {\n longitude: markerPosition.longitude,\n latitude: markerPosition.latitude,\n zoom: viewState.zoom,\n pitch: viewState.pitch,\n bearing: viewState.bearing,\n address: (value as MapBoxValue)?.address || 'Selected location',\n };\n\n const strValue = JSON.stringify(value || finalValue, null, 2);\n\n if (!accessToken || isLoading) {\n return <div>Loading...</div>;\n }\n\n if (error) {\n return <div>Error: {error}</div>;\n }\n\n return (\n <div>\n <div style={{ position: 'relative', height: '500px', width: '100%' }}>\n <MapSearch\n searchQuery={searchQuery}\n setSearchQuery={setSearchQuery}\n searchResults={searchResults}\n isSearching={isSearching}\n onSelectResult={handleSelectResult}\n onClear={handleClearSearch}\n showResults={showResults}\n setShowResults={setShowResults}\n />\n <Map\n {...viewState}\n onMove={handleMapMove}\n onMoveEnd={handleMapMoveEnd}\n onClick={handleMapClick}\n mapStyle=\"mapbox://styles/mapbox/streets-v12\"\n mapboxAccessToken={accessToken}\n attributionControl={false}\n style={{ height: '100%', width: '100%' }}\n >\n <FullscreenControl />\n <NavigationControl />\n <GeolocateControl />\n <Marker\n longitude={markerPosition.longitude}\n latitude={markerPosition.latitude}\n color=\"#4945ff\"\n draggable\n onDragEnd={handleMarkerDragEnd}\n />\n </Map>\n </div>\n {debugMode && (\n <Field.Root name={name} required={required}>\n <Field.Label>{intlLabel?.defaultMessage ?? 'Location'}</Field.Label>\n <JSONInput value={strValue} onChange={handlePositionChange}></JSONInput>\n <Field.Error />\n <Field.Hint />\n </Field.Root>\n )}\n\n {debugMode && (\n <DebugInfo\n viewState={viewState}\n searchResults={searchResults}\n searchError={searchError}\n markerPosition={markerPosition}\n searchQuery={searchQuery}\n value={value}\n />\n )}\n </div>\n );\n}\n","import { getTranslation } from './utils/getTranslation';\nimport { PLUGIN_ID } from './pluginId';\nimport { Initializer } from './components/Initializer';\nimport { PinMap } from '@strapi/icons';\nimport { MapBoxField } from './components/custom-field/MapBoxField/index';\n\nexport default {\n register(app: any) {\n \n app.customFields.register({\n name: 'map-box',\n type: 'json',\n icon: PinMap,\n intlLabel: {\n id: 'custom.fields.map-box.label',\n defaultMessage: 'Map Box',\n },\n intlDescription: {\n id: 'custom.fields.map-box.description',\n defaultMessage: 'Enter geographic coordinates',\n },\n components: {\n Input: () => ({ default: MapBoxField as React.ComponentType }) as any,\n },\n });\n\n app.registerPlugin({\n id: PLUGIN_ID,\n initializer: Initializer,\n isReady: false,\n name: PLUGIN_ID,\n });\n },\n\n async registerTrads({ locales }: { locales: string[] }) {\n return Promise.all(\n locales.map(async (locale) => {\n try {\n const { default: data } = await import(`./translations/${locale}.json`);\n\n return { data, locale };\n } catch {\n return { data: {}, locale };\n }\n })\n );\n },\n};\n"],"names":["useRef","useEffect","styled","jsx","jsxs","useFetchClient","useState","useCallback","error","value","Map","FullscreenControl","NavigationControl","GeolocateControl","Marker","Field","JSONInput","PinMap"],"mappings":"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"}