mehdi-akbari-map 0.0.9 → 0.1.1

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.
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { MapProps } from '../types';
3
+ export declare const InteractiveMap: React.FC<MapProps>;
4
+ //# sourceMappingURL=InteractiveMap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InteractiveMap.d.ts","sourceRoot":"","sources":["../../src/components/InteractiveMap.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,EAAS,QAAQ,EAAE,MAAM,UAAU,CAAC;AAE3C,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,QAAQ,CAuE7C,CAAC"}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { Store } from '../types';
3
+ interface StoreCardProps {
4
+ store: Store;
5
+ isSelected: boolean;
6
+ onSelect: () => void;
7
+ }
8
+ export declare const StoreCard: React.FC<StoreCardProps>;
9
+ export {};
10
+ //# sourceMappingURL=StoreCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StoreCard.d.ts","sourceRoot":"","sources":["../../src/components/StoreCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,UAAU,cAAc;IACtB,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAwC9C,CAAC"}
package/dist/index.cjs CHANGED
@@ -30,10 +30,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
- NeshanMap: () => Map_default
33
+ NeshanMap: () => InteractiveMap,
34
+ RawMap: () => Map_default
34
35
  });
35
36
  module.exports = __toCommonJS(src_exports);
36
37
 
38
+ // src/components/InteractiveMap.tsx
39
+ var import_react2 = require("react");
40
+
37
41
  // src/components/Map.tsx
38
42
  var import_react = require("react");
39
43
 
@@ -180,8 +184,93 @@ var Map = ({
180
184
  );
181
185
  };
182
186
  var Map_default = Map;
187
+
188
+ // src/components/StoreCard.tsx
189
+ var import_jsx_runtime2 = require("react/jsx-runtime");
190
+ var StoreCard = ({ store, isSelected, onSelect }) => {
191
+ const googleMapUrl = `https://www.google.com/maps/dir/?api=1&destination=${store.lat},${store.lng}`;
192
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
193
+ "div",
194
+ {
195
+ className: `store-card ${isSelected ? "active" : ""}`,
196
+ onClick: onSelect,
197
+ children: [
198
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "store-card-header", children: [
199
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
200
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { className: "store-name", children: store.name }),
201
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "store-city", children: store.city })
202
+ ] }),
203
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "store-price", children: [
204
+ store.price,
205
+ " \u062A\u0648\u0645\u0627\u0646"
206
+ ] })
207
+ ] }),
208
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "store-desc", children: store.desc }),
209
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "store-details-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "store-details-content", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "action-buttons", children: [
210
+ store.phone && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: `tel:${store.phone}`, className: "btn btn-call", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u062A\u0645\u0627\u0633" }) }),
211
+ store.whatsapp && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: `https://wa.me/${store.whatsapp}`, target: "_blank", className: "btn btn-wa", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u0648\u0627\u062A\u0633\u0627\u067E" }) }),
212
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: googleMapUrl, target: "_blank", className: "btn btn-route", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u0645\u0633\u06CC\u0631\u06CC\u0627\u0628\u06CC" }) })
213
+ ] }) }) })
214
+ ]
215
+ }
216
+ );
217
+ };
218
+
219
+ // src/components/InteractiveMap.tsx
220
+ var import_jsx_runtime3 = require("react/jsx-runtime");
221
+ var InteractiveMap = (props) => {
222
+ const [isMobile, setIsMobile] = (0, import_react2.useState)(false);
223
+ const [mapInstance, setMapInstance] = (0, import_react2.useState)(null);
224
+ (0, import_react2.useEffect)(() => {
225
+ const checkMobile = () => setIsMobile(window.innerWidth < 1024);
226
+ checkMobile();
227
+ window.addEventListener("resize", checkMobile);
228
+ return () => window.removeEventListener("resize", checkMobile);
229
+ }, []);
230
+ const handleStoreSelect = (store, index) => {
231
+ props.onMarkerClick?.(store, index, mapInstance);
232
+ };
233
+ const safeMarkers = props.markers || [];
234
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `map-layout-root ${isMobile ? "is-mobile" : "is-desktop"}`, children: [
235
+ !isMobile && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("aside", { className: "sidebar", children: [
236
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("header", { className: "sidebar-header", children: "\u0644\u06CC\u0633\u062A \u0641\u0631\u0648\u0634\u06AF\u0627\u0647\u200C\u0647\u0627" }),
237
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "sidebar-list", children: safeMarkers.map((store, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
238
+ StoreCard,
239
+ {
240
+ store,
241
+ isSelected: props.selectedMarkerId === store.id,
242
+ onSelect: () => handleStoreSelect(store, idx)
243
+ },
244
+ store.id
245
+ )) })
246
+ ] }),
247
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("main", { className: "map-container", children: [
248
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
249
+ Map_default,
250
+ {
251
+ ...props,
252
+ onMapLoad: (map) => {
253
+ setMapInstance(map);
254
+ props.onMapLoad?.(map);
255
+ }
256
+ }
257
+ ),
258
+ props.productName && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "product-badge", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: props.productName }) }),
259
+ isMobile && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mobile-slider", children: safeMarkers.map((store, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
260
+ StoreCard,
261
+ {
262
+ store,
263
+ isSelected: props.selectedMarkerId === store.id,
264
+ onSelect: () => handleStoreSelect(store, idx)
265
+ },
266
+ store.id
267
+ )) })
268
+ ] })
269
+ ] });
270
+ };
183
271
  // Annotate the CommonJS export names for ESM import in node:
184
272
  0 && (module.exports = {
185
- NeshanMap
273
+ NeshanMap,
274
+ RawMap
186
275
  });
187
276
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/Map.tsx","../src/utils/createCustomMarkerElement.ts"],"sourcesContent":["\r\n\r\n\r\nexport { default as NeshanMap } from './components/Map';\r\n\r\n\r\nexport type {\r\n MapProps,\r\n MapOptions,\r\n MarkerData,\r\n MapboxMap,\r\n LngLatLike,\r\n} from './types';\r\n\r\n\r\n\r\n\r\n\r\n\r\nimport './styles.css';","\"use client\";\r\n\r\nimport React, { useEffect, useRef, useState } from 'react';\r\nimport type { MapboxMap, MarkerData, MapProps } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\n\r\nimport '@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\r\n markerLogoUrl = '', \r\n selectedMarkerId = null,\r\n onMarkerClick,\r\n onMapLoad,\r\n className = '',\r\n style = { width: '100%', height: '100%' },\r\n}) => {\r\n const mapContainerRef = useRef<HTMLDivElement>(null);\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n const markersRef = useRef<any[]>([]);\r\n\r\n \r\n useEffect(() => {\r\n let isMounted = true;\r\n \r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n if (isMounted) {\r\n setMapLib(mod.default || mod);\r\n }\r\n });\r\n\r\n return () => {\r\n isMounted = false;\r\n };\r\n }, []);\r\n\r\n \r\n useEffect(() => {\r\n if (!mapLib || !mapContainerRef.current || mapInstance) return;\r\n\r\n const map = new mapLib.Map({\r\n container: mapContainerRef.current,\r\n ...options,\r\n });\r\n\r\n map.on('load', () => {\r\n setMapInstance(map);\r\n onMapLoad?.(map);\r\n });\r\n\r\n \r\n return () => {\r\n if (map) {\r\n map.remove();\r\n setMapInstance(null);\r\n }\r\n };\r\n \r\n \r\n }, [mapLib]); \r\n\r\n \r\n useEffect(() => {\r\n if (!mapInstance || !mapLib) return;\r\n\r\n \r\n markersRef.current.forEach((m) => m.remove());\r\n markersRef.current = [];\r\n\r\n markers.forEach((markerData: MarkerData, index: number) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n \r\n \r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n logoSrc: markerLogoUrl, \r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom', \r\n offset: [0, 0] \r\n })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\r\n\r\n \r\n el.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n onMarkerClick?.(markerData, index, mapInstance);\r\n });\r\n\r\n markersRef.current.push(marker);\r\n });\r\n\r\n \r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, markerLogoUrl, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n style={{ \r\n position: 'relative', \r\n overflow: 'hidden',\r\n ...style \r\n }} \r\n className={`neshan-map-wrapper ${className}`}\r\n >\r\n <div \r\n ref={mapContainerRef} \r\n style={{ width: '100%', height: '100%' }} \r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default Map;","import type { MarkerData } from '../types';\r\n\r\ninterface CreateMarkerOptions {\r\n marker: MarkerData;\r\n isSelected: boolean;\r\n logoSrc?: string;\r\n showPrice?: boolean;\r\n}\r\n\r\nexport function createCustomMarkerElement({\r\n marker,\r\n isSelected,\r\n logoSrc = '',\r\n showPrice = true,\r\n}: CreateMarkerOptions): HTMLElement {\r\n \r\n const container = document.createElement('div');\r\n container.className = 'neshan-marker-container';\r\n\r\n \r\n const body = document.createElement('div');\r\n body.className = `neshan-marker-body ${isSelected ? 'neshan-marker-selected' : ''}`;\r\n \r\n \r\n Object.assign(body.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n transition: 'transform 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n });\r\n\r\n \r\n const iconBox = document.createElement('div');\r\n Object.assign(iconBox.style, {\r\n width: '40px',\r\n height: '40px',\r\n borderRadius: '50%',\r\n backgroundColor: 'white',\r\n border: isSelected ? '3px solid #3b82f6' : '2px solid #ef4444',\r\n boxShadow: '0 4px 8px rgba(0,0,0,0.2)',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n overflow: 'hidden'\r\n });\r\n\r\n if (logoSrc) {\r\n const img = document.createElement('img');\r\n img.src = logoSrc;\r\n img.style.width = '100%';\r\n img.style.height = '100%';\r\n img.style.objectFit = 'cover';\r\n iconBox.appendChild(img);\r\n } else {\r\n iconBox.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n body.appendChild(iconBox);\r\n\r\n \r\n if (showPrice && (marker.price || marker.name)) {\r\n const label = document.createElement('div');\r\n label.className = 'neshan-marker-label';\r\n label.textContent = marker.price ? `${marker.price} ت` : (marker.name ?? '');\r\n body.appendChild(label);\r\n }\r\n\r\n container.appendChild(body);\r\n return container;\r\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/InteractiveMap.tsx","../src/components/Map.tsx","../src/utils/createCustomMarkerElement.ts","../src/components/StoreCard.tsx"],"sourcesContent":["\r\nimport './styles.css';\r\n\r\n\r\nexport { InteractiveMap as NeshanMap } from './components/InteractiveMap';\r\n\r\n\r\nexport { default as RawMap } from './components/Map';\r\n\r\n\r\nexport type {\r\n MapProps,\r\n MapOptions,\r\n MarkerData,\r\n Store,\r\n MapboxMap,\r\n LngLatLike,\r\n} from './types';","\"use client\";\r\n\r\nimport React, { useState, useEffect } from 'react';\r\nimport Map from './Map';\r\nimport { StoreCard } from './StoreCard';\r\nimport { Store, MapProps } from '../types';\r\n\r\nexport const InteractiveMap: React.FC<MapProps> = (props) => {\r\n const [isMobile, setIsMobile] = useState(false);\r\n // ✅ ذخیره نمونه نقشه برای پاس دادن به کلیک مارکر\r\n const [mapInstance, setMapInstance] = useState<any>(null);\r\n\r\n useEffect(() => {\r\n const checkMobile = () => setIsMobile(window.innerWidth < 1024);\r\n checkMobile();\r\n window.addEventListener('resize', checkMobile);\r\n return () => window.removeEventListener('resize', checkMobile);\r\n }, []);\r\n\r\n const handleStoreSelect = (store: Store, index: number) => {\r\n // ✅ حالا دیگر null نمی‌فرستیم، نمونه واقعی نقشه را می‌فرستیم\r\n props.onMarkerClick?.(store, index, mapInstance);\r\n };\r\n\r\n // اطمینان از اینکه markers همیشه یک آرایه است\r\n const safeMarkers = props.markers || [];\r\n\r\n return (\r\n <div className={`map-layout-root ${isMobile ? 'is-mobile' : 'is-desktop'}`}>\r\n \r\n {!isMobile && (\r\n <aside className=\"sidebar\">\r\n <header className=\"sidebar-header\">لیست فروشگاه‌ها</header>\r\n <div className=\"sidebar-list\">\r\n {/* ✅ استفاده از safeMarkers برای جلوگیری از خطای undefined */}\r\n {safeMarkers.map((store, idx) => (\r\n <StoreCard \r\n key={store.id} \r\n store={store} \r\n isSelected={props.selectedMarkerId === store.id}\r\n onSelect={() => handleStoreSelect(store, idx)}\r\n />\r\n ))}\r\n </div>\r\n </aside>\r\n )}\r\n\r\n <main className=\"map-container\">\r\n {/* ✅ دریافت نمونه نقشه وقتی لود شد */}\r\n <Map \r\n {...props} \r\n onMapLoad={(map) => {\r\n setMapInstance(map);\r\n props.onMapLoad?.(map);\r\n }} \r\n />\r\n \r\n {props.productName && (\r\n <div className=\"product-badge\">\r\n <span>{props.productName}</span>\r\n </div>\r\n )}\r\n\r\n {isMobile && (\r\n <div className=\"mobile-slider\">\r\n {safeMarkers.map((store, idx) => (\r\n <StoreCard \r\n key={store.id} \r\n store={store} \r\n isSelected={props.selectedMarkerId === store.id}\r\n onSelect={() => handleStoreSelect(store, idx)}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </main>\r\n </div>\r\n );\r\n};","\"use client\";\r\n\r\nimport React, { useEffect, useRef, useState } from 'react';\r\nimport type { MapboxMap, MarkerData, MapProps } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\n\r\nimport '@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\r\n markerLogoUrl = '', \r\n selectedMarkerId = null,\r\n onMarkerClick,\r\n onMapLoad,\r\n className = '',\r\n style = { width: '100%', height: '100%' },\r\n}) => {\r\n const mapContainerRef = useRef<HTMLDivElement>(null);\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n const markersRef = useRef<any[]>([]);\r\n\r\n \r\n useEffect(() => {\r\n let isMounted = true;\r\n \r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n if (isMounted) {\r\n setMapLib(mod.default || mod);\r\n }\r\n });\r\n\r\n return () => {\r\n isMounted = false;\r\n };\r\n }, []);\r\n\r\n \r\n useEffect(() => {\r\n if (!mapLib || !mapContainerRef.current || mapInstance) return;\r\n\r\n const map = new mapLib.Map({\r\n container: mapContainerRef.current,\r\n ...options,\r\n });\r\n\r\n map.on('load', () => {\r\n setMapInstance(map);\r\n onMapLoad?.(map);\r\n });\r\n\r\n \r\n return () => {\r\n if (map) {\r\n map.remove();\r\n setMapInstance(null);\r\n }\r\n };\r\n \r\n \r\n }, [mapLib]); \r\n\r\n \r\n useEffect(() => {\r\n if (!mapInstance || !mapLib) return;\r\n\r\n \r\n markersRef.current.forEach((m) => m.remove());\r\n markersRef.current = [];\r\n\r\n markers.forEach((markerData: MarkerData, index: number) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n \r\n \r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n logoSrc: markerLogoUrl, \r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom', \r\n offset: [0, 0] \r\n })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\r\n\r\n \r\n el.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n onMarkerClick?.(markerData, index, mapInstance);\r\n });\r\n\r\n markersRef.current.push(marker);\r\n });\r\n\r\n \r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, markerLogoUrl, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n style={{ \r\n position: 'relative', \r\n overflow: 'hidden',\r\n ...style \r\n }} \r\n className={`neshan-map-wrapper ${className}`}\r\n >\r\n <div \r\n ref={mapContainerRef} \r\n style={{ width: '100%', height: '100%' }} \r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default Map;","import type { MarkerData } from '../types';\r\n\r\ninterface CreateMarkerOptions {\r\n marker: MarkerData;\r\n isSelected: boolean;\r\n logoSrc?: string;\r\n showPrice?: boolean;\r\n}\r\n\r\nexport function createCustomMarkerElement({\r\n marker,\r\n isSelected,\r\n logoSrc = '',\r\n showPrice = true,\r\n}: CreateMarkerOptions): HTMLElement {\r\n \r\n const container = document.createElement('div');\r\n container.className = 'neshan-marker-container';\r\n\r\n \r\n const body = document.createElement('div');\r\n body.className = `neshan-marker-body ${isSelected ? 'neshan-marker-selected' : ''}`;\r\n \r\n \r\n Object.assign(body.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n transition: 'transform 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n });\r\n\r\n \r\n const iconBox = document.createElement('div');\r\n Object.assign(iconBox.style, {\r\n width: '40px',\r\n height: '40px',\r\n borderRadius: '50%',\r\n backgroundColor: 'white',\r\n border: isSelected ? '3px solid #3b82f6' : '2px solid #ef4444',\r\n boxShadow: '0 4px 8px rgba(0,0,0,0.2)',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n overflow: 'hidden'\r\n });\r\n\r\n if (logoSrc) {\r\n const img = document.createElement('img');\r\n img.src = logoSrc;\r\n img.style.width = '100%';\r\n img.style.height = '100%';\r\n img.style.objectFit = 'cover';\r\n iconBox.appendChild(img);\r\n } else {\r\n iconBox.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n body.appendChild(iconBox);\r\n\r\n \r\n if (showPrice && (marker.price || marker.name)) {\r\n const label = document.createElement('div');\r\n label.className = 'neshan-marker-label';\r\n label.textContent = marker.price ? `${marker.price} ت` : (marker.name ?? '');\r\n body.appendChild(label);\r\n }\r\n\r\n container.appendChild(body);\r\n return container;\r\n}","import React from 'react';\r\nimport { Store } from '../types';\r\n\r\ninterface StoreCardProps {\r\n store: Store;\r\n isSelected: boolean;\r\n onSelect: () => void;\r\n}\r\n\r\nexport const StoreCard: React.FC<StoreCardProps> = ({ store, isSelected, onSelect }) => {\r\n const googleMapUrl = `https://www.google.com/maps/dir/?api=1&destination=${store.lat},${store.lng}`;\r\n\r\n return (\r\n <div \r\n className={`store-card ${isSelected ? 'active' : ''}`}\r\n onClick={onSelect}\r\n >\r\n <div className=\"store-card-header\">\r\n <div>\r\n <h4 className=\"store-name\">{store.name}</h4>\r\n <span className=\"store-city\">{store.city}</span>\r\n </div>\r\n <div className=\"store-price\">{store.price} تومان</div>\r\n </div>\r\n\r\n <p className=\"store-desc\">{store.desc}</p>\r\n\r\n {/* بخش آکاردئونی با CSS Animation */}\r\n <div className=\"store-details-wrapper\">\r\n <div className=\"store-details-content\">\r\n <div className=\"action-buttons\">\r\n {store.phone && (\r\n <a href={`tel:${store.phone}`} className=\"btn btn-call\">\r\n <span>تماس</span>\r\n </a>\r\n )}\r\n {store.whatsapp && (\r\n <a href={`https://wa.me/${store.whatsapp}`} target=\"_blank\" className=\"btn btn-wa\">\r\n <span>واتساپ</span>\r\n </a>\r\n )}\r\n <a href={googleMapUrl} target=\"_blank\" className=\"btn btn-route\">\r\n <span>مسیریابی</span>\r\n </a>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};"],"mappings":"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","names":["import_react","import_jsx_runtime","import_jsx_runtime"]}
package/dist/index.css CHANGED
@@ -1,40 +1,138 @@
1
1
  /* src/styles.css */
