UNPKG

strapi-plugin-map-box

Version:
420 lines (418 loc) 13.5 kB
"use strict"; const react = require("react"); const icons = require("@strapi/icons"); const jsxRuntime = require("react/jsx-runtime"); const designSystem = require("@strapi/design-system"); const Map = require("react-map-gl/mapbox"); require("mapbox-gl/dist/mapbox-gl.css"); const admin = require("@strapi/strapi/admin"); const styled = require("styled-components"); const _interopDefault = (e) => e && e.__esModule ? e : { default: e }; const Map__default = /* @__PURE__ */ _interopDefault(Map); const styled__default = /* @__PURE__ */ _interopDefault(styled); const __variableDynamicImportRuntimeHelper = (glob, path, segs) => { const v = glob[path]; if (v) { return typeof v === "function" ? v() : Promise.resolve(v); } return new Promise((_, reject) => { (typeof queueMicrotask === "function" ? queueMicrotask : setTimeout)( reject.bind( null, new Error( "Unknown variable dynamic import: " + path + (path.split("/").length !== segs ? ". Note that variables only represent file names one level deep." : "") ) ) ); }); }; const PLUGIN_ID = "map-box"; const Initializer = ({ setPlugin }) => { const ref = react.useRef(setPlugin); react.useEffect(() => { ref.current(PLUGIN_ID); }, []); return null; }; const ControlsContainer = styled__default.default.div` position: absolute; top: 1rem; left: 1rem; z-index: 1; width: 300px; `; const ControlsWrapper = styled__default.default.div` display: flex; gap: 0.5rem; `; const SearchInput = styled__default.default.input` flex: 1; padding: 0.5rem; border: 1px solid #dcdce4; border-radius: 4px; font-size: 14px; `; const SearchButton = styled__default.default.button` padding: 0.5rem 1rem; background-color: #4945ff; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; &:hover { background-color: #3832e0; } `; const MapSearch = ({ onSearch, searchQuery, setSearchQuery, handleKeyDown }) => { return /* @__PURE__ */ jsxRuntime.jsx(ControlsContainer, { children: /* @__PURE__ */ jsxRuntime.jsxs(ControlsWrapper, { children: [ /* @__PURE__ */ jsxRuntime.jsx( SearchInput, { type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onKeyDown: handleKeyDown, placeholder: "Search for a location..." } ), /* @__PURE__ */ jsxRuntime.jsx( SearchButton, { type: "button", onClick: onSearch, children: "Search" } ) ] }) }); }; const DEFAULT_VIEW_STATE = { longitude: -122.4194, latitude: 37.7749, zoom: 13, pitch: 0, bearing: 0, padding: { top: 0, bottom: 0, left: 0, right: 0 } }; const useMapBoxSettings = () => { const { get } = admin.useFetchClient(); const [config, setConfig] = react.useState(null); const [isLoading, setIsLoading] = react.useState(true); const [error, setError] = react.useState(null); react.useEffect(() => { const fetchSettings = async () => { try { setIsLoading(true); const { data } = await get("/strapi-plugin-map-box/get-settings"); console.log("data from getSettings", data); setConfig(data); setError(null); } catch (err) { setError(err instanceof Error ? err.message : "Failed to fetch MapBox settings"); } finally { setIsLoading(false); } }; fetchSettings(); }, []); return { config, isLoading, error }; }; const useMapLocationHook = (initialValue) => { const [viewState, setViewState] = react.useState(DEFAULT_VIEW_STATE); const [markerPosition, setMarkerPosition] = react.useState({ longitude: DEFAULT_VIEW_STATE.longitude, latitude: DEFAULT_VIEW_STATE.latitude }); react.useEffect(() => { if (initialValue) { console.log("Initializing from previous value:", initialValue); const previousValue = initialValue; setViewState((prev) => ({ ...prev, longitude: previousValue.longitude, latitude: previousValue.latitude, zoom: previousValue.zoom, pitch: previousValue.pitch, bearing: previousValue.bearing })); setMarkerPosition({ longitude: previousValue.longitude, latitude: previousValue.latitude }); } }, []); return { viewState, setViewState, markerPosition, setMarkerPosition }; }; function DebugInfo({ searchResults, searchError, viewState, markerPosition, searchQuery, value }) { return /* @__PURE__ */ jsxRuntime.jsxs(DebugContainer, { children: [ /* @__PURE__ */ jsxRuntime.jsx("h4", { children: "Debug Information:" }), /* @__PURE__ */ jsxRuntime.jsxs(DebugSection, { children: [ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Search Results:" }), /* @__PURE__ */ jsxRuntime.jsx(DebugPre, { children: searchResults ? JSON.stringify(searchResults, null, 2) : "No search results yet" }) ] }), searchError && /* @__PURE__ */ jsxRuntime.jsxs(ErrorMessage, { children: [ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Error:" }), " ", searchError ] }), /* @__PURE__ */ jsxRuntime.jsxs(DebugSection, { children: [ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Current View State:" }), /* @__PURE__ */ jsxRuntime.jsx(DebugPre, { children: JSON.stringify(viewState, null, 2) }) ] }), /* @__PURE__ */ jsxRuntime.jsxs(DebugSection, { children: [ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Marker Position:" }), /* @__PURE__ */ jsxRuntime.jsx(DebugPre, { children: JSON.stringify(markerPosition, null, 2) }) ] }), /* @__PURE__ */ jsxRuntime.jsxs(DebugSection, { children: [ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Search Query:" }), /* @__PURE__ */ jsxRuntime.jsx(DebugPre, { children: searchQuery || "No search query" }) ] }), /* @__PURE__ */ jsxRuntime.jsxs(DebugSection, { children: [ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Current Value:" }), /* @__PURE__ */ jsxRuntime.jsx(DebugPre, { children: value ? JSON.stringify(value, null, 2) : "No value set" }) ] }) ] }); } const DebugContainer = styled__default.default.div` margin-top: 20px; padding: 1rem; background-color: #f5f5f5; border-radius: 4px; `; const DebugSection = styled__default.default.div` margin-bottom: 10px; `; const DebugPre = styled__default.default.pre` background: #ffffff; padding: 10px; border-radius: 4px; max-height: 200px; overflow: auto; margin: 5px 0; border: 1px solid #dcdce4; `; const ErrorMessage = styled__default.default.div` color: #d02b20; margin-bottom: 10px; padding: 10px; background-color: #fff5f5; border: 1px solid #ffd7d5; border-radius: 4px; `; function MapBoxField({ name, onChange, value, intlLabel, required }) { const { get } = admin.useFetchClient(); const { config, isLoading, error } = useMapBoxSettings(); const { viewState, markerPosition, setViewState, setMarkerPosition } = useMapLocationHook(value); const { accessToken, debugMode } = config || {}; const [searchQuery, setSearchQuery] = react.useState(""); const [searchResults, setSearchResults] = react.useState(null); const [searchError, setSearchError] = react.useState(null); const updateMarkerPosition = (lng, lat, address) => { setMarkerPosition({ longitude: lng, latitude: lat }); const newValue = { longitude: lng, latitude: lat, address: address || "Selected location", zoom: viewState.zoom, pitch: viewState.pitch, bearing: viewState.bearing }; onChange({ target: { name, value: newValue, type: "json" } }); }; const handleSearch = async () => { if (!searchQuery.trim()) return; try { setSearchError(null); const encodedQuery = encodeURIComponent(searchQuery.trim()); const url = `/strapi-plugin-map-box/location-search/${encodedQuery}`; const { data } = await get(url); setSearchResults(data); if (data.features && data.features[0]) { const [longitude, latitude] = data.features[0].center; setViewState((prev) => ({ ...prev, longitude, latitude, zoom: 14, transitionDuration: 1e3 })); updateMarkerPosition(longitude, latitude, data.features[0].place_name); } else if (data.error) { setSearchError(data.error); } else { setSearchError("No results found"); } } catch (error2) { console.error("Error searching location:", error2); setSearchError(error2 instanceof Error ? error2.message : "An error occurred"); } }; const handleKeyDown = (e) => { if (e.key === "Enter") { e.preventDefault(); handleSearch(); } }; const handleMapClick = (event) => { const { lngLat } = event; updateMarkerPosition(lngLat.lng, lngLat.lat); }; const handleMapMove = (evt) => { setViewState(evt.viewState); }; const handleMarkerDragEnd = (event) => { const { lngLat } = event; updateMarkerPosition(lngLat.lng, lngLat.lat); }; const handlePositionChange = (input) => { try { const value2 = JSON.parse(input); setViewState((prev) => ({ ...prev, longitude: value2.longitude, latitude: value2.latitude, zoom: value2.zoom || prev.zoom, pitch: value2.pitch || prev.pitch, bearing: value2.bearing || prev.bearing })); setMarkerPosition({ longitude: value2.longitude, latitude: value2.latitude }); onChange({ target: { name, value: value2, type: "json" } }); } catch { } }; const finalValue = { longitude: markerPosition.longitude, latitude: markerPosition.latitude, zoom: viewState.zoom, pitch: viewState.pitch, bearing: viewState.bearing, address: value?.address || "Selected location" }; const strValue = JSON.stringify(value || finalValue, null, 2); if (!accessToken || isLoading) { return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Loading..." }); } if (error) { return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [ "Error: ", error ] }); } return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", height: "500px", width: "100%" }, children: [ /* @__PURE__ */ jsxRuntime.jsx( MapSearch, { onSearch: handleSearch, searchQuery, setSearchQuery, handleKeyDown } ), /* @__PURE__ */ jsxRuntime.jsxs( Map__default.default, { ...viewState, onMove: handleMapMove, onClick: handleMapClick, mapStyle: "mapbox://styles/mapbox/streets-v12", mapboxAccessToken: accessToken, attributionControl: false, style: { height: "100%", width: "100%" }, children: [ /* @__PURE__ */ jsxRuntime.jsx(Map.FullscreenControl, {}), /* @__PURE__ */ jsxRuntime.jsx(Map.NavigationControl, {}), /* @__PURE__ */ jsxRuntime.jsx(Map.GeolocateControl, {}), /* @__PURE__ */ jsxRuntime.jsx( Map.Marker, { longitude: markerPosition.longitude, latitude: markerPosition.latitude, color: "#4945ff", draggable: true, onDragEnd: handleMarkerDragEnd } ) ] } ) ] }), debugMode && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name, required, children: [ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: intlLabel?.defaultMessage ?? "Location" }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.JSONInput, { value: strValue, onChange: handlePositionChange }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {}), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}) ] }), debugMode && /* @__PURE__ */ jsxRuntime.jsx( DebugInfo, { viewState, searchResults, searchError, markerPosition, searchQuery, value } ) ] }); } const index = { register(app) { app.customFields.register({ name: "map-box", type: "json", icon: icons.PinMap, intlLabel: { id: "custom.fields.map-box.label", defaultMessage: "Map Box" }, intlDescription: { id: "custom.fields.map-box.description", defaultMessage: "Enter geographic coordinates" }, components: { Input: () => ({ default: MapBoxField }) } }); app.registerPlugin({ id: PLUGIN_ID, initializer: Initializer, isReady: false, name: PLUGIN_ID }); }, async registerTrads({ locales }) { return Promise.all( locales.map(async (locale) => { try { const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("../_chunks/en-B4KWt_jN.js")) }), `./translations/${locale}.json`, 3); return { data, locale }; } catch { return { data: {}, locale }; } }) ); } }; module.exports = index; //# sourceMappingURL=index.js.map