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.
- package/dist/admin/index.js +292 -81
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +293 -82
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/src/components/custom-field/MapBoxField/MapSearch.d.ts +12 -2
- package/dist/server/index.js +2 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +2 -3
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/admin/index.js
CHANGED
|
@@ -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:
|
|
42
|
-
width:
|
|
41
|
+
z-index: 10;
|
|
42
|
+
width: 350px;
|
|
43
43
|
`;
|
|
44
|
-
const
|
|
44
|
+
const SearchWrapper = styled__default.default.div`
|
|
45
|
+
position: relative;
|
|
46
|
+
`;
|
|
47
|
+
const SearchInputContainer = styled__default.default.div`
|
|
45
48
|
display: flex;
|
|
46
|
-
|
|
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
|
|
51
|
-
border:
|
|
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
|
|
56
|
-
padding:
|
|
57
|
-
background
|
|
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
|
-
|
|
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: #
|
|
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
|
-
|
|
194
|
+
searchResults,
|
|
195
|
+
isSearching,
|
|
196
|
+
onSelectResult,
|
|
197
|
+
onClear,
|
|
198
|
+
showResults,
|
|
199
|
+
setShowResults
|
|
73
200
|
}) => {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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(
|
|
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
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
longitude: lng,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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
|
-
|
|
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,
|
package/dist/admin/index.js.map
CHANGED
|
@@ -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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"}
|