@mamrp/components 1.7.27 → 1.7.30

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.
@@ -15,6 +15,36 @@ interface Props$1 {
15
15
  fill?: boolean;
16
16
  }[];
17
17
  height?: number;
18
+ /**
19
+ * حداقل مقدار محور Y (اختیاری)
20
+ * اگر ست نشود، Chart.js خودش محاسبه می‌کند
21
+ * ⚠️ نکته: اگر این مقدار ست شود، beginAtZero نادیده گرفته می‌شود
22
+ */
23
+ yAxisMin?: number;
24
+ /**
25
+ * حداکثر مقدار محور Y (اختیاری)
26
+ * اگر ست نشود، Chart.js خودش محاسبه می‌کند
27
+ */
28
+ yAxisMax?: number;
29
+ /**
30
+ * آیا محور Y از صفر شروع شود؟
31
+ * پیش‌فرض: true
32
+ * ⚠️ نکته: اگر yAxisMin ست شود، این گزینه نادیده گرفته می‌شود
33
+ */
34
+ beginAtZero?: boolean;
35
+ /**
36
+ * استفاده از مقیاس لگاریتمی برای محور Y
37
+ * مناسب برای داده‌هایی که اختلاف خیلی زیادی دارند
38
+ * پیش‌فرض: false
39
+ * ⚠️ نکته: مقادیر 0 یا منفی در مقیاس لگاریتمی نمایش داده نمی‌شوند
40
+ */
41
+ logarithmic?: boolean;
42
+ /**
43
+ * حداقل ارتفاع میله برای داده‌های خیلی کوچک (پیکسل)
44
+ * مقادیر خیلی کوچک (مثل 1) در کنار مقادیر بزرگ (مثل 10000) گم نمی‌شوند
45
+ * پیش‌فرض: 0 (غیرفعال)
46
+ */
47
+ minBarLength?: number;
18
48
  }
19
49
  /**
20
50
  * 📊 BarChart — کامپوننت نمودار میله‌ای (Bar/Combo)
@@ -46,6 +76,11 @@ interface Props$1 {
46
76
  * - fill: (اختیاری) پر شدن زیر خط (برای سری‌های خطی)
47
77
  *
48
78
  * @param {number} [height] - ارتفاع نمودار (پیش‌فرض: 600 پیکسل)
79
+ * @param {number} [yAxisMin] - حداقل مقدار محور Y (نادیده‌گرفتن beginAtZero)
80
+ * @param {number} [yAxisMax] - حداکثر مقدار محور Y
81
+ * @param {boolean} [beginAtZero=true] - آیا محور Y از صفر شروع شود؟ (اگر yAxisMin ست شود نادیده گرفته می‌شود)
82
+ * @param {boolean} [logarithmic=false] - استفاده از مقیاس لگاریتمی (مقادیر 0 یا منفی نمایش داده نمی‌شوند)
83
+ * @param {number} [minBarLength=0] - حداقل ارتفاع میله (پیکسل) - برای جلوگیری از گم شدن داده‌های کوچک
49
84
  *
50
85
  * @description
51
86
  * این کامپوننت یک نمودار میله‌ای (Bar) یا ترکیبی Bar/Line با قابلیت شخصی‌سازی کامل است.
@@ -53,11 +88,14 @@ interface Props$1 {
53
88
  * - ریسپانسیو و مناسب صفحات فارسی
54
89
  * - امکان نمایش چند سری داده به صورت میله‌ای و خطی همزمان (Combo)
55
90
  * - شخصی‌سازی رنگ، ضخامت، ترتیب و استایل هر سری
91
+ * - پشتیبانی از مقیاس لگاریتمی برای داده‌های با اختلاف زیاد
92
+ * - minBarLength برای نمایش داده‌های خیلی کوچک در کنار بزرگ‌ها
56
93
  *
57
94
  * @returns {JSX.Element} یک نمودار میله‌ای یا ترکیبی با داده‌های ورودی
58
95
  *
59
96
  * @example
60
97
  * ```jsx
98
+ * // نمودار ساده
61
99
  * <BarChart
62
100
  * labels={["شنبه", "یکشنبه", "دوشنبه"]}
63
101
  * datasets={[
@@ -66,24 +104,42 @@ interface Props$1 {
66
104
  * data: [10, 20, 15],
67
105
  * backgroundColor: "rgba(75,192,192,0.7)",
68
106
  * },
107
+ * ]}
108
+ * height={400}
109
+ * />
110
+ *
111
+ * // نمودار با داده‌های اختلاف زیاد (مقیاس لگاریتمی)
112
+ * <BarChart
113
+ * labels={["A", "B", "C", "D"]}
114
+ * datasets={[
115
+ * {
116
+ * label: "مقادیر",
117
+ * data: [5, 50, 5000, 50000],
118
+ * backgroundColor: "rgba(75,192,192,0.7)",
119
+ * },
120
+ * ]}
121
+ * logarithmic={true}
122
+ * height={400}
123
+ * />
124
+ *
125
+ * // نمودار با کنترل دستی بازه محور Y
126
+ * <BarChart
127
+ * labels={["A", "B", "C"]}
128
+ * datasets={[
69
129
  * {
70
- * label: "میانگین",
71
- * data: [12, 18, 14],
72
- * borderColor: "red",
73
- * backgroundColor: "transparent",
74
- * type: "line",
75
- * order: 0,
76
- * borderWidth: 3,
77
- * tension: 0.4,
78
- * pointRadius: 4,
79
- * fill: false,
130
+ * label: "مقادیر",
131
+ * data: [100, 150, 120],
132
+ * backgroundColor: "rgba(75,192,192,0.7)",
80
133
  * },
81
134
  * ]}
135
+ * yAxisMin={80}
136
+ * yAxisMax={200}
137
+ * beginAtZero={false}
82
138
  * height={400}
83
139
  * />
84
140
  * ```
85
141
  */