2
- .neshan-marker-container {
3
- pointer-events: auto;
4
- will-change: auto;
2
+ .map-layout-root {
3
+ display: flex;
4
+ width: 100%;
5
+ height: 100%;
6
+ direction: rtl;
7
+ font-family: inherit;
8
+ }
9
+ .sidebar {
10
+ width: 350px;
11
+ background: #fff;
12
+ border-left: 1px solid #eee;
13
+ display: flex;
14
+ flex-direction: column;
15
+ z-index: 10;
16
+ }
17
+ .sidebar-header {
18
+ padding: 20px;
19
+ font-weight: bold;
20
+ border-bottom: 1px solid #eee;
5
21
  }
6
- .neshan-marker-body {
22
+ .sidebar-list {
23
+ flex: 1;
24
+ overflow-y: auto;
25
+ }
26
+ .map-container {
27
+ flex: 1;
28
+ position: relative;
29
+ }
30
+ .store-card {
31
+ padding: 15px;
32
+ border-bottom: 1px solid #f0f0f0;
7
33
  cursor: pointer;
8
- transform-origin: bottom center;
34
+ transition: background 0.2s;
35
+ }
36
+ .store-card:hover {
37
+ background: #f9f9f9;
38
+ }
39
+ .store-card.active {
40
+ background: #f0f7ff;
41
+ border-right: 4px solid #3b82f6;
42
+ }
43
+ .store-card-header {
44
+ display: flex;
45
+ justify-content: space-between;
46
+ margin-bottom: 8px;
47
+ }
48
+ .store-name {
49
+ margin: 0;
50
+ font-size: 15px;
51
+ color: #1a1a1a;
52
+ }
53
+ .store-city {
54
+ font-size: 12px;
55
+ color: #777;
56
+ }
57
+ .store-price {
58
+ color: #059669;
59
+ font-weight: bold;
60
+ font-size: 14px;
9
61
  }
10
- .neshan-marker-body:hover {
11
- transform: scale(1.2) !important;
12
- z-index: 999;
62
+ .store-desc {
63
+ font-size: 12px;
64
+ color: #555;
65
+ line-height: 1.6;
66
+ }
67
+ .store-details-wrapper {
68
+ display: grid;
69
+ grid-template-rows: 0fr;
70
+ transition: grid-template-rows 0.3s ease-out;
71
+ overflow: hidden;
72
+ }
73
+ .active .store-details-wrapper {
74
+ grid-template-rows: 1fr;
75
+ margin-top: 12px;
76
+ }
77
+ .store-details-content {
78
+ min-height: 0;
79
+ }
80
+ .action-buttons {
81
+ display: flex;
82
+ gap: 8px;
83
+ }
84
+ .btn {
85
+ flex: 1;
86
+ padding: 8px;
87
+ border-radius: 6px;
88
+ text-align: center;
89
+ text-decoration: none;
90
+ font-size: 12px;
91
+ color: #fff;
92
+ transition: opacity 0.2s;
93
+ }
94
+ .btn:hover {
95
+ opacity: 0.9;
96
+ }
97
+ .btn-call {
98
+ background: #3b82f6;
99
+ }
100
+ .btn-wa {
101
+ background: #10b981;
102
+ }
103
+ .btn-route {
104
+ background: #8b5cf6;
105
+ }
106
+ .is-mobile .mobile-slider {
107
+ position: absolute;
108
+ bottom: 20px;
109
+ left: 0;
110
+ right: 0;
111
+ display: flex;
112
+ gap: 12px;
113
+ padding: 0 20px;
114
+ overflow-x: auto;
115
+ scroll-snap-type: x mandatory;
116
+ pointer-events: none;
117
+ }
118
+ .is-mobile .store-card {
119
+ min-width: 280px;
120
+ background: #fff;
121
+ border-radius: 12px;
122
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
123
+ pointer-events: auto;
124
+ scroll-snap-align: center;
13
125
  }
14
- .neshan-marker-label {
15
- background: white;
16
- color: #1f2937;
17
- font-size: 11px;
126
+ .product-badge {
127
+ position: absolute;
128
+ top: 20px;
129
+ right: 20px;
130
+ background: rgba(255, 255, 255, 0.9);
131
+ padding: 8px 15px;
132
+ border-radius: 8px;
133
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
18
134
  font-weight: bold;
19
- padding: 3px 8px;
20
- border-radius: 4px;
21
- margin-top: 4px;
22
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
23
- white-space: nowrap;
24
- border: 1px solid #e5e7eb;
25
- }
26
- .neshan-marker-selected .neshan-marker-body {
27
- animation: marker-pulse 1.5s infinite ease-in-out;
28
- }
29
- @keyframes marker-pulse {
30
- 0% {
31
- transform: scale(1.2);
32
- }
33
- 50% {
34
- transform: scale(1.3);
35
- }
36
- 100% {
37
- transform: scale(1.2);
38
- }
135
+ font-size: 13px;
136
+ z-index: 5;
39
137
  }
40
138
  /*# sourceMappingURL=index.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/styles.css"],"sourcesContent":["\r\n.neshan-marker-container {\r\n pointer-events: auto;\r\n will-change: auto;\r\n}\r\n\r\n\r\n.neshan-marker-body {\r\n cursor: pointer;\r\n transform-origin: bottom center;\r\n}\r\n\r\n.neshan-marker-body:hover {\r\n transform: scale(1.2) !important;\r\n z-index: 999;\r\n}\r\n\r\n.neshan-marker-label {\r\n background: white;\r\n color: #1f2937;\r\n font-size: 11px;\r\n font-weight: bold;\r\n padding: 3px 8px;\r\n border-radius: 4px;\r\n margin-top: 4px;\r\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n white-space: nowrap;\r\n border: 1px solid #e5e7eb;\r\n}\r\n\r\n\r\n.neshan-marker-selected .neshan-marker-body {\r\n animation: marker-pulse 1.5s infinite ease-in-out;\r\n}\r\n\r\n@keyframes marker-pulse {\r\n 0% { transform: scale(1.2); }\r\n 50% { transform: scale(1.3); }\r\n 100% { transform: scale(1.2); }\r\n}"],"mappings":";AACA,CAAC;AACC,kBAAgB;AAChB,eAAa;AACf;AAGA,CAAC;AACC,UAAQ;AACR,oBAAkB,OAAO;AAC3B;AAEA,CALC,kBAKkB;AACjB,aAAW,MAAM;AACjB,WAAS;AACX;AAEA,CAAC;AACC,cAAY;AACZ,SAAO;AACP,aAAW;AACX,eAAa;AACb,WAAS,IAAI;AACb,iBAAe;AACf,cAAY;AACZ,cAAY,EAAE,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACpC,eAAa;AACb,UAAQ,IAAI,MAAM;AACpB;AAGA,CAAC,uBAAuB,CAxBvB;AAyBC,aAAW,aAAa,KAAK,SAAS;AACxC;AAEA,WAHa;AAIX;AAAK,eAAW,MAAM;AAAM;AAC5B;AAAM,eAAW,MAAM;AAAM;AAC7B;AAAO,eAAW,MAAM;AAAM;AAChC;","names":[]}
1
+ {"version":3,"sources":["../src/styles.css"],"sourcesContent":[".map-layout-root {\r\n display: flex;\r\n width: 100%;\r\n height: 100%;\r\n direction: rtl;\r\n font-family: inherit;\r\n}\r\n\r\n/* Sidebar Desktop */\r\n.sidebar {\r\n width: 350px;\r\n background: #fff;\r\n border-left: 1px solid #eee;\r\n display: flex;\r\n flex-direction: column;\r\n z-index: 10;\r\n}\r\n\r\n.sidebar-header {\r\n padding: 20px;\r\n font-weight: bold;\r\n border-bottom: 1px solid #eee;\r\n}\r\n\r\n.sidebar-list {\r\n flex: 1;\r\n overflow-y: auto;\r\n}\r\n\r\n/* Map Section */\r\n.map-container {\r\n flex: 1;\r\n position: relative;\r\n}\r\n\r\n/* Store Card Style */\r\n.store-card {\r\n padding: 15px;\r\n border-bottom: 1px solid #f0f0f0;\r\n cursor: pointer;\r\n transition: background 0.2s;\r\n}\r\n\r\n.store-card:hover { background: #f9f9f9; }\r\n.store-card.active { background: #f0f7ff; border-right: 4px solid #3b82f6; }\r\n\r\n.store-card-header { display: flex; justify-content: space-between; margin-bottom: 8px; }\r\n.store-name { margin: 0; font-size: 15px; color: #1a1a1a; }\r\n.store-city { font-size: 12px; color: #777; }\r\n.store-price { color: #059669; font-weight: bold; font-size: 14px; }\r\n.store-desc { font-size: 12px; color: #555; line-height: 1.6; }\r\n\r\n/* CSS Accordion Effect */\r\n.store-details-wrapper {\r\n display: grid;\r\n grid-template-rows: 0fr;\r\n transition: grid-template-rows 0.3s ease-out;\r\n overflow: hidden;\r\n}\r\n\r\n.active .store-details-wrapper {\r\n grid-template-rows: 1fr;\r\n margin-top: 12px;\r\n}\r\n\r\n.store-details-content { min-height: 0; }\r\n\r\n.action-buttons {\r\n display: flex;\r\n gap: 8px;\r\n}\r\n\r\n.btn {\r\n flex: 1;\r\n padding: 8px;\r\n border-radius: 6px;\r\n text-align: center;\r\n text-decoration: none;\r\n font-size: 12px;\r\n color: #fff;\r\n transition: opacity 0.2s;\r\n}\r\n\r\n.btn:hover { opacity: 0.9; }\r\n.btn-call { background: #3b82f6; }\r\n.btn-wa { background: #10b981; }\r\n.btn-route { background: #8b5cf6; }\r\n\r\n/* Mobile View */\r\n.is-mobile .mobile-slider {\r\n position: absolute;\r\n bottom: 20px;\r\n left: 0;\r\n right: 0;\r\n display: flex;\r\n gap: 12px;\r\n padding: 0 20px;\r\n overflow-x: auto;\r\n scroll-snap-type: x mandatory;\r\n pointer-events: none; /* اجازه کلیک روی نقشه در جاهای خالی */\r\n}\r\n\r\n.is-mobile .store-card {\r\n min-width: 280px;\r\n background: #fff;\r\n border-radius: 12px;\r\n box-shadow: 0 4px 15px rgba(0,0,0,0.15);\r\n pointer-events: auto;\r\n scroll-snap-align: center;\r\n}\r\n\r\n.product-badge {\r\n position: absolute;\r\n top: 20px;\r\n right: 20px;\r\n background: rgba(255, 255, 255, 0.9);\r\n padding: 8px 15px;\r\n border-radius: 8px;\r\n box-shadow: 0 2px 10px rgba(0,0,0,0.1);\r\n font-weight: bold;\r\n font-size: 13px;\r\n z-index: 5;\r\n}"],"mappings":";AAAA,CAAC;AACC,WAAS;AACT,SAAO;AACP,UAAQ;AACR,aAAW;AACX,eAAa;AACf;AAGA,CAAC;AACC,SAAO;AACP,cAAY;AACZ,eAAa,IAAI,MAAM;AACvB,WAAS;AACT,kBAAgB;AAChB,WAAS;AACX;AAEA,CAAC;AACC,WAAS;AACT,eAAa;AACb,iBAAe,IAAI,MAAM;AAC3B;AAEA,CAAC;AACC,QAAM;AACN,cAAY;AACd;AAGA,CAAC;AACC,QAAM;AACN,YAAU;AACZ;AAGA,CAAC;AACC,WAAS;AACT,iBAAe,IAAI,MAAM;AACzB,UAAQ;AACR,cAAY,WAAW;AACzB;AAEA,CAPC,UAOU;AAAS,cAAY;AAAS;AACzC,CARC,UAQU,CAAC;AAAS,cAAY;AAAS,gBAAc,IAAI,MAAM;AAAS;AAE3E,CAAC;AAAoB,WAAS;AAAM,mBAAiB;AAAe,iBAAe;AAAK;AACxF,CAAC;AAAa,UAAQ;AAAG,aAAW;AAAM,SAAO;AAAS;AAC1D,CAAC;AAAa,aAAW;AAAM,SAAO;AAAM;AAC5C,CAAC;AAAc,SAAO;AAAS,eAAa;AAAM,aAAW;AAAM;AACnE,CAAC;AAAa,aAAW;AAAM,SAAO;AAAM,eAAa;AAAK;AAG9D,CAAC;AACC,WAAS;AACT,sBAAoB;AACpB,cAAY,mBAAmB,KAAK;AACpC,YAAU;AACZ;AAEA,CAhBY,OAgBJ,CAPP;AAQC,sBAAoB;AACpB,cAAY;AACd;AAEA,CAAC;AAAwB,cAAY;AAAG;AAExC,CAAC;AACC,WAAS;AACT,OAAK;AACP;AAEA,CAAC;AACC,QAAM;AACN,WAAS;AACT,iBAAe;AACf,cAAY;AACZ,mBAAiB;AACjB,aAAW;AACX,SAAO;AACP,cAAY,QAAQ;AACtB;AAEA,CAXC,GAWG;AAAS,WAAS;AAAK;AAC3B,CAAC;AAAW,cAAY;AAAS;AACjC,CAAC;AAAS,cAAY;AAAS;AAC/B,CAAC;AAAY,cAAY;AAAS;AAGlC,CAAC,UAAU,CAAC;AACV,YAAU;AACV,UAAQ;AACR,QAAM;AACN,SAAO;AACP,WAAS;AACT,OAAK;AACL,WAAS,EAAE;AACX,cAAY;AACZ,oBAAkB,EAAE;AACpB,kBAAgB;AAClB;AAEA,CAbC,UAaU,CAlEV;AAmEC,aAAW;AACX,cAAY;AACZ,iBAAe;AACf,cAAY,EAAE,IAAI,KAAK,KAAK,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC;AAClC,kBAAgB;AAChB,qBAAmB;AACrB;AAEA,CAAC;AACC,YAAU;AACV,OAAK;AACL,SAAO;AACP,cAAY,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AAChC,WAAS,IAAI;AACb,iBAAe;AACf,cAAY,EAAE,IAAI,KAAK,KAAK,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC;AAClC,eAAa;AACb,aAAW;AACX,WAAS;AACX;","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { default as NeshanMap } from './components/Map';
2
- export type { MapProps, MapOptions, MarkerData, MapboxMap, LngLatLike, } from './types';
3
1
  import './styles.css';
2
+ export { InteractiveMap as NeshanMap } from './components/InteractiveMap';
3
+ export { default as RawMap } from './components/Map';
4
+ export type { MapProps, MapOptions, MarkerData, Store, MapboxMap, LngLatLike, } from './types';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGxD,YAAY,EACV,QAAQ,EACR,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,GACX,MAAM,SAAS,CAAC;AAOjB,OAAO,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,cAAc,CAAC;AAGtB,OAAO,EAAE,cAAc,IAAI,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAG1E,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAGrD,YAAY,EACV,QAAQ,EACR,UAAU,EACV,UAAU,EACV,KAAK,EACL,SAAS,EACT,UAAU,GACX,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
+ // src/components/InteractiveMap.tsx
2
+ import { useState as useState2, useEffect as useEffect2 } from "react";
3
+
1
4
  // src/components/Map.tsx
2
5
  import { useEffect, useRef, useState } from "react";
3
6
 
@@ -144,7 +147,92 @@ var Map = ({
144
147
  );
145
148
  };
146
149
  var Map_default = Map;
150
+
151
+ // src/components/StoreCard.tsx
152
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
153
+ var StoreCard = ({ store, isSelected, onSelect }) => {
154
+ const googleMapUrl = `https://www.google.com/maps/dir/?api=1&destination=${store.lat},${store.lng}`;
155
+ return /* @__PURE__ */ jsxs(
156
+ "div",
157
+ {
158
+ className: `store-card ${isSelected ? "active" : ""}`,
159
+ onClick: onSelect,
160
+ children: [
161
+ /* @__PURE__ */ jsxs("div", { className: "store-card-header", children: [
162
+ /* @__PURE__ */ jsxs("div", { children: [
163
+ /* @__PURE__ */ jsx2("h4", { className: "store-name", children: store.name }),
164
+ /* @__PURE__ */ jsx2("span", { className: "store-city", children: store.city })
165
+ ] }),
166
+ /* @__PURE__ */ jsxs("div", { className: "store-price", children: [
167
+ store.price,
168
+ " \u062A\u0648\u0645\u0627\u0646"
169
+ ] })
170
+ ] }),
171
+ /* @__PURE__ */ jsx2("p", { className: "store-desc", children: store.desc }),
172
+ /* @__PURE__ */ jsx2("div", { className: "store-details-wrapper", children: /* @__PURE__ */ jsx2("div", { className: "store-details-content", children: /* @__PURE__ */ jsxs("div", { className: "action-buttons", children: [
173
+ store.phone && /* @__PURE__ */ jsx2("a", { href: `tel:${store.phone}`, className: "btn btn-call", children: /* @__PURE__ */ jsx2("span", { children: "\u062A\u0645\u0627\u0633" }) }),
174
+ store.whatsapp && /* @__PURE__ */ jsx2("a", { href: `https://wa.me/${store.whatsapp}`, target: "_blank", className: "btn btn-wa", children: /* @__PURE__ */ jsx2("span", { children: "\u0648\u0627\u062A\u0633\u0627\u067E" }) }),
175
+ /* @__PURE__ */ jsx2("a", { href: googleMapUrl, target: "_blank", className: "btn btn-route", children: /* @__PURE__ */ jsx2("span", { children: "\u0645\u0633\u06CC\u0631\u06CC\u0627\u0628\u06CC" }) })
176
+ ] }) }) })
177
+ ]
178
+ }
179
+ );
180
+ };
181
+
182
+ // src/components/InteractiveMap.tsx
183
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
184
+ var InteractiveMap = (props) => {
185
+ const [isMobile, setIsMobile] = useState2(false);
186
+ const [mapInstance, setMapInstance] = useState2(null);
187
+ useEffect2(() => {
188
+ const checkMobile = () => setIsMobile(window.innerWidth < 1024);
189
+ checkMobile();
190
+ window.addEventListener("resize", checkMobile);
191
+ return () => window.removeEventListener("resize", checkMobile);
192
+ }, []);
193
+ const handleStoreSelect = (store, index) => {
194
+ props.onMarkerClick?.(store, index, mapInstance);
195
+ };
196
+ const safeMarkers = props.markers || [];
197
+ return /* @__PURE__ */ jsxs2("div", { className: `map-layout-root ${isMobile ? "is-mobile" : "is-desktop"}`, children: [
198
+ !isMobile && /* @__PURE__ */ jsxs2("aside", { className: "sidebar", children: [
199
+ /* @__PURE__ */ jsx3("header", { className: "sidebar-header", children: "\u0644\u06CC\u0633\u062A \u0641\u0631\u0648\u0634\u06AF\u0627\u0647\u200C\u0647\u0627" }),
200
+ /* @__PURE__ */ jsx3("div", { className: "sidebar-list", children: safeMarkers.map((store, idx) => /* @__PURE__ */ jsx3(
201
+ StoreCard,
202
+ {
203
+ store,
204
+ isSelected: props.selectedMarkerId === store.id,
205
+ onSelect: () => handleStoreSelect(store, idx)
206
+ },
207
+ store.id
208
+ )) })
209
+ ] }),
210
+ /* @__PURE__ */ jsxs2("main", { className: "map-container", children: [
211
+ /* @__PURE__ */ jsx3(
212
+ Map_default,
213
+ {
214
+ ...props,
215
+ onMapLoad: (map) => {
216
+ setMapInstance(map);
217
+ props.onMapLoad?.(map);
218
+ }
219
+ }
220
+ ),
221
+ props.productName && /* @__PURE__ */ jsx3("div", { className: "product-badge", children: /* @__PURE__ */ jsx3("span", { children: props.productName }) }),
222
+ isMobile && /* @__PURE__ */ jsx3("div", { className: "mobile-slider", children: safeMarkers.map((store, idx) => /* @__PURE__ */ jsx3(
223
+ StoreCard,
224
+ {
225
+ store,
226
+ isSelected: props.selectedMarkerId === store.id,
227
+ onSelect: () => handleStoreSelect(store, idx)
228
+ },
229
+ store.id
230
+ )) })
231
+ ] })
232
+ ] });
233
+ };
147
234
  export {
148
- Map_default as NeshanMap
235
+ InteractiveMap as NeshanMap,
236
+ Map_default as RawMap
149
237
  };
150
238
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Map.tsx","../src/utils/createCustomMarkerElement.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport React, { useEffect, useRef, useState } from 'react';\r\nimport type { MapboxMap, MarkerData, MapProps } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\n\r\nimport '@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\r\n markerLogoUrl = '', \r\n selectedMarkerId = null,\r\n onMarkerClick,\r\n onMapLoad,\r\n className = '',\r\n style = { width: '100%', height: '100%' },\r\n}) => {\r\n const mapContainerRef = useRef<HTMLDivElement>(null);\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n const markersRef = useRef<any[]>([]);\r\n\r\n \r\n useEffect(() => {\r\n let isMounted = true;\r\n \r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n if (isMounted) {\r\n setMapLib(mod.default || mod);\r\n }\r\n });\r\n\r\n return () => {\r\n isMounted = false;\r\n };\r\n }, []);\r\n\r\n \r\n useEffect(() => {\r\n if (!mapLib || !mapContainerRef.current || mapInstance) return;\r\n\r\n const map = new mapLib.Map({\r\n container: mapContainerRef.current,\r\n ...options,\r\n });\r\n\r\n map.on('load', () => {\r\n setMapInstance(map);\r\n onMapLoad?.(map);\r\n });\r\n\r\n \r\n return () => {\r\n if (map) {\r\n map.remove();\r\n setMapInstance(null);\r\n }\r\n };\r\n \r\n \r\n }, [mapLib]); \r\n\r\n \r\n useEffect(() => {\r\n if (!mapInstance || !mapLib) return;\r\n\r\n \r\n markersRef.current.forEach((m) => m.remove());\r\n markersRef.current = [];\r\n\r\n markers.forEach((markerData: MarkerData, index: number) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n \r\n \r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n logoSrc: markerLogoUrl, \r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom', \r\n offset: [0, 0] \r\n })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\r\n\r\n \r\n el.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n onMarkerClick?.(markerData, index, mapInstance);\r\n });\r\n\r\n markersRef.current.push(marker);\r\n });\r\n\r\n \r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, markerLogoUrl, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n style={{ \r\n position: 'relative', \r\n overflow: 'hidden',\r\n ...style \r\n }} \r\n className={`neshan-map-wrapper ${className}`}\r\n >\r\n <div \r\n ref={mapContainerRef} \r\n style={{ width: '100%', height: '100%' }} \r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default Map;","import type { MarkerData } from '../types';\r\n\r\ninterface CreateMarkerOptions {\r\n marker: MarkerData;\r\n isSelected: boolean;\r\n logoSrc?: string;\r\n showPrice?: boolean;\r\n}\r\n\r\nexport function createCustomMarkerElement({\r\n marker,\r\n isSelected,\r\n logoSrc = '',\r\n showPrice = true,\r\n}: CreateMarkerOptions): HTMLElement {\r\n \r\n const container = document.createElement('div');\r\n container.className = 'neshan-marker-container';\r\n\r\n \r\n const body = document.createElement('div');\r\n body.className = `neshan-marker-body ${isSelected ? 'neshan-marker-selected' : ''}`;\r\n \r\n \r\n Object.assign(body.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n transition: 'transform 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n });\r\n\r\n \r\n const iconBox = document.createElement('div');\r\n Object.assign(iconBox.style, {\r\n width: '40px',\r\n height: '40px',\r\n borderRadius: '50%',\r\n backgroundColor: 'white',\r\n border: isSelected ? '3px solid #3b82f6' : '2px solid #ef4444',\r\n boxShadow: '0 4px 8px rgba(0,0,0,0.2)',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n overflow: 'hidden'\r\n });\r\n\r\n if (logoSrc) {\r\n const img = document.createElement('img');\r\n img.src = logoSrc;\r\n img.style.width = '100%';\r\n img.style.height = '100%';\r\n img.style.objectFit = 'cover';\r\n iconBox.appendChild(img);\r\n } else {\r\n iconBox.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n body.appendChild(iconBox);\r\n\r\n \r\n if (showPrice && (marker.price || marker.name)) {\r\n const label = document.createElement('div');\r\n label.className = 'neshan-marker-label';\r\n label.textContent = marker.price ? `${marker.price} ت` : (marker.name ?? '');\r\n body.appendChild(label);\r\n }\r\n\r\n container.appendChild(body);\r\n return container;\r\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/components/InteractiveMap.tsx","../src/components/Map.tsx","../src/utils/createCustomMarkerElement.ts","../src/components/StoreCard.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport React, { useState, useEffect } from 'react';\r\nimport Map from './Map';\r\nimport { StoreCard } from './StoreCard';\r\nimport { Store, MapProps } from '../types';\r\n\r\nexport const InteractiveMap: React.FC<MapProps> = (props) => {\r\n const [isMobile, setIsMobile] = useState(false);\r\n // ✅ ذخیره نمونه نقشه برای پاس دادن به کلیک مارکر\r\n const [mapInstance, setMapInstance] = useState<any>(null);\r\n\r\n useEffect(() => {\r\n const checkMobile = () => setIsMobile(window.innerWidth < 1024);\r\n checkMobile();\r\n window.addEventListener('resize', checkMobile);\r\n return () => window.removeEventListener('resize', checkMobile);\r\n }, []);\r\n\r\n const handleStoreSelect = (store: Store, index: number) => {\r\n // ✅ حالا دیگر null نمی‌فرستیم، نمونه واقعی نقشه را می‌فرستیم\r\n props.onMarkerClick?.(store, index, mapInstance);\r\n };\r\n\r\n // اطمینان از اینکه markers همیشه یک آرایه است\r\n const safeMarkers = props.markers || [];\r\n\r\n return (\r\n <div className={`map-layout-root ${isMobile ? 'is-mobile' : 'is-desktop'}`}>\r\n \r\n {!isMobile && (\r\n <aside className=\"sidebar\">\r\n <header className=\"sidebar-header\">لیست فروشگاه‌ها</header>\r\n <div className=\"sidebar-list\">\r\n {/* ✅ استفاده از safeMarkers برای جلوگیری از خطای undefined */}\r\n {safeMarkers.map((store, idx) => (\r\n <StoreCard \r\n key={store.id} \r\n store={store} \r\n isSelected={props.selectedMarkerId === store.id}\r\n onSelect={() => handleStoreSelect(store, idx)}\r\n />\r\n ))}\r\n </div>\r\n </aside>\r\n )}\r\n\r\n <main className=\"map-container\">\r\n {/* ✅ دریافت نمونه نقشه وقتی لود شد */}\r\n <Map \r\n {...props} \r\n onMapLoad={(map) => {\r\n setMapInstance(map);\r\n props.onMapLoad?.(map);\r\n }} \r\n />\r\n \r\n {props.productName && (\r\n <div className=\"product-badge\">\r\n <span>{props.productName}</span>\r\n </div>\r\n )}\r\n\r\n {isMobile && (\r\n <div className=\"mobile-slider\">\r\n {safeMarkers.map((store, idx) => (\r\n <StoreCard \r\n key={store.id} \r\n store={store} \r\n isSelected={props.selectedMarkerId === store.id}\r\n onSelect={() => handleStoreSelect(store, idx)}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </main>\r\n </div>\r\n );\r\n};","\"use client\";\r\n\r\nimport React, { useEffect, useRef, useState } from 'react';\r\nimport type { MapboxMap, MarkerData, MapProps } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\n\r\nimport '@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\r\n markerLogoUrl = '', \r\n selectedMarkerId = null,\r\n onMarkerClick,\r\n onMapLoad,\r\n className = '',\r\n style = { width: '100%', height: '100%' },\r\n}) => {\r\n const mapContainerRef = useRef<HTMLDivElement>(null);\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n const markersRef = useRef<any[]>([]);\r\n\r\n \r\n useEffect(() => {\r\n let isMounted = true;\r\n \r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n if (isMounted) {\r\n setMapLib(mod.default || mod);\r\n }\r\n });\r\n\r\n return () => {\r\n isMounted = false;\r\n };\r\n }, []);\r\n\r\n \r\n useEffect(() => {\r\n if (!mapLib || !mapContainerRef.current || mapInstance) return;\r\n\r\n const map = new mapLib.Map({\r\n container: mapContainerRef.current,\r\n ...options,\r\n });\r\n\r\n map.on('load', () => {\r\n setMapInstance(map);\r\n onMapLoad?.(map);\r\n });\r\n\r\n \r\n return () => {\r\n if (map) {\r\n map.remove();\r\n setMapInstance(null);\r\n }\r\n };\r\n \r\n \r\n }, [mapLib]); \r\n\r\n \r\n useEffect(() => {\r\n if (!mapInstance || !mapLib) return;\r\n\r\n \r\n markersRef.current.forEach((m) => m.remove());\r\n markersRef.current = [];\r\n\r\n markers.forEach((markerData: MarkerData, index: number) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n \r\n \r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n logoSrc: markerLogoUrl, \r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom', \r\n offset: [0, 0] \r\n })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\r\n\r\n \r\n el.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n onMarkerClick?.(markerData, index, mapInstance);\r\n });\r\n\r\n markersRef.current.push(marker);\r\n });\r\n\r\n \r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, markerLogoUrl, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n style={{ \r\n position: 'relative', \r\n overflow: 'hidden',\r\n ...style \r\n }} \r\n className={`neshan-map-wrapper ${className}`}\r\n >\r\n <div \r\n ref={mapContainerRef} \r\n style={{ width: '100%', height: '100%' }} \r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default Map;","import type { MarkerData } from '../types';\r\n\r\ninterface CreateMarkerOptions {\r\n marker: MarkerData;\r\n isSelected: boolean;\r\n logoSrc?: string;\r\n showPrice?: boolean;\r\n}\r\n\r\nexport function createCustomMarkerElement({\r\n marker,\r\n isSelected,\r\n logoSrc = '',\r\n showPrice = true,\r\n}: CreateMarkerOptions): HTMLElement {\r\n \r\n const container = document.createElement('div');\r\n container.className = 'neshan-marker-container';\r\n\r\n \r\n const body = document.createElement('div');\r\n body.className = `neshan-marker-body ${isSelected ? 'neshan-marker-selected' : ''}`;\r\n \r\n \r\n Object.assign(body.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n transition: 'transform 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n });\r\n\r\n \r\n const iconBox = document.createElement('div');\r\n Object.assign(iconBox.style, {\r\n width: '40px',\r\n height: '40px',\r\n borderRadius: '50%',\r\n backgroundColor: 'white',\r\n border: isSelected ? '3px solid #3b82f6' : '2px solid #ef4444',\r\n boxShadow: '0 4px 8px rgba(0,0,0,0.2)',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n overflow: 'hidden'\r\n });\r\n\r\n if (logoSrc) {\r\n const img = document.createElement('img');\r\n img.src = logoSrc;\r\n img.style.width = '100%';\r\n img.style.height = '100%';\r\n img.style.objectFit = 'cover';\r\n iconBox.appendChild(img);\r\n } else {\r\n iconBox.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n body.appendChild(iconBox);\r\n\r\n \r\n if (showPrice && (marker.price || marker.name)) {\r\n const label = document.createElement('div');\r\n label.className = 'neshan-marker-label';\r\n label.textContent = marker.price ? `${marker.price} ت` : (marker.name ?? '');\r\n body.appendChild(label);\r\n }\r\n\r\n container.appendChild(body);\r\n return container;\r\n}","import React from 'react';\r\nimport { Store } from '../types';\r\n\r\ninterface StoreCardProps {\r\n store: Store;\r\n isSelected: boolean;\r\n onSelect: () => void;\r\n}\r\n\r\nexport const StoreCard: React.FC<StoreCardProps> = ({ store, isSelected, onSelect }) => {\r\n const googleMapUrl = `https://www.google.com/maps/dir/?api=1&destination=${store.lat},${store.lng}`;\r\n\r\n return (\r\n <div \r\n className={`store-card ${isSelected ? 'active' : ''}`}\r\n onClick={onSelect}\r\n >\r\n <div className=\"store-card-header\">\r\n <div>\r\n <h4 className=\"store-name\">{store.name}</h4>\r\n <span className=\"store-city\">{store.city}</span>\r\n </div>\r\n <div className=\"store-price\">{store.price} تومان</div>\r\n </div>\r\n\r\n <p className=\"store-desc\">{store.desc}</p>\r\n\r\n {/* بخش آکاردئونی با CSS Animation */}\r\n <div className=\"store-details-wrapper\">\r\n <div className=\"store-details-content\">\r\n <div className=\"action-buttons\">\r\n {store.phone && (\r\n <a href={`tel:${store.phone}`} className=\"btn btn-call\">\r\n <span>تماس</span>\r\n </a>\r\n )}\r\n {store.whatsapp && (\r\n <a href={`https://wa.me/${store.whatsapp}`} target=\"_blank\" className=\"btn btn-wa\">\r\n <span>واتساپ</span>\r\n </a>\r\n )}\r\n <a href={googleMapUrl} target=\"_blank\" className=\"btn btn-route\">\r\n <span>مسیریابی</span>\r\n </a>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};"],"mappings":"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","names":["useState","useEffect","jsx","jsx","jsxs","useState","useEffect"]}
package/dist/react.cjs CHANGED
@@ -31,10 +31,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/react.ts
32
32
  var react_exports = {};
33
33
  __export(react_exports, {
34
- NeshanMap: () => Map_default
34
+ NeshanMap: () => InteractiveMap
35
35
  });
36
36
  module.exports = __toCommonJS(react_exports);
37
37
 
38
+ // src/components/InteractiveMap.tsx
39
+ var import_react2 = require("react");
40
+
38
41
  // src/components/Map.tsx
39
42
  var import_react = require("react");
40
43
 
@@ -181,6 +184,90 @@ var Map = ({
181
184
  );
182
185
  };
183
186
  var Map_default = Map;
187
+
188
+ // src/components/StoreCard.tsx
189
+ var import_jsx_runtime2 = require("react/jsx-runtime");
190
+ var StoreCard = ({ store, isSelected, onSelect }) => {
191
+ const googleMapUrl = `https://www.google.com/maps/dir/?api=1&destination=${store.lat},${store.lng}`;
192
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
193
+ "div",
194
+ {
195
+ className: `store-card ${isSelected ? "active" : ""}`,
196
+ onClick: onSelect,
197
+ children: [
198
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "store-card-header", children: [
199
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
200
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h4", { className: "store-name", children: store.name }),
201
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "store-city", children: store.city })
202
+ ] }),
203
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "store-price", children: [
204
+ store.price,
205
+ " \u062A\u0648\u0645\u0627\u0646"
206
+ ] })
207
+ ] }),
208
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "store-desc", children: store.desc }),
209
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "store-details-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "store-details-content", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "action-buttons", children: [
210
+ store.phone && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: `tel:${store.phone}`, className: "btn btn-call", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u062A\u0645\u0627\u0633" }) }),
211
+ store.whatsapp && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: `https://wa.me/${store.whatsapp}`, target: "_blank", className: "btn btn-wa", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u0648\u0627\u062A\u0633\u0627\u067E" }) }),
212
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: googleMapUrl, target: "_blank", className: "btn btn-route", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "\u0645\u0633\u06CC\u0631\u06CC\u0627\u0628\u06CC" }) })
213
+ ] }) }) })
214
+ ]
215
+ }
216
+ );
217
+ };
218
+
219
+ // src/components/InteractiveMap.tsx
220
+ var import_jsx_runtime3 = require("react/jsx-runtime");
221
+ var InteractiveMap = (props) => {
222
+ const [isMobile, setIsMobile] = (0, import_react2.useState)(false);
223
+ const [mapInstance, setMapInstance] = (0, import_react2.useState)(null);
224
+ (0, import_react2.useEffect)(() => {
225
+ const checkMobile = () => setIsMobile(window.innerWidth < 1024);
226
+ checkMobile();
227
+ window.addEventListener("resize", checkMobile);
228
+ return () => window.removeEventListener("resize", checkMobile);
229
+ }, []);
230
+ const handleStoreSelect = (store, index) => {
231
+ props.onMarkerClick?.(store, index, mapInstance);
232
+ };
233
+ const safeMarkers = props.markers || [];
234
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `map-layout-root ${isMobile ? "is-mobile" : "is-desktop"}`, children: [
235
+ !isMobile && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("aside", { className: "sidebar", children: [
236
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("header", { className: "sidebar-header", children: "\u0644\u06CC\u0633\u062A \u0641\u0631\u0648\u0634\u06AF\u0627\u0647\u200C\u0647\u0627" }),
237
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "sidebar-list", children: safeMarkers.map((store, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
238
+ StoreCard,
239
+ {
240
+ store,
241
+ isSelected: props.selectedMarkerId === store.id,
242
+ onSelect: () => handleStoreSelect(store, idx)
243
+ },
244
+ store.id
245
+ )) })
246
+ ] }),
247
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("main", { className: "map-container", children: [
248
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
249
+ Map_default,
250
+ {
251
+ ...props,
252
+ onMapLoad: (map) => {
253
+ setMapInstance(map);
254
+ props.onMapLoad?.(map);
255
+ }
256
+ }
257
+ ),
258
+ props.productName && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "product-badge", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: props.productName }) }),
259
+ isMobile && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mobile-slider", children: safeMarkers.map((store, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
260
+ StoreCard,
261
+ {
262
+ store,
263
+ isSelected: props.selectedMarkerId === store.id,
264
+ onSelect: () => handleStoreSelect(store, idx)
265
+ },
266
+ store.id
267
+ )) })
268
+ ] })
269
+ ] });
270
+ };
184
271
  // Annotate the CommonJS export names for ESM import in node:
