barikoi-map-widget
Version:
A customizable map widget built with React, designed for seamless integration with Barikoi's map services.
468 lines (462 loc) • 16.4 kB
JavaScript
// src/components/BarikoiAutocomplete.tsx
import { useEffect, useRef, useState as useState2 } from "react";
// src/contexts/BarikoiMapProvider.tsx
import { createContext, useState, useContext, useMemo } from "react";
import { jsx } from "react/jsx-runtime";
var BarikoiMapContext = createContext(void 0);
var BarikoiMapProvider = ({ children }) => {
const [searchedPlace, setSearchedPlace] = useState("");
const [selectedPlace, setSelectedPlace] = useState(null);
const [suggestions, setSuggestions] = useState([]);
const [isAutocompleteLoading, setIsAutocompleteLoading] = useState(false);
const [zoomLevel, setZoomLevel] = useState(10);
const [centerPoint, setCenterPoint] = useState({ lat: 23.8103, lng: 90.4125 });
const [markerData, setMarkerData] = useState([]);
const contextValue = useMemo(() => ({
autocomplete: {
searchedPlace,
setSearchedPlace,
selectedPlace,
setSelectedPlace,
suggestions,
setSuggestions,
isAutocompleteLoading,
setIsAutocompleteLoading
},
map: {
zoomLevel,
setZoomLevel,
centerPoint,
setCenterPoint,
markerData,
setMarkerData
}
}), [searchedPlace, setSearchedPlace, selectedPlace, setSelectedPlace, suggestions, setSuggestions, isAutocompleteLoading, setIsAutocompleteLoading, zoomLevel, setZoomLevel, centerPoint, setCenterPoint, markerData, setMarkerData]);
return /* @__PURE__ */ jsx(
BarikoiMapContext.Provider,
{
value: contextValue,
children
}
);
};
var useBarikoiMapContext = () => {
const context = useContext(BarikoiMapContext);
if (!context) {
throw new Error("useBarikoiMap must be used within a BarikoiMapProvider");
}
return context;
};
// src/contexts/hooks/useAutocomplete.ts
var useAutocomplete = () => {
return useBarikoiMapContext().autocomplete;
};
// src/components/BarikoiAutocomplete.tsx
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
var MarkerSVG = () => {
return /* @__PURE__ */ jsx2("div", { style: { display: "inline-block" }, children: /* @__PURE__ */ jsxs("svg", { width: "24", height: "24", fill: "none", viewBox: "0 0 36 44", children: [
/* @__PURE__ */ jsx2(
"path",
{
stroke: "black",
strokeLinecap: "round",
strokeLinejoin: "round",
strokeWidth: "2",
d: "M18 42c2-10 16-11.163 16-24 0-8.837-7.163-16-16-16S2 9.163 2 18c0 12.837 14 14 16 24z"
}
),
/* @__PURE__ */ jsx2(
"path",
{
stroke: "black",
strokeLinecap: "round",
strokeLinejoin: "round",
strokeWidth: "2",
d: "M18 24a6 6 0 100-12 6 6 0 000 12z"
}
)
] }) });
};
var defaultStyles = {
container: {
width: "400px",
position: "relative",
fontFamily: "Arial, sans-serif"
},
input: {
width: "100%",
padding: "10px 30px 10px 10px",
fontSize: "14px",
border: "1px solid #ccc",
borderRadius: "4px",
boxSizing: "border-box",
position: "relative"
},
dropdown: {
position: "absolute",
top: "100%",
left: 0,
overflowY: "auto",
border: "1px solid #ccc",
borderRadius: "4px",
zIndex: 1e3,
boxShadow: "0 4px 8px rgba(0, 0, 0, 0.1)",
transform: "translateY(-10px)",
transition: "opacity 0.3s ease-in-out, transform 0.3s ease-in-out",
display: "none"
},
dropdownVisible: {
display: "block",
// Show when visible
transform: "translateY(0)"
},
dropdownItem: {
padding: "10px",
cursor: "pointer",
borderBottom: "1px solid #f0f0f0",
transition: "background-color 0.2s ease-in-out",
minHeight: "20px"
},
dropdownItemHover: {
backgroundColor: "#f5f5f5"
},
dropdownFooter: {
position: "sticky",
bottom: 0,
left: 0,
backgroundColor: "#fff",
padding: "10px",
fontSize: "10px",
color: "#adbabd",
borderTop: "1px solidrgb(128, 128, 128)"
},
noResult: {
padding: "10px",
color: "#999"
},
clearButton: {
position: "absolute",
top: "10px",
right: "10px",
border: "none",
backgroundColor: "transparent",
cursor: "pointer",
fontSize: "16px",
color: "#999"
}
};
var BarikoiAutocomplete = ({
apiKey,
className = {}
}) => {
const {
searchedPlace,
setSearchedPlace,
selectedPlace,
setSelectedPlace,
suggestions,
setSuggestions,
isAutocompleteLoading,
setIsAutocompleteLoading
} = useAutocomplete();
const debounceRef = useRef(null);
const [isDropdownVisible, setIsDropdownVisible] = useState2(false);
useEffect(() => {
const inputElement = document.querySelector('input[type="text"]');
const handleFocus = () => {
if (suggestions.length > 0) {
setIsDropdownVisible(true);
}
};
const handleBlur = () => {
setTimeout(() => setIsDropdownVisible(false), 200);
};
if (inputElement) {
inputElement.addEventListener("focus", handleFocus);
inputElement.addEventListener("blur", handleBlur);
}
return () => {
if (inputElement) {
inputElement.removeEventListener("focus", handleFocus);
inputElement.removeEventListener("blur", handleBlur);
}
};
}, [suggestions]);
useEffect(() => {
if (!searchedPlace.trim()) {
setSuggestions([]);
setIsDropdownVisible(false);
return;
}
if (searchedPlace === selectedPlace?.name) {
setIsDropdownVisible(false);
return;
}
setIsAutocompleteLoading(true);
if (debounceRef.current) {
clearTimeout(debounceRef.current);
}
debounceRef.current = setTimeout(async () => {
try {
const response = await fetch(
`https://barikoi.xyz/v2/api/search/autocomplete/place?api_key=${apiKey}&q=${searchedPlace}`
);
const { places } = await response.json();
const newSuggestions = places?.map((place, index) => ({
name: place?.address || "Unknown",
...place
})) || [];
setSuggestions(newSuggestions);
if (newSuggestions.length > 0) {
setIsDropdownVisible(true);
}
} catch (error) {
console.error("Error fetching autocomplete data:", error);
setSuggestions([]);
} finally {
setIsAutocompleteLoading(false);
}
}, 300);
}, [searchedPlace, selectedPlace, apiKey]);
const handleChange = (e) => {
setSearchedPlace(e.target.value);
};
const handleSelect = (item) => {
setSearchedPlace(item.name);
setSelectedPlace(item);
setIsDropdownVisible(false);
};
const handleClear = () => {
setSearchedPlace("");
setSelectedPlace(null);
setSuggestions([]);
setIsDropdownVisible(false);
};
const renderSuggestions = () => {
if (isAutocompleteLoading) {
return /* @__PURE__ */ jsx2(
"div",
{
style: defaultStyles.noResult,
className: className.noResult || "",
children: "Searching..."
}
);
}
if (suggestions.length === 0) {
return /* @__PURE__ */ jsx2(
"div",
{
style: defaultStyles.noResult,
className: className.noResult || "",
children: "No results found"
}
);
}
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx2(
"div",
{
style: {
// maxHeight: 'calc(600px - 40px)', // Adjust height to account for footer
overflowY: "auto"
},
children: suggestions.map((item) => /* @__PURE__ */ jsx2(
"div",
{
style: defaultStyles.dropdownItem,
className: className.dropdownItem || "",
onMouseEnter: (e) => e.currentTarget.style.backgroundColor = defaultStyles.dropdownItemHover.backgroundColor,
onMouseLeave: (e) => e.currentTarget.style.backgroundColor = "transparent",
onClick: () => handleSelect(item),
children: /* @__PURE__ */ jsxs(
"div",
{
style: {
display: "grid",
gridTemplateColumns: "auto 1fr",
alignItems: "center",
minHeight: "40px"
},
children: [
/* @__PURE__ */ jsx2(
"div",
{
style: {
display: "flex",
justifyContent: "center",
marginRight: 2
},
children: /* @__PURE__ */ jsx2(MarkerSVG, {})
}
),
/* @__PURE__ */ jsx2("div", { children: item.name })
]
}
)
},
item.id
))
}
),
/* @__PURE__ */ jsxs(
"div",
{
style: defaultStyles.dropdownFooter,
className: className.dropdownFooter || "",
children: [
"Powered by",
" ",
/* @__PURE__ */ jsx2(
"a",
{
href: "https://barikoi.com",
target: "_blank",
rel: "noopener noreferrer",
style: { color: "#00A66B", textDecoration: "none" },
children: "Barikoi"
}
)
]
}
)
] });
};
return /* @__PURE__ */ jsxs("div", { style: defaultStyles.container, className: className.container || "", children: [
/* @__PURE__ */ jsx2(
"input",
{
type: "text",
value: searchedPlace,
onChange: handleChange,
placeholder: "Search Address",
style: defaultStyles.input,
className: className.input || ""
}
),
searchedPlace && /* @__PURE__ */ jsx2(
"button",
{
type: "button",
style: defaultStyles.clearButton,
className: className.clearButton || "",
onClick: handleClear,
children: "X"
}
),
/* @__PURE__ */ jsx2(
"div",
{
style: {
...defaultStyles.dropdown,
...isDropdownVisible ? defaultStyles.dropdownVisible : {}
},
className: className.dropdown || "",
children: renderSuggestions()
}
)
] });
};
var BarikoiAutocomplete_default = BarikoiAutocomplete;
// src/components/BarikoiMap.tsx
import { useEffect as useEffect2, useRef as useRef2 } from "react";
import { Map, Marker, FullscreenControl, GeolocateControl, NavigationControl, ScaleControl } from "react-bkoi-gl";
// src/contexts/hooks/useMap.ts
var useMap = () => {
return useBarikoiMapContext().map;
};
// src/components/BarikoiMap.tsx
import "react-bkoi-gl/styles";
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
var defaultStyles2 = {
container: {
minWidth: "500px",
minHeight: "500px",
overflow: "hidden"
}
};
var BarikoiMap = ({ apiKey, initialViewState, controls, mapStyle, className = {} }) => {
const { centerPoint } = useMap();
const mapStyleUrl = `https://map.barikoi.com/styles/${mapStyle ?? "osm-liberty"}/style.json?key=${apiKey}`;
const mapRef = useRef2(null);
const _initialViewState = {
longitude: 90.36402,
latitude: 23.823731,
minZoom: 4,
maxZoom: 30,
zoom: 13,
bearing: 0,
pitch: 0,
antialias: true,
...initialViewState
};
useEffect2(() => {
if (centerPoint?.lng && centerPoint?.lat) {
mapRef?.current?.flyTo({
center: [centerPoint.lng, centerPoint.lat],
essential: true
});
}
}, [centerPoint]);
return /* @__PURE__ */ jsx3(
"div",
{
style: defaultStyles2.container,
className: className.container || "",
children: /* @__PURE__ */ jsxs2(
Map,
{
ref: mapRef,
mapStyle: mapStyleUrl,
style: { width: "100%", height: "100%" },
initialViewState: _initialViewState,
doubleClickZoom: false,
dragRotate: false,
attributionControl: true,
children: [
controls?.geolocate?.enabled && /* @__PURE__ */ jsx3(GeolocateControl, { position: controls?.geolocate?.position ?? "top-right" }),
controls?.fullscreen?.enabled && /* @__PURE__ */ jsx3(FullscreenControl, { position: controls?.fullscreen?.position ?? "top-right" }),
controls?.navigation?.enabled && /* @__PURE__ */ jsx3(NavigationControl, { position: controls?.navigation?.position ?? "top-right" }),
controls?.scale?.enabled && /* @__PURE__ */ jsx3(ScaleControl, { position: controls?.scale?.position ?? "bottom-right" }),
centerPoint?.lng && centerPoint?.lat && controls?.marker?.enabled && /* @__PURE__ */ jsx3(
Marker,
{
longitude: centerPoint.lng,
latitude: centerPoint.lat,
anchor: "bottom",
children: /* @__PURE__ */ jsx3("img", { width: 50, height: 50, src: controls?.marker?.url ?? "https://maps.barikoi.com/images/icon.png", alt: "marker" })
}
),
/* @__PURE__ */ jsx3(
"div",
{
className: "barikoi-logo",
style: {
width: "90px",
height: "20px",
position: "absolute",
left: 10,
bottom: 8,
backgroundSize: "contain",
backgroundRepeat: "no-repeat",
zIndex: 99999,
backgroundImage: `url('data:image/png;base64,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')`
}
}
)
]
}
)
}
);
};
var BarikoiMap_default = BarikoiMap;
export {
BarikoiAutocomplete_default as BarikoiAutocomplete,
BarikoiMap_default as BarikoiMap,
BarikoiMapProvider,
useAutocomplete,
useBarikoiMapContext,
useMap
};
//# sourceMappingURL=index.mjs.map