86
- declare function BarChart({ labels, datasets, height }: Props$1): React.JSX.Element;
142
+ declare function BarChart({ labels, datasets, height, yAxisMin, yAxisMax, beginAtZero, logarithmic, minBarLength, }: Props$1): React.JSX.Element;
87
143
 
88
144
  interface Props {
89
145
  labels: string[];
@@ -15,6 +15,36 @@ interface Props$1 {
15
15
  fill?: boolean;
16
16
  }[];
17
17
  height?: number;
18
+ /**
19
+ * حداقل مقدار محور Y (اختیاری)
20
+ * اگر ست نشود، Chart.js خودش محاسبه می‌کند
21
+ * ⚠️ نکته: اگر این مقدار ست شود، beginAtZero نادیده گرفته می‌شود
22
+ */
23
+ yAxisMin?: number;
24
+ /**
25
+ * حداکثر مقدار محور Y (اختیاری)
26
+ * اگر ست نشود، Chart.js خودش محاسبه می‌کند
27
+ */
28
+ yAxisMax?: number;
29
+ /**
30
+ * آیا محور Y از صفر شروع شود؟
31
+ * پیش‌فرض: true
32
+ * ⚠️ نکته: اگر yAxisMin ست شود، این گزینه نادیده گرفته می‌شود
33
+ */
34
+ beginAtZero?: boolean;
35
+ /**
36
+ * استفاده از مقیاس لگاریتمی برای محور Y
37
+ * مناسب برای داده‌هایی که اختلاف خیلی زیادی دارند
38
+ * پیش‌فرض: false
39
+ * ⚠️ نکته: مقادیر 0 یا منفی در مقیاس لگاریتمی نمایش داده نمی‌شوند
40
+ */
41
+ logarithmic?: boolean;
42
+ /**
43
+ * حداقل ارتفاع میله برای داده‌های خیلی کوچک (پیکسل)
44
+ * مقادیر خیلی کوچک (مثل 1) در کنار مقادیر بزرگ (مثل 10000) گم نمی‌شوند
45
+ * پیش‌فرض: 0 (غیرفعال)
46
+ */
47
+ minBarLength?: number;
18
48
  }
