mehdi-akbari-map 0.0.5 → 0.0.7

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.
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
- import { MapProps } from '../types';
2
+ import type { MapProps } from '../types';
3
+ import '@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css';
3
4
  declare const Map: React.FC<MapProps>;
4
5
  export default Map;
5
6
  //# sourceMappingURL=Map.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Map.d.ts","sourceRoot":"","sources":["../../src/components/Map.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAyB,MAAM,UAAU,CAAC;AAG3D,QAAA,MAAM,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,QAAQ,CAsF3B,CAAC;AAEF,eAAe,GAAG,CAAC"}
1
+ {"version":3,"file":"Map.d.ts","sourceRoot":"","sources":["../../src/components/Map.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,KAAK,EAAyB,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEhE,OAAO,yDAAyD,CAAC;AAEjE,QAAA,MAAM,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,QAAQ,CA2E3B,CAAC;AAEF,eAAe,GAAG,CAAC"}
package/dist/index.cjs CHANGED
@@ -44,24 +44,25 @@ function createCustomMarkerElement({
44
44
  logoSrc = "",
45
45
  showPrice = true
46
46
  }) {
47
- const wrapper = document.createElement("div");
48
- Object.assign(wrapper.style, {
47
+ const container = document.createElement("div");
48
+ container.className = "neshan-marker-container";
49
+ const body = document.createElement("div");
50
+ body.className = `neshan-marker-body ${isSelected ? "neshan-marker-selected" : ""}`;
51
+ Object.assign(body.style, {
49
52
  display: "flex",
50
53
  flexDirection: "column",
51
54
  alignItems: "center",
52
- cursor: "pointer",
53
- transition: "all 0.3s ease",
54
- transform: isSelected ? "scale(1.2)" : "scale(1)",
55
- zIndex: isSelected ? "10" : "1"
55
+ transition: "transform 0.3s ease",
56
+ transform: isSelected ? "scale(1.2)" : "scale(1)"
56
57
  });
57
- const iconTarget = document.createElement("div");
58
- Object.assign(iconTarget.style, {
58
+ const iconBox = document.createElement("div");
59
+ Object.assign(iconBox.style, {
59
60
  width: "40px",
60
61
  height: "40px",
61
62
  borderRadius: "50%",
62
63
  backgroundColor: "white",
63
64
  border: isSelected ? "3px solid #3b82f6" : "2px solid #ef4444",
64
- boxShadow: "0 4px 6px rgba(0,0,0,0.1)",
65
+ boxShadow: "0 4px 8px rgba(0,0,0,0.2)",
65
66
  display: "flex",
66
67
  alignItems: "center",
67
68
  justifyContent: "center",
@@ -70,41 +71,32 @@ function createCustomMarkerElement({
70
71
  if (logoSrc) {
71
72
  const img = document.createElement("img");
72
73
  img.src = logoSrc;
73
- img.style.width = "80%";
74
- img.style.height = "80%";
75
- img.style.objectFit = "contain";
76
- iconTarget.appendChild(img);
74
+ img.style.width = "100%";
75
+ img.style.height = "100%";
76
+ img.style.objectFit = "cover";
77
+ iconBox.appendChild(img);
77
78
  } else {
78
- iconTarget.style.backgroundColor = "#ef4444";
79
+ iconBox.style.backgroundColor = "#ef4444";
79
80
  }
80
- wrapper.appendChild(iconTarget);
81
- if (showPrice && (marker.name || marker.price)) {
81
+ body.appendChild(iconBox);
82
+ if (showPrice && (marker.price || marker.name)) {
82
83
  const label = document.createElement("div");
83
- Object.assign(label.style, {
84
- backgroundColor: "white",
85
- padding: "2px 8px",
86
- borderRadius: "4px",
87
- marginTop: "4px",
88
- fontSize: "11px",
89
- fontWeight: "bold",
90
- whiteSpace: "nowrap",
91
- boxShadow: "0 2px 4px rgba(0,0,0,0.2)",
92
- border: "1px solid #ddd"
93
- });
94
- const labelText = marker.price ? `${marker.price} \u062A` : marker.name;
95
- label.textContent = labelText || "";
84
+ label.className = "neshan-marker-label";
85
+ label.textContent = marker.price ? `${marker.price} \u062A` : marker.name ?? "";
86
+ body.appendChild(label);
96
87
  }
97
- return wrapper;
88
+ container.appendChild(body);
89
+ return container;
98
90
  }
99
91
 
100
92
  // src/components/Map.tsx
93
+ var import_NeshanMapboxGl = require("@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css");
101
94
  var import_jsx_runtime = require("react/jsx-runtime");
102
95
  var Map = ({
103
96
  options,
104
97
  markers = [],
105
98
  selectedMarkerId = null,
106
99
  onMarkerClick,
107
- onMapLoad,
108
100
  className = "",
109
101
  style = { width: "100%", height: "100%" }
110
102
  }) => {
@@ -113,10 +105,8 @@ var Map = ({
113
105
  const markersRef = (0, import_react.useRef)([]);
114
106
  const [mapLib, setMapLib] = (0, import_react.useState)(null);
115
107
  (0, import_react.useEffect)(() => {
116
- if (typeof window === "undefined") return;
117
108
  import("@neshan-maps-platform/mapbox-gl").then((mod) => {
118
109
  setMapLib(mod.default || mod);
119
- import("@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css");
120
110
  });
121
111
  }, []);
122
112
  (0, import_react.useEffect)(() => {
@@ -127,41 +117,32 @@ var Map = ({
127
117
  });
128
118
  map.on("load", () => {
129
119
  setMapInstance(map);
130
- onMapLoad?.(map);
131
120
  });
132
121
  return () => {
133
- if (map) map.remove();
134
122
  };
135
- }, [mapLib, options]);
123
+ }, [mapLib]);
136
124
  (0, import_react.useEffect)(() => {
137
125
  if (!mapInstance || !mapLib) return;
138
126
  markersRef.current.forEach((m) => m.remove());
139
127
  markersRef.current = [];
140
128
  markers.forEach((markerData, index) => {
129
+ const isSelected = markerData.id === selectedMarkerId;
141
130
  const el = createCustomMarkerElement({
142
131
  marker: markerData,
143
- isSelected: markerData.id === selectedMarkerId
144
- // logoSrc: markerLogoUrl // می‌توانید این را به props اضافه کنید
132
+ isSelected
145
133
  });
146
- const marker = new mapLib.Marker({ element: el }).setLngLat([markerData.lng, markerData.lat]).addTo(mapInstance);
134
+ const marker = new mapLib.Marker({
135
+ element: el,
136
+ anchor: "bottom"
137
+ }).setLngLat([markerData.lng, markerData.lat]).addTo(mapInstance);
147
138
  el.addEventListener("click", (e) => {
148
139
  e.stopPropagation();
149
140
  onMarkerClick?.(markerData, index, mapInstance);
150
141
  });
151
142
  markersRef.current.push(marker);
152
143
  });
153
- return () => {
154
- markersRef.current.forEach((m) => m.remove());
155
- };
156
- }, [markers, mapInstance, mapLib, selectedMarkerId, onMarkerClick]);
157
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
158
- "div",
159
- {
160
- ref: mapContainerRef,
161
- className,
162
- style: { position: "relative", ...style }
163
- }
164
- );
144
+ }, [markers, mapInstance, selectedMarkerId]);
145
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "relative", ...style }, className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: mapContainerRef, style: { width: "100%", height: "100%" } }) });
165
146
  };
166
147
  var Map_default = Map;
167
148
  // Annotate the CommonJS export names for ESM import in node:
@@ -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 { MapProps, MapboxMap, MarkerData } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\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 // ✅ استفاده از state به جای ref برای instance نقشه\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const markersRef = useRef<any[]>([]);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n\r\n // لود کردن کتابخانه نشان\r\n useEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n setMapLib(mod.default || mod);\r\n // لود کردن استایل‌های پیش‌فرض نشان\r\n import('@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css');\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); // ✅ اینجا باعث رندر مجدد و فعال شدن useEffect مارکرها می‌شود\r\n onMapLoad?.(map);\r\n });\r\n\r\n return () => {\r\n if (map) map.remove();\r\n };\r\n }, [mapLib, options]);\r\n\r\n // مدیریت مارکرها\r\n useEffect(() => {\r\n // ✅ حالا mapInstance به عنوان وابستگی درست کار می‌کند\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 // استفاده از ابزاری که خودتان نوشتید\r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: markerData.id === selectedMarkerId,\r\n // logoSrc: markerLogoUrl // می‌توانید این را به props اضافه کنید\r\n });\r\n\r\n const marker = new mapLib.Marker({ element: el })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\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 // پاکسازی مارکرها در صورت unmount\r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n ref={mapContainerRef} \r\n className={className} \r\n style={{ position: 'relative', ...style }} \r\n />\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 const wrapper = document.createElement('div');\r\n \r\n // استایل‌های پایه بصورت Inline برای اطمینان از نمایش\r\n Object.assign(wrapper.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n cursor: 'pointer',\r\n transition: 'all 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n zIndex: isSelected ? '10' : '1'\r\n });\r\n\r\n // بخش تصویر مارکر\r\n const iconTarget = document.createElement('div');\r\n Object.assign(iconTarget.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 6px rgba(0,0,0,0.1)',\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 = '80%';\r\n img.style.height = '80%';\r\n img.style.objectFit = 'contain';\r\n iconTarget.appendChild(img);\r\n } else {\r\n // یک دایره رنگی ساده اگر لوگو نبود\r\n iconTarget.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n wrapper.appendChild(iconTarget);\r\n\r\n // بخش برچسب قیمت\r\n if (showPrice && (marker.name || marker.price)) {\r\n const label = document.createElement('div');\r\n Object.assign(label.style, {\r\n backgroundColor: 'white',\r\n padding: '2px 8px',\r\n borderRadius: '4px',\r\n marginTop: '4px',\r\n fontSize: '11px',\r\n fontWeight: 'bold',\r\n whiteSpace: 'nowrap',\r\n boxShadow: '0 2px 4px rgba(0,0,0,0.2)',\r\n border: '1px solid #ddd'\r\n });\r\n const labelText = marker.price \r\n ? `${marker.price} ت` \r\n : marker.name;\r\n\r\nlabel.textContent = labelText || '';\r\n }\r\n\r\n return wrapper;\r\n}"],"mappings":"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","names":[]}
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\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 selectedMarkerId = null,\r\n onMarkerClick,\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 markersRef = useRef<any[]>([]);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n\r\n \r\n useEffect(() => {\r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n setMapLib(mod.default || mod);\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 });\r\n\r\n return () => {\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, index) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom' \r\n})\r\n.setLngLat([markerData.lng, markerData.lat])\r\n.addTo(mapInstance);\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 }, [markers, mapInstance, selectedMarkerId]); \r\n\r\n return (\r\n <div style={{ position: 'relative', ...style }} className={className}>\r\n <div ref={mapContainerRef} style={{ width: '100%', height: '100%' }} />\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":[]}
package/dist/index.css CHANGED
@@ -1,38 +1,40 @@
1
1
  /* src/styles.css */
2
- .neshan-map-container * {
3
- box-sizing: border-box;
2
+ .neshan-marker-container {
3
+ pointer-events: auto;
4
+ will-change: auto;
4
5
  }
5
- .neshan-marker {
6
- transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
7
- will-change: transform;
6
+ .neshan-marker-body {
7
+ cursor: pointer;
8
+ transform-origin: bottom center;
8
9
  }
9
- .neshan-marker:hover {
10
+ .neshan-marker-body:hover {
10
11
  transform: scale(1.2) !important;
12
+ z-index: 999;
11
13
  }
12
14
  .neshan-marker-label {
13
15
  background: white;
14
16
  color: #1f2937;
15
- font-size: 10px;
17
+ font-size: 11px;
16
18
  font-weight: bold;
17
- padding: 4px 8px;
18
- border-radius: 6px;
19
+ padding: 3px 8px;
20
+ border-radius: 4px;
19
21
  margin-top: 4px;
20
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
22
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
21
23
  white-space: nowrap;
22
- pointer-events: none;
24
+ border: 1px solid #e5e7eb;
23
25
  }
24
- .neshan-marker-selected {
25
- animation: pulse 2s infinite;
26
+ .neshan-marker-selected .neshan-marker-body {
27
+ animation: marker-pulse 1.5s infinite ease-in-out;
26
28
  }
27
- @keyframes pulse {
29
+ @keyframes marker-pulse {
28
30
  0% {
29
- transform: scale(1);
31
+ transform: scale(1.2);
30
32
  }
31
33
  50% {
32
- transform: scale(1.15);
34
+ transform: scale(1.3);
33
35
  }
34
36
  100% {
35
- transform: scale(1);
37
+ transform: scale(1.2);
36
38
  }
37
39
  }
38
40
  /*# sourceMappingURL=index.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/styles.css"],"sourcesContent":["\r\n\r\n\r\n.neshan-map-container * {\r\n box-sizing: border-box;\r\n}\r\n\r\n\r\n.neshan-marker {\r\n transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);\r\n will-change: transform;\r\n}\r\n\r\n.neshan-marker:hover {\r\n transform: scale(1.2) !important;\r\n}\r\n\r\n\r\n.neshan-marker-label {\r\n background: white;\r\n color: #1f2937;\r\n font-size: 10px;\r\n font-weight: bold;\r\n padding: 4px 8px;\r\n border-radius: 6px;\r\n margin-top: 4px;\r\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);\r\n white-space: nowrap;\r\n pointer-events: none;\r\n}\r\n\r\n\r\n.neshan-marker-selected {\r\n animation: pulse 2s infinite;\r\n}\r\n\r\n@keyframes pulse {\r\n 0% {\r\n transform: scale(1);\r\n }\r\n 50% {\r\n transform: scale(1.15);\r\n }\r\n 100% {\r\n transform: scale(1);\r\n }\r\n}"],"mappings":";AAGA,CAAC,qBAAqB;AACpB,cAAY;AACd;AAGA,CAAC;AACC,cAAY,UAAU,KAAK,aAAa,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE;AACrD,eAAa;AACf;AAEA,CALC,aAKa;AACZ,aAAW,MAAM;AACnB;AAGA,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,kBAAgB;AAClB;AAGA,CAAC;AACC,aAAW,MAAM,GAAG;AACtB;AAEA,WAHa;AAIX;AACE,eAAW,MAAM;AACnB;AACA;AACE,eAAW,MAAM;AACnB;AACA;AACE,eAAW,MAAM;AACnB;AACF;","names":[]}
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":[]}
package/dist/index.js CHANGED
@@ -8,24 +8,25 @@ function createCustomMarkerElement({
8
8
  logoSrc = "",
9
9
  showPrice = true
10
10
  }) {
11
- const wrapper = document.createElement("div");
12
- Object.assign(wrapper.style, {
11
+ const container = document.createElement("div");
12
+ container.className = "neshan-marker-container";
13
+ const body = document.createElement("div");
14
+ body.className = `neshan-marker-body ${isSelected ? "neshan-marker-selected" : ""}`;
15
+ Object.assign(body.style, {
13
16
  display: "flex",
14
17
  flexDirection: "column",
15
18
  alignItems: "center",
16
- cursor: "pointer",
17
- transition: "all 0.3s ease",
18
- transform: isSelected ? "scale(1.2)" : "scale(1)",
19
- zIndex: isSelected ? "10" : "1"
19
+ transition: "transform 0.3s ease",
20
+ transform: isSelected ? "scale(1.2)" : "scale(1)"
20
21
  });
21
- const iconTarget = document.createElement("div");
22
- Object.assign(iconTarget.style, {
22
+ const iconBox = document.createElement("div");
23
+ Object.assign(iconBox.style, {
23
24
  width: "40px",
24
25
  height: "40px",
25
26
  borderRadius: "50%",
26
27
  backgroundColor: "white",
27
28
  border: isSelected ? "3px solid #3b82f6" : "2px solid #ef4444",
28
- boxShadow: "0 4px 6px rgba(0,0,0,0.1)",
29
+ boxShadow: "0 4px 8px rgba(0,0,0,0.2)",
29
30
  display: "flex",
30
31
  alignItems: "center",
31
32
  justifyContent: "center",
@@ -34,41 +35,32 @@ function createCustomMarkerElement({
34
35
  if (logoSrc) {
35
36
  const img = document.createElement("img");
36
37
  img.src = logoSrc;
37
- img.style.width = "80%";
38
- img.style.height = "80%";
39
- img.style.objectFit = "contain";
40
- iconTarget.appendChild(img);
38
+ img.style.width = "100%";
39
+ img.style.height = "100%";
40
+ img.style.objectFit = "cover";
41
+ iconBox.appendChild(img);
41
42
  } else {
42
- iconTarget.style.backgroundColor = "#ef4444";
43
+ iconBox.style.backgroundColor = "#ef4444";
43
44
  }
44
- wrapper.appendChild(iconTarget);
45
- if (showPrice && (marker.name || marker.price)) {
45
+ body.appendChild(iconBox);
46
+ if (showPrice && (marker.price || marker.name)) {
46
47
  const label = document.createElement("div");
47
- Object.assign(label.style, {
48
- backgroundColor: "white",
49
- padding: "2px 8px",
50
- borderRadius: "4px",
51
- marginTop: "4px",
52
- fontSize: "11px",
53
- fontWeight: "bold",
54
- whiteSpace: "nowrap",
55
- boxShadow: "0 2px 4px rgba(0,0,0,0.2)",
56
- border: "1px solid #ddd"
57
- });
58
- const labelText = marker.price ? `${marker.price} \u062A` : marker.name;
59
- label.textContent = labelText || "";
48
+ label.className = "neshan-marker-label";
49
+ label.textContent = marker.price ? `${marker.price} \u062A` : marker.name ?? "";
50
+ body.appendChild(label);
60
51
  }
61
- return wrapper;
52
+ container.appendChild(body);
53
+ return container;
62
54
  }
63
55
 
64
56
  // src/components/Map.tsx
57
+ import "@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css";
65
58
  import { jsx } from "react/jsx-runtime";
66
59
  var Map = ({
67
60
  options,
68
61
  markers = [],
69
62
  selectedMarkerId = null,
70
63
  onMarkerClick,
71
- onMapLoad,
72
64
  className = "",
73
65
  style = { width: "100%", height: "100%" }
74
66
  }) => {
@@ -77,10 +69,8 @@ var Map = ({
77
69
  const markersRef = useRef([]);
78
70
  const [mapLib, setMapLib] = useState(null);
79
71
  useEffect(() => {
80
- if (typeof window === "undefined") return;
81
72
  import("@neshan-maps-platform/mapbox-gl").then((mod) => {
82
73
  setMapLib(mod.default || mod);
83
- import("@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css");
84
74
  });
85
75
  }, []);
86
76
  useEffect(() => {
@@ -91,41 +81,32 @@ var Map = ({
91
81
  });
92
82
  map.on("load", () => {
93
83
  setMapInstance(map);
94
- onMapLoad?.(map);
95
84
  });
96
85
  return () => {
97
- if (map) map.remove();
98
86
  };
99
- }, [mapLib, options]);
87
+ }, [mapLib]);
100
88
  useEffect(() => {
101
89
  if (!mapInstance || !mapLib) return;
102
90
  markersRef.current.forEach((m) => m.remove());
103
91
  markersRef.current = [];
104
92
  markers.forEach((markerData, index) => {
93
+ const isSelected = markerData.id === selectedMarkerId;
105
94
  const el = createCustomMarkerElement({
106
95
  marker: markerData,
107
- isSelected: markerData.id === selectedMarkerId
108
- // logoSrc: markerLogoUrl // می‌توانید این را به props اضافه کنید
96
+ isSelected
109
97
  });
110
- const marker = new mapLib.Marker({ element: el }).setLngLat([markerData.lng, markerData.lat]).addTo(mapInstance);
98
+ const marker = new mapLib.Marker({
99
+ element: el,
100
+ anchor: "bottom"
101
+ }).setLngLat([markerData.lng, markerData.lat]).addTo(mapInstance);
111
102
  el.addEventListener("click", (e) => {
112
103
  e.stopPropagation();
113
104
  onMarkerClick?.(markerData, index, mapInstance);
114
105
  });
115
106
  markersRef.current.push(marker);
116
107
  });
117
- return () => {
118
- markersRef.current.forEach((m) => m.remove());
119
- };
120
- }, [markers, mapInstance, mapLib, selectedMarkerId, onMarkerClick]);
121
- return /* @__PURE__ */ jsx(
122
- "div",
123
- {
124
- ref: mapContainerRef,
125
- className,
126
- style: { position: "relative", ...style }
127
- }
128
- );
108
+ }, [markers, mapInstance, selectedMarkerId]);
109
+ return /* @__PURE__ */ jsx("div", { style: { position: "relative", ...style }, className, children: /* @__PURE__ */ jsx("div", { ref: mapContainerRef, style: { width: "100%", height: "100%" } }) });
129
110
  };
130
111
  var Map_default = Map;
131
112
  export {
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 { MapProps, MapboxMap, MarkerData } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\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 // ✅ استفاده از state به جای ref برای instance نقشه\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const markersRef = useRef<any[]>([]);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n\r\n // لود کردن کتابخانه نشان\r\n useEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n setMapLib(mod.default || mod);\r\n // لود کردن استایل‌های پیش‌فرض نشان\r\n import('@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css');\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); // ✅ اینجا باعث رندر مجدد و فعال شدن useEffect مارکرها می‌شود\r\n onMapLoad?.(map);\r\n });\r\n\r\n return () => {\r\n if (map) map.remove();\r\n };\r\n }, [mapLib, options]);\r\n\r\n // مدیریت مارکرها\r\n useEffect(() => {\r\n // ✅ حالا mapInstance به عنوان وابستگی درست کار می‌کند\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 // استفاده از ابزاری که خودتان نوشتید\r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: markerData.id === selectedMarkerId,\r\n // logoSrc: markerLogoUrl // می‌توانید این را به props اضافه کنید\r\n });\r\n\r\n const marker = new mapLib.Marker({ element: el })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\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 // پاکسازی مارکرها در صورت unmount\r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n ref={mapContainerRef} \r\n className={className} \r\n style={{ position: 'relative', ...style }} \r\n />\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 const wrapper = document.createElement('div');\r\n \r\n // استایل‌های پایه بصورت Inline برای اطمینان از نمایش\r\n Object.assign(wrapper.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n cursor: 'pointer',\r\n transition: 'all 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n zIndex: isSelected ? '10' : '1'\r\n });\r\n\r\n // بخش تصویر مارکر\r\n const iconTarget = document.createElement('div');\r\n Object.assign(iconTarget.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 6px rgba(0,0,0,0.1)',\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 = '80%';\r\n img.style.height = '80%';\r\n img.style.objectFit = 'contain';\r\n iconTarget.appendChild(img);\r\n } else {\r\n // یک دایره رنگی ساده اگر لوگو نبود\r\n iconTarget.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n wrapper.appendChild(iconTarget);\r\n\r\n // بخش برچسب قیمت\r\n if (showPrice && (marker.name || marker.price)) {\r\n const label = document.createElement('div');\r\n Object.assign(label.style, {\r\n backgroundColor: 'white',\r\n padding: '2px 8px',\r\n borderRadius: '4px',\r\n marginTop: '4px',\r\n fontSize: '11px',\r\n fontWeight: 'bold',\r\n whiteSpace: 'nowrap',\r\n boxShadow: '0 2px 4px rgba(0,0,0,0.2)',\r\n border: '1px solid #ddd'\r\n });\r\n const labelText = marker.price \r\n ? `${marker.price} ت` \r\n : marker.name;\r\n\r\nlabel.textContent = labelText || '';\r\n }\r\n\r\n return wrapper;\r\n}"],"mappings":"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","names":[]}
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\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 selectedMarkerId = null,\r\n onMarkerClick,\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 markersRef = useRef<any[]>([]);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n\r\n \r\n useEffect(() => {\r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n setMapLib(mod.default || mod);\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 });\r\n\r\n return () => {\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, index) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom' \r\n})\r\n.setLngLat([markerData.lng, markerData.lat])\r\n.addTo(mapInstance);\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 }, [markers, mapInstance, selectedMarkerId]); \r\n\r\n return (\r\n <div style={{ position: 'relative', ...style }} className={className}>\r\n <div ref={mapContainerRef} style={{ width: '100%', height: '100%' }} />\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":[]}
package/dist/react.cjs CHANGED
@@ -45,24 +45,25 @@ function createCustomMarkerElement({
45
45
  logoSrc = "",
46
46
  showPrice = true
47
47
  }) {
48
- const wrapper = document.createElement("div");
49
- Object.assign(wrapper.style, {
48
+ const container = document.createElement("div");
49
+ container.className = "neshan-marker-container";
50
+ const body = document.createElement("div");
51
+ body.className = `neshan-marker-body ${isSelected ? "neshan-marker-selected" : ""}`;
52
+ Object.assign(body.style, {
50
53
  display: "flex",
51
54
  flexDirection: "column",
52
55
  alignItems: "center",
53
- cursor: "pointer",
54
- transition: "all 0.3s ease",
55
- transform: isSelected ? "scale(1.2)" : "scale(1)",
56
- zIndex: isSelected ? "10" : "1"
56
+ transition: "transform 0.3s ease",
57
+ transform: isSelected ? "scale(1.2)" : "scale(1)"
57
58
  });
58
- const iconTarget = document.createElement("div");
59
- Object.assign(iconTarget.style, {
59
+ const iconBox = document.createElement("div");
60
+ Object.assign(iconBox.style, {
60
61
  width: "40px",
61
62
  height: "40px",
62
63
  borderRadius: "50%",
63
64
  backgroundColor: "white",
64
65
  border: isSelected ? "3px solid #3b82f6" : "2px solid #ef4444",
65
- boxShadow: "0 4px 6px rgba(0,0,0,0.1)",
66
+ boxShadow: "0 4px 8px rgba(0,0,0,0.2)",
66
67
  display: "flex",
67
68
  alignItems: "center",
68
69
  justifyContent: "center",
@@ -71,41 +72,32 @@ function createCustomMarkerElement({
71
72
  if (logoSrc) {
72
73
  const img = document.createElement("img");
73
74
  img.src = logoSrc;
74
- img.style.width = "80%";
75
- img.style.height = "80%";
76
- img.style.objectFit = "contain";
77
- iconTarget.appendChild(img);
75
+ img.style.width = "100%";
76
+ img.style.height = "100%";
77
+ img.style.objectFit = "cover";
78
+ iconBox.appendChild(img);
78
79
  } else {
79
- iconTarget.style.backgroundColor = "#ef4444";
80
+ iconBox.style.backgroundColor = "#ef4444";
80
81
  }
81
- wrapper.appendChild(iconTarget);
82
- if (showPrice && (marker.name || marker.price)) {
82
+ body.appendChild(iconBox);
83
+ if (showPrice && (marker.price || marker.name)) {
83
84
  const label = document.createElement("div");
84
- Object.assign(label.style, {
85
- backgroundColor: "white",
86
- padding: "2px 8px",
87
- borderRadius: "4px",
88
- marginTop: "4px",
89
- fontSize: "11px",
90
- fontWeight: "bold",
91
- whiteSpace: "nowrap",
92
- boxShadow: "0 2px 4px rgba(0,0,0,0.2)",
93
- border: "1px solid #ddd"
94
- });
95
- const labelText = marker.price ? `${marker.price} \u062A` : marker.name;
96
- label.textContent = labelText || "";
85
+ label.className = "neshan-marker-label";
86
+ label.textContent = marker.price ? `${marker.price} \u062A` : marker.name ?? "";
87
+ body.appendChild(label);
97
88
  }
98
- return wrapper;
89
+ container.appendChild(body);
90
+ return container;
99
91
  }
100
92
 
101
93
  // src/components/Map.tsx
94
+ var import_NeshanMapboxGl = require("@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css");
102
95
  var import_jsx_runtime = require("react/jsx-runtime");
103
96
  var Map = ({
104
97
  options,
105
98
  markers = [],
106
99
  selectedMarkerId = null,
107
100
  onMarkerClick,
108
- onMapLoad,
109
101
  className = "",
110
102
  style = { width: "100%", height: "100%" }
111
103
  }) => {
@@ -114,10 +106,8 @@ var Map = ({
114
106
  const markersRef = (0, import_react.useRef)([]);
115
107
  const [mapLib, setMapLib] = (0, import_react.useState)(null);
116
108
  (0, import_react.useEffect)(() => {
117
- if (typeof window === "undefined") return;
118
109
  import("@neshan-maps-platform/mapbox-gl").then((mod) => {
119
110
  setMapLib(mod.default || mod);
120
- import("@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css");
121
111
  });
122
112
  }, []);
123
113
  (0, import_react.useEffect)(() => {
@@ -128,41 +118,32 @@ var Map = ({
128
118
  });
129
119
  map.on("load", () => {
130
120
  setMapInstance(map);
131
- onMapLoad?.(map);
132
121
  });
133
122
  return () => {
134
- if (map) map.remove();
135
123
  };
136
- }, [mapLib, options]);
124
+ }, [mapLib]);
137
125
  (0, import_react.useEffect)(() => {
138
126
  if (!mapInstance || !mapLib) return;
139
127
  markersRef.current.forEach((m) => m.remove());
140
128
  markersRef.current = [];
141
129
  markers.forEach((markerData, index) => {
130
+ const isSelected = markerData.id === selectedMarkerId;
142
131
  const el = createCustomMarkerElement({
143
132
  marker: markerData,
144
- isSelected: markerData.id === selectedMarkerId
145
- // logoSrc: markerLogoUrl // می‌توانید این را به props اضافه کنید
133
+ isSelected
146
134
  });
147
- const marker = new mapLib.Marker({ element: el }).setLngLat([markerData.lng, markerData.lat]).addTo(mapInstance);
135
+ const marker = new mapLib.Marker({
136
+ element: el,
137
+ anchor: "bottom"
138
+ }).setLngLat([markerData.lng, markerData.lat]).addTo(mapInstance);
148
139
  el.addEventListener("click", (e) => {
149
140
  e.stopPropagation();
150
141
  onMarkerClick?.(markerData, index, mapInstance);
151
142
  });
152
143
  markersRef.current.push(marker);
153
144
  });
154
- return () => {
155
- markersRef.current.forEach((m) => m.remove());
156
- };
157
- }, [markers, mapInstance, mapLib, selectedMarkerId, onMarkerClick]);
158
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
159
- "div",
160
- {
161
- ref: mapContainerRef,
162
- className,
163
- style: { position: "relative", ...style }
164
- }
165
- );
145
+ }, [markers, mapInstance, selectedMarkerId]);
146
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "relative", ...style }, className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: mapContainerRef, style: { width: "100%", height: "100%" } }) });
166
147
  };
167
148
  var Map_default = Map;
168
149
  // Annotate the CommonJS export names for ESM import in node:
@@ -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 { MapProps, MapboxMap, MarkerData } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\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 // ✅ استفاده از state به جای ref برای instance نقشه\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const markersRef = useRef<any[]>([]);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n\r\n // لود کردن کتابخانه نشان\r\n useEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n setMapLib(mod.default || mod);\r\n // لود کردن استایل‌های پیش‌فرض نشان\r\n import('@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css');\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); // ✅ اینجا باعث رندر مجدد و فعال شدن useEffect مارکرها می‌شود\r\n onMapLoad?.(map);\r\n });\r\n\r\n return () => {\r\n if (map) map.remove();\r\n };\r\n }, [mapLib, options]);\r\n\r\n // مدیریت مارکرها\r\n useEffect(() => {\r\n // ✅ حالا mapInstance به عنوان وابستگی درست کار می‌کند\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 // استفاده از ابزاری که خودتان نوشتید\r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: markerData.id === selectedMarkerId,\r\n // logoSrc: markerLogoUrl // می‌توانید این را به props اضافه کنید\r\n });\r\n\r\n const marker = new mapLib.Marker({ element: el })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\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 // پاکسازی مارکرها در صورت unmount\r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n ref={mapContainerRef} \r\n className={className} \r\n style={{ position: 'relative', ...style }} \r\n />\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 const wrapper = document.createElement('div');\r\n \r\n // استایل‌های پایه بصورت Inline برای اطمینان از نمایش\r\n Object.assign(wrapper.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n cursor: 'pointer',\r\n transition: 'all 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n zIndex: isSelected ? '10' : '1'\r\n });\r\n\r\n // بخش تصویر مارکر\r\n const iconTarget = document.createElement('div');\r\n Object.assign(iconTarget.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 6px rgba(0,0,0,0.1)',\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 = '80%';\r\n img.style.height = '80%';\r\n img.style.objectFit = 'contain';\r\n iconTarget.appendChild(img);\r\n } else {\r\n // یک دایره رنگی ساده اگر لوگو نبود\r\n iconTarget.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n wrapper.appendChild(iconTarget);\r\n\r\n // بخش برچسب قیمت\r\n if (showPrice && (marker.name || marker.price)) {\r\n const label = document.createElement('div');\r\n Object.assign(label.style, {\r\n backgroundColor: 'white',\r\n padding: '2px 8px',\r\n borderRadius: '4px',\r\n marginTop: '4px',\r\n fontSize: '11px',\r\n fontWeight: 'bold',\r\n whiteSpace: 'nowrap',\r\n boxShadow: '0 2px 4px rgba(0,0,0,0.2)',\r\n border: '1px solid #ddd'\r\n });\r\n const labelText = marker.price \r\n ? `${marker.price} ت` \r\n : marker.name;\r\n\r\nlabel.textContent = labelText || '';\r\n }\r\n\r\n return wrapper;\r\n}"],"mappings":"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","names":[]}
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\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 selectedMarkerId = null,\r\n onMarkerClick,\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 markersRef = useRef<any[]>([]);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n\r\n \r\n useEffect(() => {\r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n setMapLib(mod.default || mod);\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 });\r\n\r\n return () => {\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, index) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom' \r\n})\r\n.setLngLat([markerData.lng, markerData.lat])\r\n.addTo(mapInstance);\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 }, [markers, mapInstance, selectedMarkerId]); \r\n\r\n return (\r\n <div style={{ position: 'relative', ...style }} className={className}>\r\n <div ref={mapContainerRef} style={{ width: '100%', height: '100%' }} />\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":[]}
package/dist/react.js CHANGED
@@ -10,24 +10,25 @@ function createCustomMarkerElement({
10
10
  logoSrc = "",
11
11
  showPrice = true
12
12
  }) {
13
- const wrapper = document.createElement("div");
14
- Object.assign(wrapper.style, {
13
+ const container = document.createElement("div");
14
+ container.className = "neshan-marker-container";
15
+ const body = document.createElement("div");
16
+ body.className = `neshan-marker-body ${isSelected ? "neshan-marker-selected" : ""}`;
17
+ Object.assign(body.style, {
15
18
  display: "flex",
16
19
  flexDirection: "column",
17
20
  alignItems: "center",
18
- cursor: "pointer",
19
- transition: "all 0.3s ease",
20
- transform: isSelected ? "scale(1.2)" : "scale(1)",
21
- zIndex: isSelected ? "10" : "1"
21
+ transition: "transform 0.3s ease",
22
+ transform: isSelected ? "scale(1.2)" : "scale(1)"
22
23
  });
23
- const iconTarget = document.createElement("div");
24
- Object.assign(iconTarget.style, {
24
+ const iconBox = document.createElement("div");
25
+ Object.assign(iconBox.style, {
25
26
  width: "40px",
26
27
  height: "40px",
27
28
  borderRadius: "50%",
28
29
  backgroundColor: "white",
29
30
  border: isSelected ? "3px solid #3b82f6" : "2px solid #ef4444",
30
- boxShadow: "0 4px 6px rgba(0,0,0,0.1)",
31
+ boxShadow: "0 4px 8px rgba(0,0,0,0.2)",
31
32
  display: "flex",
32
33
  alignItems: "center",
33
34
  justifyContent: "center",
@@ -36,41 +37,32 @@ function createCustomMarkerElement({
36
37
  if (logoSrc) {
37
38
  const img = document.createElement("img");
38
39
  img.src = logoSrc;
39
- img.style.width = "80%";
40
- img.style.height = "80%";
41
- img.style.objectFit = "contain";
42
- iconTarget.appendChild(img);
40
+ img.style.width = "100%";
41
+ img.style.height = "100%";
42
+ img.style.objectFit = "cover";
43
+ iconBox.appendChild(img);
43
44
  } else {
44
- iconTarget.style.backgroundColor = "#ef4444";
45
+ iconBox.style.backgroundColor = "#ef4444";
45
46
  }
46
- wrapper.appendChild(iconTarget);
47
- if (showPrice && (marker.name || marker.price)) {
47
+ body.appendChild(iconBox);
48
+ if (showPrice && (marker.price || marker.name)) {
48
49
  const label = document.createElement("div");
49
- Object.assign(label.style, {
50
- backgroundColor: "white",
51
- padding: "2px 8px",
52
- borderRadius: "4px",
53
- marginTop: "4px",
54
- fontSize: "11px",
55
- fontWeight: "bold",
56
- whiteSpace: "nowrap",
57
- boxShadow: "0 2px 4px rgba(0,0,0,0.2)",
58
- border: "1px solid #ddd"
59
- });
60
- const labelText = marker.price ? `${marker.price} \u062A` : marker.name;
61
- label.textContent = labelText || "";
50
+ label.className = "neshan-marker-label";
51
+ label.textContent = marker.price ? `${marker.price} \u062A` : marker.name ?? "";
52
+ body.appendChild(label);
62
53
  }
63
- return wrapper;
54
+ container.appendChild(body);
55
+ return container;
64
56
  }
65
57
 
66
58
  // src/components/Map.tsx
59
+ import "@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css";
67
60
  import { jsx } from "react/jsx-runtime";
68
61
  var Map = ({
69
62
  options,
70
63
  markers = [],
71
64
  selectedMarkerId = null,
72
65
  onMarkerClick,
73
- onMapLoad,
74
66
  className = "",
75
67
  style = { width: "100%", height: "100%" }
76
68
  }) => {
@@ -79,10 +71,8 @@ var Map = ({
79
71
  const markersRef = useRef([]);
80
72
  const [mapLib, setMapLib] = useState(null);
81
73
  useEffect(() => {
82
- if (typeof window === "undefined") return;
83
74
  import("@neshan-maps-platform/mapbox-gl").then((mod) => {
84
75
  setMapLib(mod.default || mod);
85
- import("@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css");
86
76
  });
87
77
  }, []);
88
78
  useEffect(() => {
@@ -93,41 +83,32 @@ var Map = ({
93
83
  });
94
84
  map.on("load", () => {
95
85
  setMapInstance(map);
96
- onMapLoad?.(map);
97
86
  });
98
87
  return () => {
99
- if (map) map.remove();
100
88
  };
101
- }, [mapLib, options]);
89
+ }, [mapLib]);
102
90
  useEffect(() => {
103
91
  if (!mapInstance || !mapLib) return;
104
92
  markersRef.current.forEach((m) => m.remove());
105
93
  markersRef.current = [];
106
94
  markers.forEach((markerData, index) => {
95
+ const isSelected = markerData.id === selectedMarkerId;
107
96
  const el = createCustomMarkerElement({
108
97
  marker: markerData,
109
- isSelected: markerData.id === selectedMarkerId
110
- // logoSrc: markerLogoUrl // می‌توانید این را به props اضافه کنید
98
+ isSelected
111
99
  });
112
- const marker = new mapLib.Marker({ element: el }).setLngLat([markerData.lng, markerData.lat]).addTo(mapInstance);
100
+ const marker = new mapLib.Marker({
101
+ element: el,
102
+ anchor: "bottom"
103
+ }).setLngLat([markerData.lng, markerData.lat]).addTo(mapInstance);
113
104
  el.addEventListener("click", (e) => {
114
105
  e.stopPropagation();
115
106
  onMarkerClick?.(markerData, index, mapInstance);
116
107
  });
117
108
  markersRef.current.push(marker);
118
109
  });
119
- return () => {
120
- markersRef.current.forEach((m) => m.remove());
121
- };
122
- }, [markers, mapInstance, mapLib, selectedMarkerId, onMarkerClick]);
123
- return /* @__PURE__ */ jsx(
124
- "div",
125
- {
126
- ref: mapContainerRef,
127
- className,
128
- style: { position: "relative", ...style }
129
- }
130
- );
110
+ }, [markers, mapInstance, selectedMarkerId]);
111
+ return /* @__PURE__ */ jsx("div", { style: { position: "relative", ...style }, className, children: /* @__PURE__ */ jsx("div", { ref: mapContainerRef, style: { width: "100%", height: "100%" } }) });
131
112
  };
132
113
  var Map_default = Map;
133
114
  export {
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 { MapProps, MapboxMap, MarkerData } from '../types';\r\nimport { createCustomMarkerElement } from '../utils/createCustomMarkerElement';\r\n\r\nconst Map: React.FC<MapProps> = ({\r\n options,\r\n markers = [],\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 // ✅ استفاده از state به جای ref برای instance نقشه\r\n const [mapInstance, setMapInstance] = useState<MapboxMap | null>(null);\r\n const markersRef = useRef<any[]>([]);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n\r\n // لود کردن کتابخانه نشان\r\n useEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n setMapLib(mod.default || mod);\r\n // لود کردن استایل‌های پیش‌فرض نشان\r\n import('@neshan-maps-platform/mapbox-gl/dist/NeshanMapboxGl.css');\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); // ✅ اینجا باعث رندر مجدد و فعال شدن useEffect مارکرها می‌شود\r\n onMapLoad?.(map);\r\n });\r\n\r\n return () => {\r\n if (map) map.remove();\r\n };\r\n }, [mapLib, options]);\r\n\r\n // مدیریت مارکرها\r\n useEffect(() => {\r\n // ✅ حالا mapInstance به عنوان وابستگی درست کار می‌کند\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 // استفاده از ابزاری که خودتان نوشتید\r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: markerData.id === selectedMarkerId,\r\n // logoSrc: markerLogoUrl // می‌توانید این را به props اضافه کنید\r\n });\r\n\r\n const marker = new mapLib.Marker({ element: el })\r\n .setLngLat([markerData.lng, markerData.lat])\r\n .addTo(mapInstance);\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 // پاکسازی مارکرها در صورت unmount\r\n return () => {\r\n markersRef.current.forEach((m) => m.remove());\r\n };\r\n }, [markers, mapInstance, mapLib, selectedMarkerId, onMarkerClick]);\r\n\r\n return (\r\n <div \r\n ref={mapContainerRef} \r\n className={className} \r\n style={{ position: 'relative', ...style }} \r\n />\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 const wrapper = document.createElement('div');\r\n \r\n // استایل‌های پایه بصورت Inline برای اطمینان از نمایش\r\n Object.assign(wrapper.style, {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n cursor: 'pointer',\r\n transition: 'all 0.3s ease',\r\n transform: isSelected ? 'scale(1.2)' : 'scale(1)',\r\n zIndex: isSelected ? '10' : '1'\r\n });\r\n\r\n // بخش تصویر مارکر\r\n const iconTarget = document.createElement('div');\r\n Object.assign(iconTarget.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 6px rgba(0,0,0,0.1)',\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 = '80%';\r\n img.style.height = '80%';\r\n img.style.objectFit = 'contain';\r\n iconTarget.appendChild(img);\r\n } else {\r\n // یک دایره رنگی ساده اگر لوگو نبود\r\n iconTarget.style.backgroundColor = '#ef4444';\r\n }\r\n\r\n wrapper.appendChild(iconTarget);\r\n\r\n // بخش برچسب قیمت\r\n if (showPrice && (marker.name || marker.price)) {\r\n const label = document.createElement('div');\r\n Object.assign(label.style, {\r\n backgroundColor: 'white',\r\n padding: '2px 8px',\r\n borderRadius: '4px',\r\n marginTop: '4px',\r\n fontSize: '11px',\r\n fontWeight: 'bold',\r\n whiteSpace: 'nowrap',\r\n boxShadow: '0 2px 4px rgba(0,0,0,0.2)',\r\n border: '1px solid #ddd'\r\n });\r\n const labelText = marker.price \r\n ? `${marker.price} ت` \r\n : marker.name;\r\n\r\nlabel.textContent = labelText || '';\r\n }\r\n\r\n return wrapper;\r\n}"],"mappings":"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","names":[]}
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\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 selectedMarkerId = null,\r\n onMarkerClick,\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 markersRef = useRef<any[]>([]);\r\n const [mapLib, setMapLib] = useState<any>(null);\r\n\r\n \r\n useEffect(() => {\r\n import('@neshan-maps-platform/mapbox-gl').then((mod) => {\r\n setMapLib(mod.default || mod);\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 });\r\n\r\n return () => {\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, index) => {\r\n const isSelected = markerData.id === selectedMarkerId;\r\n const el = createCustomMarkerElement({\r\n marker: markerData,\r\n isSelected: isSelected,\r\n });\r\n\r\n \r\n const marker = new mapLib.Marker({ \r\n element: el,\r\n anchor: 'bottom' \r\n})\r\n.setLngLat([markerData.lng, markerData.lat])\r\n.addTo(mapInstance);\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 }, [markers, mapInstance, selectedMarkerId]); \r\n\r\n return (\r\n <div style={{ position: 'relative', ...style }} className={className}>\r\n <div ref={mapContainerRef} style={{ width: '100%', height: '100%' }} />\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":[]}
package/dist/styles.css CHANGED
@@ -1,47 +1,40 @@
1
1
 
2
-
3
-
4
- .neshan-map-container * {
5
- box-sizing: border-box;
2
+ .neshan-marker-container {
3
+ pointer-events: auto;
4
+ will-change: auto;
6
5
  }
7
6
 
8
7
 
9
- .neshan-marker {
10
- transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
11
- will-change: transform;
8
+ .neshan-marker-body {
9
+ cursor: pointer;
10
+ transform-origin: bottom center;
12
11
  }
13
12
 
14
- .neshan-marker:hover {
13
+ .neshan-marker-body:hover {
15
14
  transform: scale(1.2) !important;
15
+ z-index: 999;
16
16
  }
17
17
 
18
-
19
18
  .neshan-marker-label {
20
19
  background: white;
21
20
  color: #1f2937;
22
- font-size: 10px;
21
+ font-size: 11px;
23
22
  font-weight: bold;
24
- padding: 4px 8px;
25
- border-radius: 6px;
23
+ padding: 3px 8px;
24
+ border-radius: 4px;
26
25
  margin-top: 4px;
27
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
26
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
28
27
  white-space: nowrap;
29
- pointer-events: none;
28
+ border: 1px solid #e5e7eb;
30
29
  }
31
30
 
32
31
 
33
- .neshan-marker-selected {
34
- animation: pulse 2s infinite;
32
+ .neshan-marker-selected .neshan-marker-body {
33
+ animation: marker-pulse 1.5s infinite ease-in-out;
35
34
  }
36
35
 
37
- @keyframes pulse {
38
- 0% {
39
- transform: scale(1);
40
- }
41
- 50% {
42
- transform: scale(1.15);
43
- }
44
- 100% {
45
- transform: scale(1);
46
- }
36
+ @keyframes marker-pulse {
37
+ 0% { transform: scale(1.2); }
38
+ 50% { transform: scale(1.3); }
39
+ 100% { transform: scale(1.2); }
47
40
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createCustomMarkerElement.d.ts","sourceRoot":"","sources":["../../src/utils/createCustomMarkerElement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,UAAU,mBAAmB;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,yBAAyB,CAAC,EACxC,MAAM,EACN,UAAU,EACV,OAAY,EACZ,SAAgB,GACjB,EAAE,mBAAmB,GAAG,WAAW,CAiEnC"}
1
+ {"version":3,"file":"createCustomMarkerElement.d.ts","sourceRoot":"","sources":["../../src/utils/createCustomMarkerElement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,UAAU,mBAAmB;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,yBAAyB,CAAC,EACxC,MAAM,EACN,UAAU,EACV,OAAY,EACZ,SAAgB,GACjB,EAAE,mBAAmB,GAAG,WAAW,CAwDnC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mehdi-akbari-map",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "A professional Map",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",