barikoi-map-widget
Version:
A customizable map widget built with React, designed for seamless integration with Barikoi's map services.
500 lines (492 loc) • 18.6 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
BarikoiAutocomplete: () => BarikoiAutocomplete_default,
BarikoiMap: () => BarikoiMap_default,
BarikoiMapProvider: () => BarikoiMapProvider,
useAutocomplete: () => useAutocomplete,
useBarikoiMapContext: () => useBarikoiMapContext,
useMap: () => useMap
});
module.exports = __toCommonJS(index_exports);
// src/components/BarikoiAutocomplete.tsx
var import_react2 = require("react");
// src/contexts/BarikoiMapProvider.tsx
var import_react = require("react");
var import_jsx_runtime = require("react/jsx-runtime");
var BarikoiMapContext = (0, import_react.createContext)(void 0);
var BarikoiMapProvider = ({ children }) => {
const [searchedPlace, setSearchedPlace] = (0, import_react.useState)("");
const [selectedPlace, setSelectedPlace] = (0, import_react.useState)(null);
const [suggestions, setSuggestions] = (0, import_react.useState)([]);
const [isAutocompleteLoading, setIsAutocompleteLoading] = (0, import_react.useState)(false);
const [zoomLevel, setZoomLevel] = (0, import_react.useState)(10);
const [centerPoint, setCenterPoint] = (0, import_react.useState)({ lat: 23.8103, lng: 90.4125 });
const [markerData, setMarkerData] = (0, import_react.useState)([]);
const contextValue = (0, import_react.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__ */ (0, import_jsx_runtime.jsx)(
BarikoiMapContext.Provider,
{
value: contextValue,
children
}
);
};
var useBarikoiMapContext = () => {
const context = (0, import_react.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
var import_jsx_runtime2 = require("react/jsx-runtime");
var MarkerSVG = () => {
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "inline-block" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "24", height: "24", fill: "none", viewBox: "0 0 36 44", children: [
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
"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__ */ (0, import_jsx_runtime2.jsx)(
"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 = (0, import_react2.useRef)(null);
const [isDropdownVisible, setIsDropdownVisible] = (0, import_react2.useState)(false);
(0, import_react2.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]);
(0, import_react2.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__ */ (0, import_jsx_runtime2.jsx)(
"div",
{
style: defaultStyles.noResult,
className: className.noResult || "",
children: "Searching..."
}
);
}
if (suggestions.length === 0) {
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
"div",
{
style: defaultStyles.noResult,
className: className.noResult || "",
children: "No results found"
}
);
}
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
"div",
{
style: {
// maxHeight: 'calc(600px - 40px)', // Adjust height to account for footer
overflowY: "auto"
},
children: suggestions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
"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__ */ (0, import_jsx_runtime2.jsxs)(
"div",
{
style: {
display: "grid",
gridTemplateColumns: "auto 1fr",
alignItems: "center",
minHeight: "40px"
},
children: [
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
"div",
{
style: {
display: "flex",
justifyContent: "center",
marginRight: 2
},
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MarkerSVG, {})
}
),
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: item.name })
]
}
)
},
item.id
))
}
),
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
"div",
{
style: defaultStyles.dropdownFooter,
className: className.dropdownFooter || "",
children: [
"Powered by",
" ",
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
"a",
{
href: "https://barikoi.com",
target: "_blank",
rel: "noopener noreferrer",
style: { color: "#00A66B", textDecoration: "none" },
children: "Barikoi"
}
)
]
}
)
] });
};
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles.container, className: className.container || "", children: [
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
"input",
{
type: "text",
value: searchedPlace,
onChange: handleChange,
placeholder: "Search Address",
style: defaultStyles.input,
className: className.input || ""
}
),
searchedPlace && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
"button",
{
type: "button",
style: defaultStyles.clearButton,
className: className.clearButton || "",
onClick: handleClear,
children: "X"
}
),
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
"div",
{
style: {
...defaultStyles.dropdown,
...isDropdownVisible ? defaultStyles.dropdownVisible : {}
},
className: className.dropdown || "",
children: renderSuggestions()
}
)
] });
};
var BarikoiAutocomplete_default = BarikoiAutocomplete;
// src/components/BarikoiMap.tsx
var import_react3 = require("react");
var import_react_bkoi_gl = require("react-bkoi-gl");
// src/contexts/hooks/useMap.ts
var useMap = () => {
return useBarikoiMapContext().map;
};
// src/components/BarikoiMap.tsx
var import_styles = require("react-bkoi-gl/styles");
var import_jsx_runtime3 = require("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 = (0, import_react3.useRef)(null);
const _initialViewState = {
longitude: 90.36402,
latitude: 23.823731,
minZoom: 4,
maxZoom: 30,
zoom: 13,
bearing: 0,
pitch: 0,
antialias: true,
...initialViewState
};
(0, import_react3.useEffect)(() => {
if (centerPoint?.lng && centerPoint?.lat) {
mapRef?.current?.flyTo({
center: [centerPoint.lng, centerPoint.lat],
essential: true
});
}
}, [centerPoint]);
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
"div",
{
style: defaultStyles2.container,
className: className.container || "",
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
import_react_bkoi_gl.Map,
{
ref: mapRef,
mapStyle: mapStyleUrl,
style: { width: "100%", height: "100%" },
initialViewState: _initialViewState,
doubleClickZoom: false,
dragRotate: false,
attributionControl: true,
children: [
controls?.geolocate?.enabled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_bkoi_gl.GeolocateControl, { position: controls?.geolocate?.position ?? "top-right" }),
controls?.fullscreen?.enabled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_bkoi_gl.FullscreenControl, { position: controls?.fullscreen?.position ?? "top-right" }),
controls?.navigation?.enabled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_bkoi_gl.NavigationControl, { position: controls?.navigation?.position ?? "top-right" }),
controls?.scale?.enabled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_bkoi_gl.ScaleControl, { position: controls?.scale?.position ?? "bottom-right" }),
centerPoint?.lng && centerPoint?.lat && controls?.marker?.enabled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
import_react_bkoi_gl.Marker,
{
longitude: centerPoint.lng,
latitude: centerPoint.lat,
anchor: "bottom",
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("img", { width: 50, height: 50, src: controls?.marker?.url ?? "https://maps.barikoi.com/images/icon.png", alt: "marker" })
}
),
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
"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;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
BarikoiAutocomplete,
BarikoiMap,
BarikoiMapProvider,
useAutocomplete,
useBarikoiMapContext,
useMap
});
//# sourceMappingURL=index.js.map