19
49
  /**
20
50
  * 📊 BarChart — کامپوننت نمودار میله‌ای (Bar/Combo)
@@ -46,6 +76,11 @@ interface Props$1 {
46
76
  * - fill: (اختیاری) پر شدن زیر خط (برای سری‌های خطی)
47
77
  *
48
78
  * @param {number} [height] - ارتفاع نمودار (پیش‌فرض: 600 پیکسل)
79
+ * @param {number} [yAxisMin] - حداقل مقدار محور Y (نادیده‌گرفتن beginAtZero)
80
+ * @param {number} [yAxisMax] - حداکثر مقدار محور Y
81
+ * @param {boolean} [beginAtZero=true] - آیا محور Y از صفر شروع شود؟ (اگر yAxisMin ست شود نادیده گرفته می‌شود)
82
+ * @param {boolean} [logarithmic=false] - استفاده از مقیاس لگاریتمی (مقادیر 0 یا منفی نمایش داده نمی‌شوند)
83
+ * @param {number} [minBarLength=0] - حداقل ارتفاع میله (پیکسل) - برای جلوگیری از گم شدن داده‌های کوچک
49
84
  *
50
85
  * @description
51
86
  * این کامپوننت یک نمودار میله‌ای (Bar) یا ترکیبی Bar/Line با قابلیت شخصی‌سازی کامل است.
@@ -53,11 +88,14 @@ interface Props$1 {
53
88
  * - ریسپانسیو و مناسب صفحات فارسی
54
89
  * - امکان نمایش چند سری داده به صورت میله‌ای و خطی همزمان (Combo)
55
90
  * - شخصی‌سازی رنگ، ضخامت، ترتیب و استایل هر سری
91
+ * - پشتیبانی از مقیاس لگاریتمی برای داده‌های با اختلاف زیاد
92
+ * - minBarLength برای نمایش داده‌های خیلی کوچک در کنار بزرگ‌ها
56
93
  *
57
94
  * @returns {JSX.Element} یک نمودار میله‌ای یا ترکیبی با داده‌های ورودی
58
95
  *
59
96
  * @example
60
97
  * ```jsx
98
+ * // نمودار ساده
61
99
  * <BarChart
62
100
  * labels={["شنبه", "یکشنبه", "دوشنبه"]}
63
101
  * datasets={[
@@ -66,24 +104,42 @@ interface Props$1 {
66
104
  * data: [10, 20, 15],
67
105
  * backgroundColor: "rgba(75,192,192,0.7)",
68
106
  * },
107
+ * ]}
108
+ * height={400}
109
+ * />
110
+ *
111
+ * // نمودار با داده‌های اختلاف زیاد (مقیاس لگاریتمی)
112
+ * <BarChart
113
+ * labels={["A", "B", "C", "D"]}
114
+ * datasets={[
115
+ * {
116
+ * label: "مقادیر",
117
+ * data: [5, 50, 5000, 50000],
118
+ * backgroundColor: "rgba(75,192,192,0.7)",
119
+ * },
120
+ * ]}
121
+ * logarithmic={true}
122
+ * height={400}
123
+ * />
124
+ *
125
+ * // نمودار با کنترل دستی بازه محور Y
126
+ * <BarChart
127
+ * labels={["A", "B", "C"]}
128
+ * datasets={[
69
129
  * {
70
- * label: "میانگین",
71
- * data: [12, 18, 14],
72
- * borderColor: "red",
73
- * backgroundColor: "transparent",
74
- * type: "line",
75
- * order: 0,
76
- * borderWidth: 3,
77
- * tension: 0.4,
78
- * pointRadius: 4,
79
- * fill: false,
130
+ * label: "مقادیر",
131
+ * data: [100, 150, 120],
132
+ * backgroundColor: "rgba(75,192,192,0.7)",
80
133
  * },
81
134
  * ]}
135
+ * yAxisMin={80}
136
+ * yAxisMax={200}
137
+ * beginAtZero={false}
82
138
  * height={400}
83
139
  * />
84
140
  * ```
85
141
  */
