@ef2/store-locator
v0.9.2
Published
A fully customizable **Google Maps Store Locator** built for Next.js and React. Supports: ✅ **Custom Components** (List, Map, Markers, Panels) ✅ **Dynamic Clustering** with customizable colors ✅ **Context & Hooks** for extending behavior ✅ **TypeS
Readme
📍 Store Locator
A fully customizable Google Maps Store Locator built for Next.js and React. Supports:
✅ Custom Components (List, Map, Markers, Panels)
✅ Dynamic Clustering with customizable colors
✅ Context & Hooks for extending behavior
✅ TypeScript Support for full type safety
✅ Next.js App Router (SSR-Compatible)
🚀 Installation
npm install @ef2/store-locator
# or
yarn add @ef2/store-locator🛠️ Basic Usage
Import and use the StoreLocator component in your Next.js App Router.
import { StoreLocator } from "@ef2/store-locator";
import locationsData from "../public/data.json";
const formattedLocations = locationsData.map((location) => ({
position: { lat: location.position.lat, lng: location.position.lng },
slug: location.slug || "",
name: location.name || "",
city: location.city || "",
postalCode: location.postalCode || "",
street: location.street || "",
phone: location.phone || "",
email: location.email || "",
image: location.image || "",
}));
export default function Page() {
return (
<StoreLocator
translations={{
panelTitle: "In de buurt",
locationQuantity: "locatie",
locationQuantity_plural: "locaties",
placeholder: "Zoek op een plaats",
}}
mapOptions={{
defaultZoom: 8,
defaultCenter: { lat: 52.370216, lng: 4.895168 },
mapStyle: {
mapTypeId: "roadmap",
renderingType: "RASTER",
mapId: "71c741f5368dc7b2",
},
}}
apiKey={process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || ""}
locations={formattedLocations}
cluster={{
fillColor: "#000",
fillOpacity: 0.7,
strokeWeight: 2,
strokeColor: "#ffffff",
textColor: "#000000",
}}
/>
);
}🎨 Customizing Components
Every part of the StoreLocator component can be overridden using the components prop.
Example: Override the List Component
import CustomList from "./CustomList";
export default function Page() {
return (
<StoreLocator
locations={formattedLocations}
components={{
List: CustomList, // ✅ Use custom list component
}}
/>
);
}Example: Override the SelectedLocation Component
import SelectedLocationTest from "./SelectedLocationTest";
export default function Page() {
return (
<StoreLocator
locations={formattedLocations}
components={{
SelectedLocation: SelectedLocationTest, // ✅ Custom selected location UI
}}
/>
);
}📦 Component Structure
StoreLocator is modular, meaning you can swap components as needed.
| Component | Description |
|--------------------|--------------------------------------------------------|
| StoreLocator | The main component, includes map, panel, and controls. |
| Map | Renders the Google Map. |
| Marker | Customizable store location markers. |
| Markers | Wrapper for all markers, supports clustering. |
| Panel | Sidebar for location results. |
| List | Displays locations in a list view. |
| PanelTop | The top section of the panel with search/autocomplete. |
| SelectedLocation | The UI shown when a location is selected. |
🌍 Multi-Language Support
<StoreLocator
translations={{
panelTitle: "Near You",
locationQuantity: "location",
locationQuantity_plural: "locations",
placeholder: "Search for a place",
}}
/>🚀 Performance Optimizations
- ✅ Tree-shakable – Only the components you use are included.
- ✅ Lazy-loaded Google Maps – Ensures fast page load times.
- ✅ Uses Context for global state – No unnecessary re-renders.
📦 Importing Individual Hooks & Components
import { useStoreLocator, useStoreLocatorContext } from "@ef2/store-locator/hooks";
import { StoreLocatorProvider } from "@ef2/store-locator/contexts";
import { Location } from "@ef2/store-locator/types";🛠️ Roadmap
- 🔹 Improve SSR support for React Server Components
- 🔹 More customization for clustering and marker icons
- 🔹 Better accessibility for screen readers
📜 License
This project is licensed under the MIT License.
🙌 Contributing
Want to contribute? Open an issue or submit a PR! 🚀
💬 Questions?
For questions or support, feel free to ask!