185
272
  0 && (module.exports = {
186
273
  NeshanMap
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react.ts","../src/components/Map.tsx","../src/utils/createCustomMarkerElement.ts"],"sourcesContent":["// src/react.ts\r\n\r\n\"use client\";\r\n\r\nexport { default as NeshanMap } from './components/Map';\r\nexport type {\r\n MapProps,\r\n MapOptions,\r\n MarkerData,\r\n} from './types';","\"use client\";\r\n\r\nimport React, { useEffect, useRef, useState } from 'react';\r\nimport type { MapboxMap, MarkerData, MapProps } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\n\r\nimport '@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\r\n markerLogoUrl = '', \r\n selectedMarkerId = null,\r\n onMarkerClick,\r\n onMapLoad,\r\n className = '',\r\n style = { width: '100%', height: '100%' },\r\n}) => {\r\n const mapContainerRef = useRef<HTMLDivElement>(null);\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n const markersRef = useRef<any[]>([]);\r\n\r\n \r\n useEffect(() => {\r\n let isMounted = true;\r\n \r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n if (isMounted) {\r\n setMapLib(mod.default || mod);\r\n }\r\n });\r\n\r\n return () => {\r\n isMounted = false;\r\n };\r\n }, []);\r\n\r\n \r\n useEffect(() => {\r\n if (!mapLib || !mapContainerRef.current || mapInstance) return;\r\n\r\n const map = new mapLib.Map({\r\n container: mapContainerRef.current,\r\n ...options,\r\n });\r\n\r\n map.on('load', () => {\r\n setMapInstance(map);\r\n onMapLoad?.(map);\r\n });\r\n\r\n \r\n return () => {\r\n if (map) {\r\n map.remove();\r\n setMapInstance(null);\r\n }\r\n };\r\n \r\n \r\n }, [mapLib]); \r\n\r\n \r\n useEffect(() => {\r\n if (!mapInstance || !mapLib) return;\r\n\r\n \r\n markersRef.current.forEach((m) => m.remove());\r\n markersRef.current = [];\r\n\r\n markers.forEach((markerData: MarkerData, index: number) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n \r\n \r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n logoSrc: markerLogoUrl, \r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom', \r\n offset: [0, 0] \r\n })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\r\n\r\n \r\n el.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n onMarkerClick?.(markerData, index, mapInstance);\r\n });\r\n\r\n markersRef.current.push(marker);\r\n });\r\n\r\n \r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, markerLogoUrl, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n style={{ \r\n position: 'relative', \r\n overflow: 'hidden',\r\n ...style \r\n }} \r\n className={`neshan-map-wrapper ${className}`}\r\n >\r\n <div \r\n ref={mapContainerRef} \r\n style={{ width: '100%', height: '100%' }} \r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default Map;","import type { MarkerData } from '../types';\r\n\r\ninterface CreateMarkerOptions {\r\n marker: MarkerData;\r\n isSelected: boolean;\r\n logoSrc?: string;\r\n showPrice?: boolean;\r\n}\r\n\r\nexport function createCustomMarkerElement({\r\n marker,\r\n isSelected,\r\n logoSrc = '',\r\n showPrice = true,\r\n}: CreateMarkerOptions): HTMLElement {\r\n \r\n const container = document.createElement('div');\r\n container.className = 'neshan-marker-container';\r\n\r\n \r\n const body = document.createElement('div');\r\n body.className = `neshan-marker-body ${isSelected ? 'neshan-marker-selected' : ''}`;\r\n \r\n \r\n Object.assign(body.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n transition: 'transform 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n });\r\n\r\n \r\n const iconBox = document.createElement('div');\r\n Object.assign(iconBox.style, {\r\n width: '40px',\r\n height: '40px',\r\n borderRadius: '50%',\r\n backgroundColor: 'white',\r\n border: isSelected ? '3px solid #3b82f6' : '2px solid #ef4444',\r\n boxShadow: '0 4px 8px rgba(0,0,0,0.2)',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n overflow: 'hidden'\r\n });\r\n\r\n if (logoSrc) {\r\n const img = document.createElement('img');\r\n img.src = logoSrc;\r\n img.style.width = '100%';\r\n img.style.height = '100%';\r\n img.style.objectFit = 'cover';\r\n iconBox.appendChild(img);\r\n } else {\r\n iconBox.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n body.appendChild(iconBox);\r\n\r\n \r\n if (showPrice && (marker.price || marker.name)) {\r\n const label = document.createElement('div');\r\n label.className = 'neshan-marker-label';\r\n label.textContent = marker.price ? `${marker.price} ت` : (marker.name ?? '');\r\n body.appendChild(label);\r\n }\r\n\r\n container.appendChild(body);\r\n return container;\r\n}"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,mBAAmD;;;ACO5C,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,YAAY;AACd,GAAqC;AAEnC,QAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,YAAU,YAAY;AAGtB,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,YAAY,sBAAsB,aAAa,2BAA2B,EAAE;AAGjF,SAAO,OAAO,KAAK,OAAO;AAAA,IACxB,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,WAAW,aAAa,eAAe;AAAA,EACzC,CAAC;AAGD,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,SAAO,OAAO,QAAQ,OAAO;AAAA,IAC3B,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,QAAQ,aAAa,sBAAsB;AAAA,IAC3C,WAAW;AAAA,IACX,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,UAAU;AAAA,EACZ,CAAC;AAED,MAAI,SAAS;AACX,UAAM,MAAM,SAAS,cAAc,KAAK;AACxC,QAAI,MAAM;AACV,QAAI,MAAM,QAAQ;AAClB,QAAI,MAAM,SAAS;AACnB,QAAI,MAAM,YAAY;AACtB,YAAQ,YAAY,GAAG;AAAA,EACzB,OAAO;AACL,YAAQ,MAAM,kBAAkB;AAAA,EAClC;AAEA,OAAK,YAAY,OAAO;AAGxB,MAAI,cAAc,OAAO,SAAS,OAAO,OAAO;AAC9C,UAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,UAAM,YAAY;AAClB,UAAM,cAAc,OAAO,QAAQ,GAAG,OAAO,KAAK,YAAQ,OAAO,QAAQ;AACzE,SAAK,YAAY,KAAK;AAAA,EACxB;AAEA,YAAU,YAAY,IAAI;AAC1B,SAAO;AACT;;;AD/DA,4BAAO;AA4GD;AA1GN,IAAM,MAA0B,CAAC;AAAA,EAC/B;AAAA,EACA,UAAU,CAAC;AAAA,EACX,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,QAAQ,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAC1C,MAAM;AACJ,QAAM,sBAAkB,qBAAuB,IAAI;AACnD,QAAM,CAAC,aAAa,cAAc,QAAI,uBAA2B,IAAI;AACrE,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAAc,IAAI;AAC9C,QAAM,iBAAa,qBAAc,CAAC,CAAC;AAGnC,8BAAU,MAAM;AACd,QAAI,YAAY;AAEhB,WAAO,iCAAiC,EAAE,KAAK,CAAC,QAAQ;AACtD,UAAI,WAAW;AACb,kBAAU,IAAI,WAAW,GAAG;AAAA,MAC9B;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,8BAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,gBAAgB,WAAW,YAAa;AAExD,UAAM,MAAM,IAAI,OAAO,IAAI;AAAA,MACzB,WAAW,gBAAgB;AAAA,MAC3B,GAAG;AAAA,IACL,CAAC;AAED,QAAI,GAAG,QAAQ,MAAM;AACnB,qBAAe,GAAG;AAClB,kBAAY,GAAG;AAAA,IACjB,CAAC;AAGD,WAAO,MAAM;AACX,UAAI,KAAK;AACP,YAAI,OAAO;AACX,uBAAe,IAAI;AAAA,MACrB;AAAA,IACF;AAAA,EAGF,GAAG,CAAC,MAAM,CAAC;AAGX,8BAAU,MAAM;AACd,QAAI,CAAC,eAAe,CAAC,OAAQ;AAG7B,eAAW,QAAQ,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AAC5C,eAAW,UAAU,CAAC;AAEtB,YAAQ,QAAQ,CAAC,YAAwB,UAAkB;AACzD,YAAM,aAAa,WAAW,OAAO;AAGrC,YAAM,KAAK,0BAA0B;AAAA,QACnC,QAAQ;AAAA,QACR;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AAGD,YAAM,SAAS,IAAI,OAAO,OAAO;AAAA,QAC/B,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ,CAAC,GAAG,CAAC;AAAA,MACf,CAAC,EACE,UAAU,CAAC,WAAW,KAAK,WAAW,GAAG,CAAC,EAC1C,MAAM,WAAW;AAGpB,SAAG,iBAAiB,SAAS,CAAC,MAAM;AAClC,UAAE,gBAAgB;AAClB,wBAAgB,YAAY,OAAO,WAAW;AAAA,MAChD,CAAC;AAED,iBAAW,QAAQ,KAAK,MAAM;AAAA,IAChC,CAAC;AAGD,WAAO,MAAM;AACX,iBAAW,QAAQ,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AAAA,IAC9C;AAAA,EACF,GAAG,CAAC,SAAS,aAAa,QAAQ,kBAAkB,eAAe,aAAa,CAAC;AAEjF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAU;AAAA,QACV,GAAG;AAAA,MACL;AAAA,MACA,WAAW,sBAAsB,SAAS;AAAA,MAE1C;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAAA;AAAA,MACzC;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,cAAQ;","names":[]}
1
+ {"version":3,"sources":["../src/react.ts","../src/components/InteractiveMap.tsx","../src/components/Map.tsx","../src/utils/createCustomMarkerElement.ts","../src/components/StoreCard.tsx"],"sourcesContent":["\"use client\";\r\n\r\n\r\nexport { InteractiveMap as NeshanMap } from './components/InteractiveMap';\r\n\r\n\r\nexport type {\r\n MapProps,\r\n MapOptions,\r\n MarkerData,\r\n Store,\r\n} from './types';","\"use client\";\r\n\r\nimport React, { useState, useEffect } from 'react';\r\nimport Map from './Map';\r\nimport { StoreCard } from './StoreCard';\r\nimport { Store, MapProps } from '../types';\r\n\r\nexport const InteractiveMap: React.FC<MapProps> = (props) => {\r\n const [isMobile, setIsMobile] = useState(false);\r\n // ✅ ذخیره نمونه نقشه برای پاس دادن به کلیک مارکر\r\n const [mapInstance, setMapInstance] = useState<any>(null);\r\n\r\n useEffect(() => {\r\n const checkMobile = () => setIsMobile(window.innerWidth < 1024);\r\n checkMobile();\r\n window.addEventListener('resize', checkMobile);\r\n return () => window.removeEventListener('resize', checkMobile);\r\n }, []);\r\n\r\n const handleStoreSelect = (store: Store, index: number) => {\r\n // ✅ حالا دیگر null نمی‌فرستیم، نمونه واقعی نقشه را می‌فرستیم\r\n props.onMarkerClick?.(store, index, mapInstance);\r\n };\r\n\r\n // اطمینان از اینکه markers همیشه یک آرایه است\r\n const safeMarkers = props.markers || [];\r\n\r\n return (\r\n <div className={`map-layout-root ${isMobile ? 'is-mobile' : 'is-desktop'}`}>\r\n \r\n {!isMobile && (\r\n <aside className=\"sidebar\">\r\n <header className=\"sidebar-header\">لیست فروشگاه‌ها</header>\r\n <div className=\"sidebar-list\">\r\n {/* ✅ استفاده از safeMarkers برای جلوگیری از خطای undefined */}\r\n {safeMarkers.map((store, idx) => (\r\n <StoreCard \r\n key={store.id} \r\n store={store} \r\n isSelected={props.selectedMarkerId === store.id}\r\n onSelect={() => handleStoreSelect(store, idx)}\r\n />\r\n ))}\r\n </div>\r\n </aside>\r\n )}\r\n\r\n <main className=\"map-container\">\r\n {/* ✅ دریافت نمونه نقشه وقتی لود شد */}\r\n <Map \r\n {...props} \r\n onMapLoad={(map) => {\r\n setMapInstance(map);\r\n props.onMapLoad?.(map);\r\n }} \r\n />\r\n \r\n {props.productName && (\r\n <div className=\"product-badge\">\r\n <span>{props.productName}</span>\r\n </div>\r\n )}\r\n\r\n {isMobile && (\r\n <div className=\"mobile-slider\">\r\n {safeMarkers.map((store, idx) => (\r\n <StoreCard \r\n key={store.id} \r\n store={store} \r\n isSelected={props.selectedMarkerId === store.id}\r\n onSelect={() => handleStoreSelect(store, idx)}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </main>\r\n </div>\r\n );\r\n};","\"use client\";\r\n\r\nimport React, { useEffect, useRef, useState } from 'react';\r\nimport type { MapboxMap, MarkerData, MapProps } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\n\r\nimport '@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\r\n markerLogoUrl = '', \r\n selectedMarkerId = null,\r\n onMarkerClick,\r\n onMapLoad,\r\n className = '',\r\n style = { width: '100%', height: '100%' },\r\n}) => {\r\n const mapContainerRef = useRef<HTMLDivElement>(null);\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n const markersRef = useRef<any[]>([]);\r\n\r\n \r\n useEffect(() => {\r\n let isMounted = true;\r\n \r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n if (isMounted) {\r\n setMapLib(mod.default || mod);\r\n }\r\n });\r\n\r\n return () => {\r\n isMounted = false;\r\n };\r\n }, []);\r\n\r\n \r\n useEffect(() => {\r\n if (!mapLib || !mapContainerRef.current || mapInstance) return;\r\n\r\n const map = new mapLib.Map({\r\n container: mapContainerRef.current,\r\n ...options,\r\n });\r\n\r\n map.on('load', () => {\r\n setMapInstance(map);\r\n onMapLoad?.(map);\r\n });\r\n\r\n \r\n return () => {\r\n if (map) {\r\n map.remove();\r\n setMapInstance(null);\r\n }\r\n };\r\n \r\n \r\n }, [mapLib]); \r\n\r\n \r\n useEffect(() => {\r\n if (!mapInstance || !mapLib) return;\r\n\r\n \r\n markersRef.current.forEach((m) => m.remove());\r\n markersRef.current = [];\r\n\r\n markers.forEach((markerData: MarkerData, index: number) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n \r\n \r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n logoSrc: markerLogoUrl, \r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom', \r\n offset: [0, 0] \r\n })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\r\n\r\n \r\n el.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n onMarkerClick?.(markerData, index, mapInstance);\r\n });\r\n\r\n markersRef.current.push(marker);\r\n });\r\n\r\n \r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, markerLogoUrl, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n style={{ \r\n position: 'relative', \r\n overflow: 'hidden',\r\n ...style \r\n }} \r\n className={`neshan-map-wrapper ${className}`}\r\n >\r\n <div \r\n ref={mapContainerRef} \r\n style={{ width: '100%', height: '100%' }} \r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default Map;","import type { MarkerData } from '../types';\r\n\r\ninterface CreateMarkerOptions {\r\n marker: MarkerData;\r\n isSelected: boolean;\r\n logoSrc?: string;\r\n showPrice?: boolean;\r\n}\r\n\r\nexport function createCustomMarkerElement({\r\n marker,\r\n isSelected,\r\n logoSrc = '',\r\n showPrice = true,\r\n}: CreateMarkerOptions): HTMLElement {\r\n \r\n const container = document.createElement('div');\r\n container.className = 'neshan-marker-container';\r\n\r\n \r\n const body = document.createElement('div');\r\n body.className = `neshan-marker-body ${isSelected ? 'neshan-marker-selected' : ''}`;\r\n \r\n \r\n Object.assign(body.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n transition: 'transform 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n });\r\n\r\n \r\n const iconBox = document.createElement('div');\r\n Object.assign(iconBox.style, {\r\n width: '40px',\r\n height: '40px',\r\n borderRadius: '50%',\r\n backgroundColor: 'white',\r\n border: isSelected ? '3px solid #3b82f6' : '2px solid #ef4444',\r\n boxShadow: '0 4px 8px rgba(0,0,0,0.2)',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n overflow: 'hidden'\r\n });\r\n\r\n if (logoSrc) {\r\n const img = document.createElement('img');\r\n img.src = logoSrc;\r\n img.style.width = '100%';\r\n img.style.height = '100%';\r\n img.style.objectFit = 'cover';\r\n iconBox.appendChild(img);\r\n } else {\r\n iconBox.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n body.appendChild(iconBox);\r\n\r\n \r\n if (showPrice && (marker.price || marker.name)) {\r\n const label = document.createElement('div');\r\n label.className = 'neshan-marker-label';\r\n label.textContent = marker.price ? `${marker.price} ت` : (marker.name ?? '');\r\n body.appendChild(label);\r\n }\r\n\r\n container.appendChild(body);\r\n return container;\r\n}","import React from 'react';\r\nimport { Store } from '../types';\r\n\r\ninterface StoreCardProps {\r\n store: Store;\r\n isSelected: boolean;\r\n onSelect: () => void;\r\n}\r\n\r\nexport const StoreCard: React.FC<StoreCardProps> = ({ store, isSelected, onSelect }) => {\r\n const googleMapUrl = `https://www.google.com/maps/dir/?api=1&destination=${store.lat},${store.lng}`;\r\n\r\n return (\r\n <div \r\n className={`store-card ${isSelected ? 'active' : ''}`}\r\n onClick={onSelect}\r\n >\r\n <div className=\"store-card-header\">\r\n <div>\r\n <h4 className=\"store-name\">{store.name}</h4>\r\n <span className=\"store-city\">{store.city}</span>\r\n </div>\r\n <div className=\"store-price\">{store.price} تومان</div>\r\n </div>\r\n\r\n <p className=\"store-desc\">{store.desc}</p>\r\n\r\n {/* بخش آکاردئونی با CSS Animation */}\r\n <div className=\"store-details-wrapper\">\r\n <div className=\"store-details-content\">\r\n <div className=\"action-buttons\">\r\n {store.phone && (\r\n <a href={`tel:${store.phone}`} className=\"btn btn-call\">\r\n <span>تماس</span>\r\n </a>\r\n )}\r\n {store.whatsapp && (\r\n <a href={`https://wa.me/${store.whatsapp}`} target=\"_blank\" className=\"btn btn-wa\">\r\n <span>واتساپ</span>\r\n </a>\r\n )}\r\n <a href={googleMapUrl} target=\"_blank\" className=\"btn btn-route\">\r\n <span>مسیریابی</span>\r\n </a>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,IAAAA,gBAA2C;;;ACA3C,mBAAmD;;;ACO5C,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,YAAY;AACd,GAAqC;AAEnC,QAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,YAAU,YAAY;AAGtB,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,YAAY,sBAAsB,aAAa,2BAA2B,EAAE;AAGjF,SAAO,OAAO,KAAK,OAAO;AAAA,IACxB,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,WAAW,aAAa,eAAe;AAAA,EACzC,CAAC;AAGD,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,SAAO,OAAO,QAAQ,OAAO;AAAA,IAC3B,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,QAAQ,aAAa,sBAAsB;AAAA,IAC3C,WAAW;AAAA,IACX,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,UAAU;AAAA,EACZ,CAAC;AAED,MAAI,SAAS;AACX,UAAM,MAAM,SAAS,cAAc,KAAK;AACxC,QAAI,MAAM;AACV,QAAI,MAAM,QAAQ;AAClB,QAAI,MAAM,SAAS;AACnB,QAAI,MAAM,YAAY;AACtB,YAAQ,YAAY,GAAG;AAAA,EACzB,OAAO;AACL,YAAQ,MAAM,kBAAkB;AAAA,EAClC;AAEA,OAAK,YAAY,OAAO;AAGxB,MAAI,cAAc,OAAO,SAAS,OAAO,OAAO;AAC9C,UAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,UAAM,YAAY;AAClB,UAAM,cAAc,OAAO,QAAQ,GAAG,OAAO,KAAK,YAAQ,OAAO,QAAQ;AACzE,SAAK,YAAY,KAAK;AAAA,EACxB;AAEA,YAAU,YAAY,IAAI;AAC1B,SAAO;AACT;;;AD/DA,4BAAO;AA4GD;AA1GN,IAAM,MAA0B,CAAC;AAAA,EAC/B;AAAA,EACA,UAAU,CAAC;AAAA,EACX,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,QAAQ,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAC1C,MAAM;AACJ,QAAM,sBAAkB,qBAAuB,IAAI;AACnD,QAAM,CAAC,aAAa,cAAc,QAAI,uBAA2B,IAAI;AACrE,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAAc,IAAI;AAC9C,QAAM,iBAAa,qBAAc,CAAC,CAAC;AAGnC,8BAAU,MAAM;AACd,QAAI,YAAY;AAEhB,WAAO,iCAAiC,EAAE,KAAK,CAAC,QAAQ;AACtD,UAAI,WAAW;AACb,kBAAU,IAAI,WAAW,GAAG;AAAA,MAC9B;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,8BAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,gBAAgB,WAAW,YAAa;AAExD,UAAM,MAAM,IAAI,OAAO,IAAI;AAAA,MACzB,WAAW,gBAAgB;AAAA,MAC3B,GAAG;AAAA,IACL,CAAC;AAED,QAAI,GAAG,QAAQ,MAAM;AACnB,qBAAe,GAAG;AAClB,kBAAY,GAAG;AAAA,IACjB,CAAC;AAGD,WAAO,MAAM;AACX,UAAI,KAAK;AACP,YAAI,OAAO;AACX,uBAAe,IAAI;AAAA,MACrB;AAAA,IACF;AAAA,EAGF,GAAG,CAAC,MAAM,CAAC;AAGX,8BAAU,MAAM;AACd,QAAI,CAAC,eAAe,CAAC,OAAQ;AAG7B,eAAW,QAAQ,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AAC5C,eAAW,UAAU,CAAC;AAEtB,YAAQ,QAAQ,CAAC,YAAwB,UAAkB;AACzD,YAAM,aAAa,WAAW,OAAO;AAGrC,YAAM,KAAK,0BAA0B;AAAA,QACnC,QAAQ;AAAA,QACR;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AAGD,YAAM,SAAS,IAAI,OAAO,OAAO;AAAA,QAC/B,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ,CAAC,GAAG,CAAC;AAAA,MACf,CAAC,EACE,UAAU,CAAC,WAAW,KAAK,WAAW,GAAG,CAAC,EAC1C,MAAM,WAAW;AAGpB,SAAG,iBAAiB,SAAS,CAAC,MAAM;AAClC,UAAE,gBAAgB;AAClB,wBAAgB,YAAY,OAAO,WAAW;AAAA,MAChD,CAAC;AAED,iBAAW,QAAQ,KAAK,MAAM;AAAA,IAChC,CAAC;AAGD,WAAO,MAAM;AACX,iBAAW,QAAQ,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AAAA,IAC9C;AAAA,EACF,GAAG,CAAC,SAAS,aAAa,QAAQ,kBAAkB,eAAe,aAAa,CAAC;AAEjF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAU;AAAA,QACV,GAAG;AAAA,MACL;AAAA,MACA,WAAW,sBAAsB,SAAS;AAAA,MAE1C;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAAA;AAAA,MACzC;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,cAAQ;;;AEzGP,IAAAC,sBAAA;AATD,IAAM,YAAsC,CAAC,EAAE,OAAO,YAAY,SAAS,MAAM;AACtF,QAAM,eAAe,sDAAsD,MAAM,GAAG,IAAI,MAAM,GAAG;AAEjG,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,cAAc,aAAa,WAAW,EAAE;AAAA,MACnD,SAAS;AAAA,MAET;AAAA,sDAAC,SAAI,WAAU,qBACb;AAAA,wDAAC,SACC;AAAA,yDAAC,QAAG,WAAU,cAAc,gBAAM,MAAK;AAAA,YACvC,6CAAC,UAAK,WAAU,cAAc,gBAAM,MAAK;AAAA,aAC3C;AAAA,UACA,8CAAC,SAAI,WAAU,eAAe;AAAA,kBAAM;AAAA,YAAM;AAAA,aAAM;AAAA,WAClD;AAAA,QAEA,6CAAC,OAAE,WAAU,cAAc,gBAAM,MAAK;AAAA,QAGtC,6CAAC,SAAI,WAAU,yBACb,uDAAC,SAAI,WAAU,yBACb,wDAAC,SAAI,WAAU,kBACZ;AAAA,gBAAM,SACL,6CAAC,OAAE,MAAM,OAAO,MAAM,KAAK,IAAI,WAAU,gBACvC,uDAAC,UAAK,sCAAI,GACZ;AAAA,UAED,MAAM,YACL,6CAAC,OAAE,MAAM,iBAAiB,MAAM,QAAQ,IAAI,QAAO,UAAS,WAAU,cACpE,uDAAC,UAAK,kDAAM,GACd;AAAA,UAEF,6CAAC,OAAE,MAAM,cAAc,QAAO,UAAS,WAAU,iBAC/C,uDAAC,UAAK,8DAAQ,GAChB;AAAA,WACF,GACF,GACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;AHlBQ,IAAAC,sBAAA;AAxBD,IAAM,iBAAqC,CAAC,UAAU;AAC3D,QAAM,CAAC,UAAU,WAAW,QAAI,wBAAS,KAAK;AAE9C,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAc,IAAI;AAExD,+BAAU,MAAM;AACd,UAAM,cAAc,MAAM,YAAY,OAAO,aAAa,IAAI;AAC9D,gBAAY;AACZ,WAAO,iBAAiB,UAAU,WAAW;AAC7C,WAAO,MAAM,OAAO,oBAAoB,UAAU,WAAW;AAAA,EAC/D,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAoB,CAAC,OAAc,UAAkB;AAEzD,UAAM,gBAAgB,OAAO,OAAO,WAAW;AAAA,EACjD;AAGA,QAAM,cAAc,MAAM,WAAW,CAAC;AAEtC,SACE,8CAAC,SAAI,WAAW,mBAAmB,WAAW,cAAc,YAAY,IAErE;AAAA,KAAC,YACA,8CAAC,WAAM,WAAU,WACf;AAAA,mDAAC,YAAO,WAAU,kBAAiB,mGAAe;AAAA,MAClD,6CAAC,SAAI,WAAU,gBAEZ,sBAAY,IAAI,CAAC,OAAO,QACvB;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,YAAY,MAAM,qBAAqB,MAAM;AAAA,UAC7C,UAAU,MAAM,kBAAkB,OAAO,GAAG;AAAA;AAAA,QAHvC,MAAM;AAAA,MAIb,CACD,GACH;AAAA,OACF;AAAA,IAGF,8CAAC,UAAK,WAAU,iBAEd;AAAA;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,WAAW,CAAC,QAAQ;AAClB,2BAAe,GAAG;AAClB,kBAAM,YAAY,GAAG;AAAA,UACvB;AAAA;AAAA,MACF;AAAA,MAEC,MAAM,eACL,6CAAC,SAAI,WAAU,iBACZ,uDAAC,UAAM,gBAAM,aAAY,GAC5B;AAAA,MAGD,YACC,6CAAC,SAAI,WAAU,iBACZ,sBAAY,IAAI,CAAC,OAAO,QACvB;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,YAAY,MAAM,qBAAqB,MAAM;AAAA,UAC7C,UAAU,MAAM,kBAAkB,OAAO,GAAG;AAAA;AAAA,QAHvC,MAAM;AAAA,MAIb,CACD,GACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":["import_react","import_jsx_runtime","import_jsx_runtime"]}
package/dist/react.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { default as NeshanMap } from './components/Map';
2
- export type { MapProps, MapOptions, MarkerData, } from './types';
1
+ export { InteractiveMap as NeshanMap } from './components/InteractiveMap';
2
+ export type { MapProps, MapOptions, MarkerData, Store, } from './types';
3
3
  //# sourceMappingURL=react.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACxD,YAAY,EACV,QAAQ,EACR,UAAU,EACV,UAAU,GACX,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,IAAI,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAG1E,YAAY,EACV,QAAQ,EACR,UAAU,EACV,UAAU,EACV,KAAK,GACN,MAAM,SAAS,CAAC"}
package/dist/react.js CHANGED
@@ -1,5 +1,8 @@
1
1
  "use client";
2
2
 
3
+ // src/components/InteractiveMap.tsx
4
+ import { useState as useState2, useEffect as useEffect2 } from "react";
5
+
3
6
  // src/components/Map.tsx
4
7
  import { useEffect, useRef, useState } from "react";
5
8
 
@@ -146,7 +149,91 @@ var Map = ({
146
149
  );
147
150
  };
148
151
  var Map_default = Map;
152
+
153
+ // src/components/StoreCard.tsx
154
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
155
+ var StoreCard = ({ store, isSelected, onSelect }) => {
156
+ const googleMapUrl = `https://www.google.com/maps/dir/?api=1&destination=${store.lat},${store.lng}`;
157
+ return /* @__PURE__ */ jsxs(
158
+ "div",
159
+ {
160
+ className: `store-card ${isSelected ? "active" : ""}`,
161
+ onClick: onSelect,
162
+ children: [
163
+ /* @__PURE__ */ jsxs("div", { className: "store-card-header", children: [
164
+ /* @__PURE__ */ jsxs("div", { children: [
165
+ /* @__PURE__ */ jsx2("h4", { className: "store-name", children: store.name }),
166
+ /* @__PURE__ */ jsx2("span", { className: "store-city", children: store.city })
167
+ ] }),
168
+ /* @__PURE__ */ jsxs("div", { className: "store-price", children: [
169
+ store.price,
170
+ " \u062A\u0648\u0645\u0627\u0646"
171
+ ] })
172
+ ] }),
173
+ /* @__PURE__ */ jsx2("p", { className: "store-desc", children: store.desc }),
174
+ /* @__PURE__ */ jsx2("div", { className: "store-details-wrapper", children: /* @__PURE__ */ jsx2("div", { className: "store-details-content", children: /* @__PURE__ */ jsxs("div", { className: "action-buttons", children: [
175
+ store.phone && /* @__PURE__ */ jsx2("a", { href: `tel:${store.phone}`, className: "btn btn-call", children: /* @__PURE__ */ jsx2("span", { children: "\u062A\u0645\u0627\u0633" }) }),
176
+ store.whatsapp && /* @__PURE__ */ jsx2("a", { href: `https://wa.me/${store.whatsapp}`, target: "_blank", className: "btn btn-wa", children: /* @__PURE__ */ jsx2("span", { children: "\u0648\u0627\u062A\u0633\u0627\u067E" }) }),
177
+ /* @__PURE__ */ jsx2("a", { href: googleMapUrl, target: "_blank", className: "btn btn-route", children: /* @__PURE__ */ jsx2("span", { children: "\u0645\u0633\u06CC\u0631\u06CC\u0627\u0628\u06CC" }) })
178
+ ] }) }) })
179
+ ]
180
+ }
181
+ );
182
+ };
183
+
184
+ // src/components/InteractiveMap.tsx
185
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
186
+ var InteractiveMap = (props) => {
187
+ const [isMobile, setIsMobile] = useState2(false);
188
+ const [mapInstance, setMapInstance] = useState2(null);
189
+ useEffect2(() => {
190
+ const checkMobile = () => setIsMobile(window.innerWidth < 1024);
191
+ checkMobile();
192
+ window.addEventListener("resize", checkMobile);
193
+ return () => window.removeEventListener("resize", checkMobile);
194
+ }, []);
195
+ const handleStoreSelect = (store, index) => {
196
+ props.onMarkerClick?.(store, index, mapInstance);
197
+ };
198
+ const safeMarkers = props.markers || [];
199
+ return /* @__PURE__ */ jsxs2("div", { className: `map-layout-root ${isMobile ? "is-mobile" : "is-desktop"}`, children: [
200
+ !isMobile && /* @__PURE__ */ jsxs2("aside", { className: "sidebar", children: [
201
+ /* @__PURE__ */ jsx3("header", { className: "sidebar-header", children: "\u0644\u06CC\u0633\u062A \u0641\u0631\u0648\u0634\u06AF\u0627\u0647\u200C\u0647\u0627" }),
202
+ /* @__PURE__ */ jsx3("div", { className: "sidebar-list", children: safeMarkers.map((store, idx) => /* @__PURE__ */ jsx3(
203
+ StoreCard,
204
+ {
205
+ store,
206
+ isSelected: props.selectedMarkerId === store.id,
207
+ onSelect: () => handleStoreSelect(store, idx)
208
+ },
209
+ store.id
210
+ )) })
211
+ ] }),
212
+ /* @__PURE__ */ jsxs2("main", { className: "map-container", children: [
213
+ /* @__PURE__ */ jsx3(
214
+ Map_default,
215
+ {
216
+ ...props,
217
+ onMapLoad: (map) => {
218
+ setMapInstance(map);
219
+ props.onMapLoad?.(map);
220
+ }
221
+ }
222
+ ),
223
+ props.productName && /* @__PURE__ */ jsx3("div", { className: "product-badge", children: /* @__PURE__ */ jsx3("span", { children: props.productName }) }),
224
+ isMobile && /* @__PURE__ */ jsx3("div", { className: "mobile-slider", children: safeMarkers.map((store, idx) => /* @__PURE__ */ jsx3(
225
+ StoreCard,
226
+ {
227
+ store,
228
+ isSelected: props.selectedMarkerId === store.id,
229
+ onSelect: () => handleStoreSelect(store, idx)
230
+ },
231
+ store.id
232
+ )) })
233
+ ] })
234
+ ] });
235
+ };
149
236
  export {
150
- Map_default as NeshanMap
237
+ InteractiveMap as NeshanMap
151
238
  };
152
239
  //# sourceMappingURL=react.js.map
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Map.tsx","../src/utils/createCustomMarkerElement.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport React, { useEffect, useRef, useState } from 'react';\r\nimport type { MapboxMap, MarkerData, MapProps } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\n\r\nimport '@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\r\n markerLogoUrl = '', \r\n selectedMarkerId = null,\r\n onMarkerClick,\r\n onMapLoad,\r\n className = '',\r\n style = { width: '100%', height: '100%' },\r\n}) => {\r\n const mapContainerRef = useRef<HTMLDivElement>(null);\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n const markersRef = useRef<any[]>([]);\r\n\r\n \r\n useEffect(() => {\r\n let isMounted = true;\r\n \r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n if (isMounted) {\r\n setMapLib(mod.default || mod);\r\n }\r\n });\r\n\r\n return () => {\r\n isMounted = false;\r\n };\r\n }, []);\r\n\r\n \r\n useEffect(() => {\r\n if (!mapLib || !mapContainerRef.current || mapInstance) return;\r\n\r\n const map = new mapLib.Map({\r\n container: mapContainerRef.current,\r\n ...options,\r\n });\r\n\r\n map.on('load', () => {\r\n setMapInstance(map);\r\n onMapLoad?.(map);\r\n });\r\n\r\n \r\n return () => {\r\n if (map) {\r\n map.remove();\r\n setMapInstance(null);\r\n }\r\n };\r\n \r\n \r\n }, [mapLib]); \r\n\r\n \r\n useEffect(() => {\r\n if (!mapInstance || !mapLib) return;\r\n\r\n \r\n markersRef.current.forEach((m) => m.remove());\r\n markersRef.current = [];\r\n\r\n markers.forEach((markerData: MarkerData, index: number) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n \r\n \r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n logoSrc: markerLogoUrl, \r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom', \r\n offset: [0, 0] \r\n })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\r\n\r\n \r\n el.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n onMarkerClick?.(markerData, index, mapInstance);\r\n });\r\n\r\n markersRef.current.push(marker);\r\n });\r\n\r\n \r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, markerLogoUrl, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n style={{ \r\n position: 'relative', \r\n overflow: 'hidden',\r\n ...style \r\n }} \r\n className={`neshan-map-wrapper ${className}`}\r\n >\r\n <div \r\n ref={mapContainerRef} \r\n style={{ width: '100%', height: '100%' }} \r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default Map;","import type { MarkerData } from '../types';\r\n\r\ninterface CreateMarkerOptions {\r\n marker: MarkerData;\r\n isSelected: boolean;\r\n logoSrc?: string;\r\n showPrice?: boolean;\r\n}\r\n\r\nexport function createCustomMarkerElement({\r\n marker,\r\n isSelected,\r\n logoSrc = '',\r\n showPrice = true,\r\n}: CreateMarkerOptions): HTMLElement {\r\n \r\n const container = document.createElement('div');\r\n container.className = 'neshan-marker-container';\r\n\r\n \r\n const body = document.createElement('div');\r\n body.className = `neshan-marker-body ${isSelected ? 'neshan-marker-selected' : ''}`;\r\n \r\n \r\n Object.assign(body.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n transition: 'transform 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n });\r\n\r\n \r\n const iconBox = document.createElement('div');\r\n Object.assign(iconBox.style, {\r\n width: '40px',\r\n height: '40px',\r\n borderRadius: '50%',\r\n backgroundColor: 'white',\r\n border: isSelected ? '3px solid #3b82f6' : '2px solid #ef4444',\r\n boxShadow: '0 4px 8px rgba(0,0,0,0.2)',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n overflow: 'hidden'\r\n });\r\n\r\n if (logoSrc) {\r\n const img = document.createElement('img');\r\n img.src = logoSrc;\r\n img.style.width = '100%';\r\n img.style.height = '100%';\r\n img.style.objectFit = 'cover';\r\n iconBox.appendChild(img);\r\n } else {\r\n iconBox.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n body.appendChild(iconBox);\r\n\r\n \r\n if (showPrice && (marker.price || marker.name)) {\r\n const label = document.createElement('div');\r\n label.className = 'neshan-marker-label';\r\n label.textContent = marker.price ? `${marker.price} ت` : (marker.name ?? '');\r\n body.appendChild(label);\r\n }\r\n\r\n container.appendChild(body);\r\n return container;\r\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/components/InteractiveMap.tsx","../src/components/Map.tsx","../src/utils/createCustomMarkerElement.ts","../src/components/StoreCard.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport React, { useState, useEffect } from 'react';\r\nimport Map from './Map';\r\nimport { StoreCard } from './StoreCard';\r\nimport { Store, MapProps } from '../types';\r\n\r\nexport const InteractiveMap: React.FC<MapProps> = (props) => {\r\n const [isMobile, setIsMobile] = useState(false);\r\n // ✅ ذخیره نمونه نقشه برای پاس دادن به کلیک مارکر\r\n const [mapInstance, setMapInstance] = useState<any>(null);\r\n\r\n useEffect(() => {\r\n const checkMobile = () => setIsMobile(window.innerWidth < 1024);\r\n checkMobile();\r\n window.addEventListener('resize', checkMobile);\r\n return () => window.removeEventListener('resize', checkMobile);\r\n }, []);\r\n\r\n const handleStoreSelect = (store: Store, index: number) => {\r\n // ✅ حالا دیگر null نمی‌فرستیم، نمونه واقعی نقشه را می‌فرستیم\r\n props.onMarkerClick?.(store, index, mapInstance);\r\n };\r\n\r\n // اطمینان از اینکه markers همیشه یک آرایه است\r\n const safeMarkers = props.markers || [];\r\n\r\n return (\r\n <div className={`map-layout-root ${isMobile ? 'is-mobile' : 'is-desktop'}`}>\r\n \r\n {!isMobile && (\r\n <aside className=\"sidebar\">\r\n <header className=\"sidebar-header\">لیست فروشگاه‌ها</header>\r\n <div className=\"sidebar-list\">\r\n {/* ✅ استفاده از safeMarkers برای جلوگیری از خطای undefined */}\r\n {safeMarkers.map((store, idx) => (\r\n <StoreCard \r\n key={store.id} \r\n store={store} \r\n isSelected={props.selectedMarkerId === store.id}\r\n onSelect={() => handleStoreSelect(store, idx)}\r\n />\r\n ))}\r\n </div>\r\n </aside>\r\n )}\r\n\r\n <main className=\"map-container\">\r\n {/* ✅ دریافت نمونه نقشه وقتی لود شد */}\r\n <Map \r\n {...props} \r\n onMapLoad={(map) => {\r\n setMapInstance(map);\r\n props.onMapLoad?.(map);\r\n }} \r\n />\r\n \r\n {props.productName && (\r\n <div className=\"product-badge\">\r\n <span>{props.productName}</span>\r\n </div>\r\n )}\r\n\r\n {isMobile && (\r\n <div className=\"mobile-slider\">\r\n {safeMarkers.map((store, idx) => (\r\n <StoreCard \r\n key={store.id} \r\n store={store} \r\n isSelected={props.selectedMarkerId === store.id}\r\n onSelect={() => handleStoreSelect(store, idx)}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n </main>\r\n </div>\r\n );\r\n};","\"use client\";\r\n\r\nimport React, { useEffect, useRef, useState } from 'react';\r\nimport type { MapboxMap, MarkerData, MapProps } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\n\r\nimport '@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\r\n markerLogoUrl = '', \r\n selectedMarkerId = null,\r\n onMarkerClick,\r\n onMapLoad,\r\n className = '',\r\n style = { width: '100%', height: '100%' },\r\n}) => {\r\n const mapContainerRef = useRef<HTMLDivElement>(null);\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n const markersRef = useRef<any[]>([]);\r\n\r\n \r\n useEffect(() => {\r\n let isMounted = true;\r\n \r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n if (isMounted) {\r\n setMapLib(mod.default || mod);\r\n }\r\n });\r\n\r\n return () => {\r\n isMounted = false;\r\n };\r\n }, []);\r\n\r\n \r\n useEffect(() => {\r\n if (!mapLib || !mapContainerRef.current || mapInstance) return;\r\n\r\n const map = new mapLib.Map({\r\n container: mapContainerRef.current,\r\n ...options,\r\n });\r\n\r\n map.on('load', () => {\r\n setMapInstance(map);\r\n onMapLoad?.(map);\r\n });\r\n\r\n \r\n return () => {\r\n if (map) {\r\n map.remove();\r\n setMapInstance(null);\r\n }\r\n };\r\n \r\n \r\n }, [mapLib]); \r\n\r\n \r\n useEffect(() => {\r\n if (!mapInstance || !mapLib) return;\r\n\r\n \r\n markersRef.current.forEach((m) => m.remove());\r\n markersRef.current = [];\r\n\r\n markers.forEach((markerData: MarkerData, index: number) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n \r\n \r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n logoSrc: markerLogoUrl, \r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom', \r\n offset: [0, 0] \r\n })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\r\n\r\n \r\n el.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n onMarkerClick?.(markerData, index, mapInstance);\r\n });\r\n\r\n markersRef.current.push(marker);\r\n });\r\n\r\n \r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, markerLogoUrl, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n style={{ \r\n position: 'relative', \r\n overflow: 'hidden',\r\n ...style \r\n }} \r\n className={`neshan-map-wrapper ${className}`}\r\n >\r\n <div \r\n ref={mapContainerRef} \r\n style={{ width: '100%', height: '100%' }} \r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default Map;","import type { MarkerData } from '../types';\r\n\r\ninterface CreateMarkerOptions {\r\n marker: MarkerData;\r\n isSelected: boolean;\r\n logoSrc?: string;\r\n showPrice?: boolean;\r\n}\r\n\r\nexport function createCustomMarkerElement({\r\n marker,\r\n isSelected,\r\n logoSrc = '',\r\n showPrice = true,\r\n}: CreateMarkerOptions): HTMLElement {\r\n \r\n const container = document.createElement('div');\r\n container.className = 'neshan-marker-container';\r\n\r\n \r\n const body = document.createElement('div');\r\n body.className = `neshan-marker-body ${isSelected ? 'neshan-marker-selected' : ''}`;\r\n \r\n \r\n Object.assign(body.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n transition: 'transform 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n });\r\n\r\n \r\n const iconBox = document.createElement('div');\r\n Object.assign(iconBox.style, {\r\n width: '40px',\r\n height: '40px',\r\n borderRadius: '50%',\r\n backgroundColor: 'white',\r\n border: isSelected ? '3px solid #3b82f6' : '2px solid #ef4444',\r\n boxShadow: '0 4px 8px rgba(0,0,0,0.2)',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n overflow: 'hidden'\r\n });\r\n\r\n if (logoSrc) {\r\n const img = document.createElement('img');\r\n img.src = logoSrc;\r\n img.style.width = '100%';\r\n img.style.height = '100%';\r\n img.style.objectFit = 'cover';\r\n iconBox.appendChild(img);\r\n } else {\r\n iconBox.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n body.appendChild(iconBox);\r\n\r\n \r\n if (showPrice && (marker.price || marker.name)) {\r\n const label = document.createElement('div');\r\n label.className = 'neshan-marker-label';\r\n label.textContent = marker.price ? `${marker.price} ت` : (marker.name ?? '');\r\n body.appendChild(label);\r\n }\r\n\r\n container.appendChild(body);\r\n return container;\r\n}","import React from 'react';\r\nimport { Store } from '../types';\r\n\r\ninterface StoreCardProps {\r\n store: Store;\r\n isSelected: boolean;\r\n onSelect: () => void;\r\n}\r\n\r\nexport const StoreCard: React.FC<StoreCardProps> = ({ store, isSelected, onSelect }) => {\r\n const googleMapUrl = `https://www.google.com/maps/dir/?api=1&destination=${store.lat},${store.lng}`;\r\n\r\n return (\r\n <div \r\n className={`store-card ${isSelected ? 'active' : ''}`}\r\n onClick={onSelect}\r\n >\r\n <div className=\"store-card-header\">\r\n <div>\r\n <h4 className=\"store-name\">{store.name}</h4>\r\n <span className=\"store-city\">{store.city}</span>\r\n </div>\r\n <div className=\"store-price\">{store.price} تومان</div>\r\n </div>\r\n\r\n <p className=\"store-desc\">{store.desc}</p>\r\n\r\n {/* بخش آکاردئونی با CSS Animation */}\r\n <div className=\"store-details-wrapper\">\r\n <div className=\"store-details-content\">\r\n <div className=\"action-buttons\">\r\n {store.phone && (\r\n <a href={`tel:${store.phone}`} className=\"btn btn-call\">\r\n <span>تماس</span>\r\n </a>\r\n )}\r\n {store.whatsapp && (\r\n <a href={`https://wa.me/${store.whatsapp}`} target=\"_blank\" className=\"btn btn-wa\">\r\n <span>واتساپ</span>\r\n </a>\r\n )}\r\n <a href={googleMapUrl} target=\"_blank\" className=\"btn btn-route\">\r\n <span>مسیریابی</span>\r\n </a>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};"],"mappings":";;;AAEA,SAAgB,YAAAA,WAAU,aAAAC,kBAAiB;;;ACA3C,SAAgB,WAAW,QAAQ,gBAAgB;;;ACO5C,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,YAAY;AACd,GAAqC;AAEnC,QAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,YAAU,YAAY;AAGtB,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,YAAY,sBAAsB,aAAa,2BAA2B,EAAE;AAGjF,SAAO,OAAO,KAAK,OAAO;AAAA,IACxB,SAAS;AAAA,IACT,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,WAAW,aAAa,eAAe;AAAA,EACzC,CAAC;AAGD,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,SAAO,OAAO,QAAQ,OAAO;AAAA,IAC3B,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,QAAQ,aAAa,sBAAsB;AAAA,IAC3C,WAAW;AAAA,IACX,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,UAAU;AAAA,EACZ,CAAC;AAED,MAAI,SAAS;AACX,UAAM,MAAM,SAAS,cAAc,KAAK;AACxC,QAAI,MAAM;AACV,QAAI,MAAM,QAAQ;AAClB,QAAI,MAAM,SAAS;AACnB,QAAI,MAAM,YAAY;AACtB,YAAQ,YAAY,GAAG;AAAA,EACzB,OAAO;AACL,YAAQ,MAAM,kBAAkB;AAAA,EAClC;AAEA,OAAK,YAAY,OAAO;AAGxB,MAAI,cAAc,OAAO,SAAS,OAAO,OAAO;AAC9C,UAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,UAAM,YAAY;AAClB,UAAM,cAAc,OAAO,QAAQ,GAAG,OAAO,KAAK,YAAQ,OAAO,QAAQ;AACzE,SAAK,YAAY,KAAK;AAAA,EACxB;AAEA,YAAU,YAAY,IAAI;AAC1B,SAAO;AACT;;;AD/DA,OAAO;AA4GD;AA1GN,IAAM,MAA0B,CAAC;AAAA,EAC/B;AAAA,EACA,UAAU,CAAC;AAAA,EACX,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,QAAQ,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAC1C,MAAM;AACJ,QAAM,kBAAkB,OAAuB,IAAI;AACnD,QAAM,CAAC,aAAa,cAAc,IAAI,SAA2B,IAAI;AACrE,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAc,IAAI;AAC9C,QAAM,aAAa,OAAc,CAAC,CAAC;AAGnC,YAAU,MAAM;AACd,QAAI,YAAY;AAEhB,WAAO,iCAAiC,EAAE,KAAK,CAAC,QAAQ;AACtD,UAAI,WAAW;AACb,kBAAU,IAAI,WAAW,GAAG;AAAA,MAC9B;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,gBAAgB,WAAW,YAAa;AAExD,UAAM,MAAM,IAAI,OAAO,IAAI;AAAA,MACzB,WAAW,gBAAgB;AAAA,MAC3B,GAAG;AAAA,IACL,CAAC;AAED,QAAI,GAAG,QAAQ,MAAM;AACnB,qBAAe,GAAG;AAClB,kBAAY,GAAG;AAAA,IACjB,CAAC;AAGD,WAAO,MAAM;AACX,UAAI,KAAK;AACP,YAAI,OAAO;AACX,uBAAe,IAAI;AAAA,MACrB;AAAA,IACF;AAAA,EAGF,GAAG,CAAC,MAAM,CAAC;AAGX,YAAU,MAAM;AACd,QAAI,CAAC,eAAe,CAAC,OAAQ;AAG7B,eAAW,QAAQ,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AAC5C,eAAW,UAAU,CAAC;AAEtB,YAAQ,QAAQ,CAAC,YAAwB,UAAkB;AACzD,YAAM,aAAa,WAAW,OAAO;AAGrC,YAAM,KAAK,0BAA0B;AAAA,QACnC,QAAQ;AAAA,QACR;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AAGD,YAAM,SAAS,IAAI,OAAO,OAAO;AAAA,QAC/B,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ,CAAC,GAAG,CAAC;AAAA,MACf,CAAC,EACE,UAAU,CAAC,WAAW,KAAK,WAAW,GAAG,CAAC,EAC1C,MAAM,WAAW;AAGpB,SAAG,iBAAiB,SAAS,CAAC,MAAM;AAClC,UAAE,gBAAgB;AAClB,wBAAgB,YAAY,OAAO,WAAW;AAAA,MAChD,CAAC;AAED,iBAAW,QAAQ,KAAK,MAAM;AAAA,IAChC,CAAC;AAGD,WAAO,MAAM;AACX,iBAAW,QAAQ,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AAAA,IAC9C;AAAA,EACF,GAAG,CAAC,SAAS,aAAa,QAAQ,kBAAkB,eAAe,aAAa,CAAC;AAEjF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAU;AAAA,QACV,GAAG;AAAA,MACL;AAAA,MACA,WAAW,sBAAsB,SAAS;AAAA,MAE1C;AAAA,QAAC;AAAA;AAAA,UACC,KAAK;AAAA,UACL,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAAA;AAAA,MACzC;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,cAAQ;;;AEzGP,SACE,OAAAC,MADF;AATD,IAAM,YAAsC,CAAC,EAAE,OAAO,YAAY,SAAS,MAAM;AACtF,QAAM,eAAe,sDAAsD,MAAM,GAAG,IAAI,MAAM,GAAG;AAEjG,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,cAAc,aAAa,WAAW,EAAE;AAAA,MACnD,SAAS;AAAA,MAET;AAAA,6BAAC,SAAI,WAAU,qBACb;AAAA,+BAAC,SACC;AAAA,4BAAAA,KAAC,QAAG,WAAU,cAAc,gBAAM,MAAK;AAAA,YACvC,gBAAAA,KAAC,UAAK,WAAU,cAAc,gBAAM,MAAK;AAAA,aAC3C;AAAA,UACA,qBAAC,SAAI,WAAU,eAAe;AAAA,kBAAM;AAAA,YAAM;AAAA,aAAM;AAAA,WAClD;AAAA,QAEA,gBAAAA,KAAC,OAAE,WAAU,cAAc,gBAAM,MAAK;AAAA,QAGtC,gBAAAA,KAAC,SAAI,WAAU,yBACb,0BAAAA,KAAC,SAAI,WAAU,yBACb,+BAAC,SAAI,WAAU,kBACZ;AAAA,gBAAM,SACL,gBAAAA,KAAC,OAAE,MAAM,OAAO,MAAM,KAAK,IAAI,WAAU,gBACvC,0BAAAA,KAAC,UAAK,sCAAI,GACZ;AAAA,UAED,MAAM,YACL,gBAAAA,KAAC,OAAE,MAAM,iBAAiB,MAAM,QAAQ,IAAI,QAAO,UAAS,WAAU,cACpE,0BAAAA,KAAC,UAAK,kDAAM,GACd;AAAA,UAEF,gBAAAA,KAAC,OAAE,MAAM,cAAc,QAAO,UAAS,WAAU,iBAC/C,0BAAAA,KAAC,UAAK,8DAAQ,GAChB;AAAA,WACF,GACF,GACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;AHlBQ,SACE,OAAAC,MADF,QAAAC,aAAA;AAxBD,IAAM,iBAAqC,CAAC,UAAU;AAC3D,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAS,KAAK;AAE9C,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAc,IAAI;AAExD,EAAAC,WAAU,MAAM;AACd,UAAM,cAAc,MAAM,YAAY,OAAO,aAAa,IAAI;AAC9D,gBAAY;AACZ,WAAO,iBAAiB,UAAU,WAAW;AAC7C,WAAO,MAAM,OAAO,oBAAoB,UAAU,WAAW;AAAA,EAC/D,GAAG,CAAC,CAAC;AAEL,QAAM,oBAAoB,CAAC,OAAc,UAAkB;AAEzD,UAAM,gBAAgB,OAAO,OAAO,WAAW;AAAA,EACjD;AAGA,QAAM,cAAc,MAAM,WAAW,CAAC;AAEtC,SACE,gBAAAF,MAAC,SAAI,WAAW,mBAAmB,WAAW,cAAc,YAAY,IAErE;AAAA,KAAC,YACA,gBAAAA,MAAC,WAAM,WAAU,WACf;AAAA,sBAAAD,KAAC,YAAO,WAAU,kBAAiB,mGAAe;AAAA,MAClD,gBAAAA,KAAC,SAAI,WAAU,gBAEZ,sBAAY,IAAI,CAAC,OAAO,QACvB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,YAAY,MAAM,qBAAqB,MAAM;AAAA,UAC7C,UAAU,MAAM,kBAAkB,OAAO,GAAG;AAAA;AAAA,QAHvC,MAAM;AAAA,MAIb,CACD,GACH;AAAA,OACF;AAAA,IAGF,gBAAAC,MAAC,UAAK,WAAU,iBAEd;AAAA,sBAAAD;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,WAAW,CAAC,QAAQ;AAClB,2BAAe,GAAG;AAClB,kBAAM,YAAY,GAAG;AAAA,UACvB;AAAA;AAAA,MACF;AAAA,MAEC,MAAM,eACL,gBAAAA,KAAC,SAAI,WAAU,iBACZ,0BAAAA,KAAC,UAAM,gBAAM,aAAY,GAC5B;AAAA,MAGD,YACC,gBAAAA,KAAC,SAAI,WAAU,iBACZ,sBAAY,IAAI,CAAC,OAAO,QACvB,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,YAAY,MAAM,qBAAqB,MAAM;AAAA,UAC7C,UAAU,MAAM,kBAAkB,OAAO,GAAG;AAAA;AAAA,QAHvC,MAAM;AAAA,MAIb,CACD,GACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":["useState","useEffect","jsx","jsx","jsxs","useState","useEffect"]}
package/dist/styles.css CHANGED
@@ -1,40 +1,123 @@
1
+ .map-layout-root {
2
+ display: flex;
3
+ width: 100%;
4
+ height: 100%;
5
+ direction: rtl;
6
+ font-family: inherit;
7
+ }
1
8
 
2
- .neshan-marker-container {
3
- pointer-events: auto;
4
- will-change: auto;
9
+ /* Sidebar Desktop */
10
+ .sidebar {
11
+ width: 350px;
12
+ background: #fff;
13
+ border-left: 1px solid #eee;
14
+ display: flex;
15
+ flex-direction: column;
16
+ z-index: 10;
17
+ }
18
+
19
+ .sidebar-header {
20
+ padding: 20px;
21
+ font-weight: bold;
22
+ border-bottom: 1px solid #eee;
5
23
  }
6
24
 
25
+ .sidebar-list {
26
+ flex: 1;
27
+ overflow-y: auto;
28
+ }
29
+
30
+ /* Map Section */
31
+ .map-container {
32
+ flex: 1;
33
+ position: relative;
34
+ }
7
35
 
8
- .neshan-marker-body {
36
+ /* Store Card Style */
37
+ .store-card {
38
+ padding: 15px;
39
+ border-bottom: 1px solid #f0f0f0;
9
40
  cursor: pointer;
10
- transform-origin: bottom center;
41
+ transition: background 0.2s;
42
+ }
43
+
44
+ .store-card:hover { background: #f9f9f9; }
45
+ .store-card.active { background: #f0f7ff; border-right: 4px solid #3b82f6; }
46
+
47
+ .store-card-header { display: flex; justify-content: space-between; margin-bottom: 8px; }
48
+ .store-name { margin: 0; font-size: 15px; color: #1a1a1a; }
49
+ .store-city { font-size: 12px; color: #777; }
50
+ .store-price { color: #059669; font-weight: bold; font-size: 14px; }
51
+ .store-desc { font-size: 12px; color: #555; line-height: 1.6; }
52
+
53
+ /* CSS Accordion Effect */
54
+ .store-details-wrapper {
55
+ display: grid;
56
+ grid-template-rows: 0fr;
57
+ transition: grid-template-rows 0.3s ease-out;
58
+ overflow: hidden;
11
59
  }
12
60
 
13
- .neshan-marker-body:hover {
14
- transform: scale(1.2) !important;
15
- z-index: 999;
61
+ .active .store-details-wrapper {
62
+ grid-template-rows: 1fr;
63
+ margin-top: 12px;
16
64
  }
17
65
 
18
- .neshan-marker-label {
19
- background: white;
20
- color: #1f2937;
21
- font-size: 11px;
22
- font-weight: bold;
23
- padding: 3px 8px;
24
- border-radius: 4px;
25
- margin-top: 4px;
26
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
27
- white-space: nowrap;
28
- border: 1px solid #e5e7eb;
66
+ .store-details-content { min-height: 0; }
67
+
68
+ .action-buttons {
69
+ display: flex;
70
+ gap: 8px;
71
+ }
72
+
73
+ .btn {
74
+ flex: 1;
75
+ padding: 8px;
76
+ border-radius: 6px;
77
+ text-align: center;
78
+ text-decoration: none;
79
+ font-size: 12px;
80
+ color: #fff;
81
+ transition: opacity 0.2s;
29
82
  }
30
83
 
84
+ .btn:hover { opacity: 0.9; }
85
+ .btn-call { background: #3b82f6; }
86
+ .btn-wa { background: #10b981; }
87
+ .btn-route { background: #8b5cf6; }
31
88
 
32
- .neshan-marker-selected .neshan-marker-body {
33
- animation: marker-pulse 1.5s infinite ease-in-out;
89
+ /* Mobile View */
90
+ .is-mobile .mobile-slider {
91
+ position: absolute;
92
+ bottom: 20px;
93
+ left: 0;
94
+ right: 0;
95
+ display: flex;
96
+ gap: 12px;
97
+ padding: 0 20px;
98
+ overflow-x: auto;
99
+ scroll-snap-type: x mandatory;
100
+ pointer-events: none; /* اجازه کلیک روی نقشه در جاهای خالی */
34
101
  }
35
102
 
36
- @keyframes marker-pulse {
37
- 0% { transform: scale(1.2); }
38
- 50% { transform: scale(1.3); }
39
- 100% { transform: scale(1.2); }
103
+ .is-mobile .store-card {
104
+ min-width: 280px;
105
+ background: #fff;
106
+ border-radius: 12px;
107
+ box-shadow: 0 4px 15px rgba(0,0,0,0.15);
108
+ pointer-events: auto;
109
+ scroll-snap-align: center;
110
+ }
111
+
112
+ .product-badge {
113
+ position: absolute;
114
+ top: 20px;
115
+ right: 20px;
116
+ background: rgba(255, 255, 255, 0.9);
117
+ padding: 8px 15px;
118
+ border-radius: 8px;
119
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
120
+ font-weight: bold;
121
+ font-size: 13px;
122
+ z-index: 5;
40
123
  }
@@ -6,30 +6,32 @@ export interface MapOptions {
6
6
  zoom?: number;
7
7
  [key: string]: any;
8
8
  }
9
- export interface MarkerData {
9
+ export interface Store {
10
10
  id: string | number;
11
11
  lat: number;
12
12
  lng: number;
13
- name?: string;
14
- price?: string;
13
+ name: string;
15
14
  city?: string;
16
15
  performance?: string;
17
16
  desc?: string;
17
+ price?: string;
18
18
  phone?: string;
19
19
  whatsapp?: string;
20
20
  [key: string]: any;
21
21
  }
22
+ export type MarkerData = Store;
22
23
  export interface MapProps {
23
24
  options: MapOptions;
24
- markers?: MarkerData[];
25
+ markers?: Store[];
25
26
  selectedMarkerId?: string | number | null;
26
- onMarkerClick?: (marker: MarkerData, index: number, map: MapboxMap) => void;
27
+ onMarkerClick?: (marker: Store, index: number, map: MapboxMap) => void;
27
28
  onMapLoad?: (map: MapboxMap) => void;
28
29
  children?: React.ReactNode;
29
30
  className?: string;
30
31
  style?: React.CSSProperties;
31
32
  markerLogoUrl?: string;
32
33
  flyToOnSelect?: boolean;
34
+ productName?: string;
33
35
  }
34
36
  export type { LngLatLike, LngLatBoundsLike, MapboxMap, MapboxMarker, PointLike };
35
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,GAAG,IAAI,SAAS,EAChB,MAAM,IAAI,YAAY,EACtB,SAAS,EACV,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,QAAQ,GAAG,cAAc,GAAG,KAAK,GAAG,MAAM,CAAC;IACrD,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,UAAU,EAAE,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IAC5E,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,GAAG,IAAI,SAAS,EAChB,MAAM,IAAI,YAAY,EACtB,SAAS,EACV,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,QAAQ,GAAG,cAAc,GAAG,KAAK,GAAG,MAAM,CAAC;IACrD,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAGD,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAGD,MAAM,MAAM,UAAU,GAAG,KAAK,CAAC;AAE/B,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC1C,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IACvE,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mehdi-akbari-map",
3
- "version": "0.0.9",
3
+ "version": "0.1.1",
4
4
  "description": "A professional Map",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",