86
- declare function BarChart({ labels, datasets, height }: Props$1): React.JSX.Element;
142
+ declare function BarChart({ labels, datasets, height, yAxisMin, yAxisMax, beginAtZero, logarithmic, minBarLength, }: Props$1): React.JSX.Element;
87
143
 
88
144
  interface Props {
89
145
  labels: string[];
@@ -42,9 +42,11 @@ var React = __toESM(require("react"));
42
42
  var import_react_chartjs_2 = require("react-chartjs-2");
43
43
  var import_chart = require("chart.js");
44
44
  var import_material = require("@mui/material");
45
+ var import_react = require("react");
45
46
  import_chart.Chart.register(
46
47
  import_chart.CategoryScale,
47
48
  import_chart.LinearScale,
49
+ import_chart.LogarithmicScale,
48
50
  import_chart.BarElement,
49
51
  import_chart.LineElement,
50
52
  import_chart.PointElement,
@@ -53,16 +55,113 @@ import_chart.Chart.register(
53
55
  import_chart.BarController,
54
56
  import_chart.LineController
55
57
  );
56
- function BarChart({ labels, datasets, height }) {
58
+ import_chart.Chart.defaults.font.family = "Vazir, sans-serif";
59
+ function BarChart({
60
+ labels,
61
+ datasets,
62
+ height,
63
+ yAxisMin,
64
+ yAxisMax,
65
+ beginAtZero = true,
66
+ logarithmic = false,
67
+ minBarLength = 0
68
+ }) {
69
+ const chartRef = (0, import_react.useRef)(null);
70
+ const [fontLoaded, setFontLoaded] = (0, import_react.useState)(false);
71
+ (0, import_react.useEffect)(() => {
72
+ let isMounted = true;
73
+ const loadFont = async () => {
74
+ if (typeof document !== "undefined" && document.fonts) {
75
+ try {
76
+ await document.fonts.load("16px Vazir");
77
+ await document.fonts.ready;
78
+ } catch (e) {
79
+ }
80
+ if (isMounted) {
81
+ setFontLoaded(true);
82
+ setTimeout(() => {
83
+ if (chartRef.current) {
84
+ chartRef.current.update();
85
+ }
86
+ }, 100);
87
+ }
88
+ } else {
89
+ if (isMounted) setFontLoaded(true);
90
+ }
91
+ };
92
+ loadFont();
93
+ return () => {
94
+ isMounted = false;
95
+ };
96
+ }, []);
97
+ const getVisibleData = () => {
98
+ if (!chartRef.current) return [];
99
+ return datasets.reduce((acc, ds, i) => {
100
+ if ((ds.type === void 0 || ds.type === "bar") && chartRef.current && typeof chartRef.current.isDatasetVisible === "function" && chartRef.current.isDatasetVisible(i)) {
101
+ ds.data.forEach((v) => {
102
+ if (typeof v === "number" && v > 0) acc.push(v);
103
+ });
104
+ }
105
+ return acc;
106
+ }, []);
107
+ };
108
+ let autoMin = yAxisMin;
109
+ let autoMax = yAxisMax;
110
+ if (logarithmic && yAxisMin === void 0 && yAxisMax === void 0) {
111
+ const visibleData = getVisibleData();
112
+ if (visibleData.length) {
113
+ const minVal = Math.min(...visibleData);
114
+ const maxVal = Math.max(...visibleData);
115
+ autoMin = minVal < 1 ? 0.5 : minVal * 0.7;
116
+ autoMax = minVal === maxVal ? maxVal * 1.2 : maxVal * 1.1;
117
+ }
118
+ }
119
+ (0, import_react.useEffect)(() => {
120
+ if (!logarithmic || yAxisMin !== void 0 || yAxisMax !== void 0) return;
121
+ if (!chartRef.current) return;
122
+ const handler = () => {
123
+ const visibleData = getVisibleData();
124
+ if (visibleData.length && chartRef.current && chartRef.current.options && chartRef.current.options.scales && chartRef.current.options.scales.y) {
125
+ const minVal = Math.min(...visibleData);
126
+ const maxVal = Math.max(...visibleData);
127
+ chartRef.current.options.scales.y.min = minVal < 1 ? 0.5 : minVal * 0.7;
128
+ chartRef.current.options.scales.y.max = minVal === maxVal ? maxVal * 1.2 : maxVal * 1.1;
129
+ chartRef.current.update();
130
+ }
131
+ };
132
+ chartRef.current?.canvas?.addEventListener("click", handler);
133
+ return () => {
134
+ chartRef.current?.canvas?.removeEventListener("click", handler);
135
+ };
136
+ }, [logarithmic, yAxisMin, yAxisMax, datasets]);
57
137
  const options = {
58
138
  responsive: true,
59
139
  maintainAspectRatio: false,
60
140
  scales: {
61
141
  y: {
142
+ type: logarithmic ? "logarithmic" : "linear",
143
+ ...yAxisMin === void 0 && yAxisMax === void 0 && !logarithmic && {
144
+ beginAtZero
145
+ },
146
+ ...autoMin !== void 0 && { min: autoMin },
147
+ ...autoMax !== void 0 && { max: autoMax },
62
148
  ticks: {
63
149
  font: {
64
- family: "'Vazir', sans-serif",
150
+ family: "Vazir, sans-serif",
65
151
  size: 14
152
+ },
153
+ ...logarithmic && {
154
+ callback: function(value) {
155
+ const numValue = Number(value);
156
+ if (numValue === 0) return null;
157
+ const log10 = Math.log10(numValue);
158
+ if (Math.abs(log10 - Math.round(log10)) < 1e-4) {
159
+ if (numValue >= 1e6) return (numValue / 1e6).toFixed(1) + "M";
160
+ if (numValue >= 1e3) return (numValue / 1e3).toFixed(1) + "K";
161
+ return numValue;
162
+ }
163
+ return null;
164
+ }
66
165
  }
67
166
  }
68
167
  },
@@ -70,7 +169,7 @@ function BarChart({ labels, datasets, height }) {
70
169
  ticks: {
71
170
  autoSkip: false,
72
171
  font: {
73
- family: "'Vazir', sans-serif",
172
+ family: "Vazir, sans-serif",
74
173
  size: 13
75
174
  }
76
175
  }
@@ -83,11 +182,11 @@ function BarChart({ labels, datasets, height }) {
83
182
  },
84
183
  tooltip: {
85
184
  bodyFont: {
86
- family: "'Vazir', sans-serif",
185
+ family: "Vazir, sans-serif",
87
186
  size: 14
88
187
  },
89
188
  titleFont: {
90
- family: "'Vazir', sans-serif",
189
+ family: "Vazir, sans-serif",
91
190
  size: 16
92
191
  }
93
192
  },
@@ -106,7 +205,7 @@ function BarChart({ labels, datasets, height }) {
106
205
  usePointStyle: true,
107
206
  font: {
108
207
  size: 16,
109
- family: "'Vazir', sans-serif"
208
+ family: "Vazir, sans-serif"
110
209
  },
111
210
  boxWidth: 40,
112
211
  paddingBottom: 10
@@ -114,16 +213,22 @@ function BarChart({ labels, datasets, height }) {
114
213
  }
115
214
  }
116
215
  };
117
- return /* @__PURE__ */ React.createElement(import_material.Box, { height: height ?? 600 }, /* @__PURE__ */ React.createElement(import_react_chartjs_2.Chart, { type: "bar", data: { labels, datasets }, options }));
216
+ const processedDatasets = datasets.map((ds) => ({
217
+ ...ds,
218
+ minBarLength
219
+ }));
220
+ return /* @__PURE__ */ React.createElement(import_material.Box, { height: height ?? 600 }, fontLoaded && /* @__PURE__ */ React.createElement(import_react_chartjs_2.Chart, { ref: chartRef, type: "bar", data: { labels, datasets: processedDatasets }, options }));
118
221
  }
119
222
 
120
223
  // src/charts/pie/index.tsx
121
224
  var import_react_chartjs_22 = require("react-chartjs-2");
122
225
  var import_chart2 = require("chart.js");
226
+ var import_react2 = require("react");
123
227
  var import_material2 = require("@mui/material");
124
228
  var import_image = __toESM(require("next/image"));
125
229
  var import_chartjs_plugin_datalabels = __toESM(require("chartjs-plugin-datalabels"));
126
230
  import_chart2.Chart.register(import_chart2.ArcElement, import_chart2.Tooltip, import_chart2.Legend, import_chartjs_plugin_datalabels.default);
231
+ import_chart2.Chart.defaults.font.family = "Vazir, sans-serif";
127
232
  function PieChart({
128
233
  labels,
129
234
  datasets,
@@ -133,18 +238,83 @@ function PieChart({
133
238
  showDataLabels = false,
134
239
  showPercentage = false
135
240
  }) {
136
- const options = {
241
+ const chartRef = (0, import_react2.useRef)(null);
242
+ const [dataLabels, setDataLabels] = (0, import_react2.useState)([]);
243
+ const containerRef = (0, import_react2.useRef)(null);
244
+ const calculateLabels = () => {
245
+ if (!showDataLabels || !chartRef.current || !containerRef.current) return;
246
+ const chart = chartRef.current;
247
+ const meta = chart.getDatasetMeta(0);
248
+ const data = chart.data.datasets[0].data;
249
+ const chartArea = chart.chartArea;
250
+ const visibleTotal = data.reduce((sum, val, index) => {
251
+ if (!meta.data[index] || meta.data[index].hidden !== true) {
252
+ return sum + val;
253
+ }
254
+ return sum;
255
+ }, 0);
256
+ const newLabels = [];
257
+ meta.data.forEach((arc, index) => {
258
+ if (arc.hidden) return;
259
+ const value = data[index];
260
+ if (value === 0) return;
261
+ const centerAngle = (arc.startAngle + arc.endAngle) / 2;
262
+ const midRadius = arc.innerRadius + (arc.outerRadius - arc.innerRadius) * 0.65;
263
+ const x = arc.x - Math.cos(centerAngle) * midRadius;
264
+ const y = arc.y + Math.sin(centerAngle) * midRadius;
265
+ let text;
266
+ if (showPercentage) {
267
+ const percentage = (value / visibleTotal * 100).toFixed(1);
268
+ text = percentage + "%";
269
+ } else {
270
+ text = String(value);
271
+ }
272
+ newLabels.push({ x, y, text, opacity: 1 });
273
+ });
274
+ setDataLabels(newLabels);
275
+ };
276
+ (0, import_react2.useEffect)(() => {
277
+ if (!showDataLabels) {
278
+ setDataLabels([]);
279
+ return;
280
+ }
281
+ const timeout = setTimeout(() => {
282
+ calculateLabels();
283
+ }, 500);
284
+ return () => clearTimeout(timeout);
285
+ }, [datasets, showDataLabels, showPercentage]);
286
+ (0, import_react2.useEffect)(() => {
287
+ if (!chartRef.current || !showDataLabels) return;
288
+ const chart = chartRef.current;
289
+ const originalUpdate = chart.update.bind(chart);
290
+ chart.update = function(...args) {
291
+ setDataLabels((prev) => prev.map((l) => ({ ...l, opacity: 0 })));
292
+ originalUpdate(...args);
293
+ setTimeout(() => {
294
+ calculateLabels();
295
+ }, 250);
296
+ };
297
+ return () => {
298
+ chart.update = originalUpdate;
299
+ };
300
+ }, [showDataLabels, showPercentage]);
301
+ const options = (0, import_react2.useMemo)(() => ({
137
302
  responsive: true,
138
303
  maintainAspectRatio: false,
139
304
  cutout: !disableLogo ? "59%" : "0%",
305
+ animation: {
306
+ animateRotate: true,
307
+ animateScale: true,
308
+ duration: 400
309
+ },
140
310
  plugins: {
141
311
  tooltip: {
142
312
  bodyFont: {
143
- family: "'Vazir', sans-serif",
313
+ family: "Vazir, sans-serif",
144
314
  size: 14
145
315
  },
146
316
  titleFont: {
147
- family: "'Vazir', sans-serif",
317
+ family: "Vazir, sans-serif",
148
318
  size: 16
149
319
  }
150
320
  },
@@ -156,7 +326,7 @@ function PieChart({
156
326
  // رنگ متن legend را نرم‌تر می‌کند
157
327
  font: {
158
328
  size: 16,
159
- family: "'Vazir', sans-serif"
329
+ family: "Vazir, sans-serif"
160
330
  },
161
331
  boxWidth: 40,
162
332
  paddingBottom: 10,
@@ -187,38 +357,11 @@ function PieChart({
187
357
  }
188
358
  },
189
359
  datalabels: {
190
- display: (context) => {
191
- return showDataLabels && !context.chart.getDatasetMeta(context.datasetIndex).data[context.dataIndex].hidden;
192
- },
193
- color: "#fff",
194
- font: {
195
- size: 14,
196
- weight: "bold",
197
- family: "'Vazir', sans-serif"
198
- },
199
- anchor: "center",
200
- // ← روی مرکز هر تکه
201
- align: "center",
202
- offset: 20,
203
- // فاصله از مرکز (می‌تونی کم/زیاد کنی)
204
- formatter: showPercentage ? (value, context) => {
205
- if (value === 0) return "";
206
- const total = context.chart.data.datasets[context.datasetIndex].data.reduce(
207
- (sum, val, index) => {
208
- const meta = context.chart.getDatasetMeta(context.datasetIndex);
209
- if (!meta.data[index] || meta.data[index].hidden !== true) {
210
- return sum + val;
211
- }
212
- return sum;
213
- },
214
- 0
215
- );
216
- const percentage = (value / total * 100).toFixed(1);
217
- return percentage + "%";
218
- } : (value) => value === 0 ? "" : value
360
+ display: false
361
+ // غیرفعال - لیبل‌ها با React رندر می‌شوند
219
362
  }
220
363
  }
221
- };
364
+ }), [disableLogo]);
222
365
  const CenterComponent = () => {
223
366
  return /* @__PURE__ */ React.createElement(
224
367
  "div",
@@ -242,16 +385,37 @@ function PieChart({
242
385
  )
243
386
  );
244
387
  };
245
- return /* @__PURE__ */ React.createElement(import_material2.Box, { height: height ?? 600, sx: { position: "relative" } }, /* @__PURE__ */ React.createElement(
388
+ return /* @__PURE__ */ React.createElement(import_material2.Box, { ref: containerRef, height: height ?? 600, sx: { position: "relative" } }, /* @__PURE__ */ React.createElement(
246
389
  import_react_chartjs_22.Pie,
247
390
  {
391
+ ref: chartRef,
248
392
  data: {
249
393
  labels,
250
394
  datasets
251
395
  },
252
396
  options
253
397
  }
254
- ), !disableLogo && /* @__PURE__ */ React.createElement(
398
+ ), showDataLabels && dataLabels.map((label, index) => /* @__PURE__ */ React.createElement(
399
+ import_material2.Typography,
400
+ {
401
+ key: index,
402
+ sx: {
403
+ position: "absolute",
404
+ left: label.x / (window.devicePixelRatio || 1),
405
+ top: label.y / (window.devicePixelRatio || 1),
406
+ transform: "translate(-50%, -50%)",
407
+ color: "#fff",
408
+ fontWeight: "bold",
409
+ fontSize: 14,
410
+ fontFamily: "Vazir, sans-serif",
411
+ pointerEvents: "none",
412
+ textShadow: "0 1px 2px rgba(0,0,0,0.5)",
413
+ opacity: label.opacity,
414
+ transition: "opacity 0.2s ease-in-out, left 0.2s ease-in-out, top 0.2s ease-in-out"
415
+ }
416
+ },
417
+ label.text
418
+ )), !disableLogo && /* @__PURE__ */ React.createElement(
255
419
  "div",
256
420
  {
257
421
  style: {