@mamrp/components 1.7.31 → 1.7.33

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.
@@ -17,6 +17,93 @@ interface Props$1 {
17
17
  datasets: Dataset[];
18
18
  height?: number;
19
19
  }
20
+ /**
21
+ * 📊 BarChart — کامپوننت نمودار میله‌ای (Bar / Combo Bar+Line)
22
+ *
23
+ * @component BarChart
24
+ *
25
+ * @param {string[]} labels
26
+ * آرایه‌ای از برچسب‌های محور افقی (X). طول این آرایه مبنای تمام داده‌هاست.
27
+ *
28
+ * @param {Array<{
29
+ * label: string,
30
+ * data: (number | null)[],
31
+ * backgroundColor: string,
32
+ * borderColor?: string,
33
+ * borderWidth?: number,
34
+ * type?: "line",
35
+ * order?: number,
36
+ * tension?: number,
37
+ * pointRadius?: number,
38
+ * fill?: boolean
39
+ * }>} datasets
40
+ *
41
+ * آرایه‌ای از سری‌های داده برای نمایش در نمودار.
42
+ * هر آبجکت یک سری داده است که می‌تواند میله‌ای (Bar) یا خطی (Line) باشد:
43
+ *
44
+ * - ● **label**: عنوان سری (نمایش در Legend)
45
+ * - ● **data**: مقادیر هر نقطه – مقدار `null` باعث حذف نقطه از نمودار می‌شود.
46
+ * - ● **backgroundColor**: رنگ میله یا رنگ پرشدگی خط
47
+ * - ● **borderColor**: (اختیاری) رنگ خط دور میله یا خط
48
+ * - ● **borderWidth**: (اختیاری) ضخامت خط دور میله یا خط
49
+ * - ● **type**: اگر `"line"` باشد، سری به صورت نمودار خطی نمایش داده می‌شود (Combo chart)
50
+ * - ● **order**: ترتیب رسم (سری با order بزرگ‌تر روی سایر سری‌ها قرار می‌گیرد)
51
+ * - ● **tension**: (خطی) میزان خمیدگی منحنی (۰ = خط صاف)
52
+ * - ● **pointRadius**: (خطی) شعاع نقاط
53
+ * - ● **fill**: (خطی) پر شدن زیر نمودار خطی
54
+ *
55
+ *
56
+ * @param {number} [height=600]
57
+ * ارتفاع نمودار بر حسب پیکسل.
58
+ *
59
+ *
60
+ * @description
61
+ * این کامپوننت یک نمودار میله‌ای (BarChart) با پشتیبانی از **نمودار ترکیبی Bar + Line**
62
+ * است و برای نمایش داده‌ها در محیط فارسی و راست‌چین بهینه‌سازی شده است.
63
+ *
64
+ * ✔ پشتیبانی از فونت وزیر
65
+ * ✔ پشتیبانی از RTL
66
+ * ✔ امکان ترکیب چند سری میله‌ای یا خطی
67
+ * ✔ مقیاس‌دهی خودکار محور Y
68
+ * ✔ تشخیص خودکار بین `linear` و `logarithmic`
69
+ * (اگر اختلاف min/max بیش از ۵۰ برابر باشد، محور Y به حالت لگاریتمی تغییر می‌کند)
70
+ *
71
+ * 🔹 تعامل Legend:
72
+ * کلیک روی هر سری در Legend آن را مخفی/ظاهر می‌کند و محور Y با توجه به مقدار سری‌های
73
+ * قابل‌مشاهده مجدداً محاسبه می‌شود.
74
+ *
75
+ *
76
+ * @returns {JSX.Element}
77
+ * یک نمودار میله‌ای یا ترکیبی با قابلیت شخصی‌سازی کامل.
78
+ *
79
+ *
80
+ * @example
81
+ * ```jsx
82
+ * <BarChart
83
+ * labels={["شنبه", "یکشنبه", "دوشنبه"]}
84
+ * datasets={[
85
+ * {
86
+ * label: "فروش",
87
+ * data: [10, 20, 15],
88
+ * backgroundColor: "rgba(75,192,192,0.7)",
89
+ * },
90
+ * {
91
+ * label: "میانگین",
92
+ * data: [12, 18, 14],
93
+ * type: "line",
94
+ * borderColor: "red",
95
+ * backgroundColor: "transparent",
96
+ * borderWidth: 3,
97
+ * tension: 0.4,
98
+ * pointRadius: 4,
99
+ * fill: false,
100
+ * order: 0
101
+ * }
102
+ * ]}
103
+ * height={400}
104
+ * />
105
+ * ```
106
+ */
20
107
  declare function BarChart({ labels, datasets, height }: Props$1): React.JSX.Element;
21
108
 
22
109
  interface Props {
@@ -17,6 +17,93 @@ interface Props$1 {
17
17
  datasets: Dataset[];
18
18
  height?: number;
19
19
  }
20
+ /**
21
+ * 📊 BarChart — کامپوننت نمودار میله‌ای (Bar / Combo Bar+Line)
22
+ *
23
+ * @component BarChart
24
+ *
25
+ * @param {string[]} labels
26
+ * آرایه‌ای از برچسب‌های محور افقی (X). طول این آرایه مبنای تمام داده‌هاست.
27
+ *
28
+ * @param {Array<{
29
+ * label: string,
30
+ * data: (number | null)[],
31
+ * backgroundColor: string,
32
+ * borderColor?: string,
33
+ * borderWidth?: number,
34
+ * type?: "line",
35
+ * order?: number,
36
+ * tension?: number,
37
+ * pointRadius?: number,
38
+ * fill?: boolean
39
+ * }>} datasets
40
+ *
41
+ * آرایه‌ای از سری‌های داده برای نمایش در نمودار.
42
+ * هر آبجکت یک سری داده است که می‌تواند میله‌ای (Bar) یا خطی (Line) باشد:
43
+ *
44
+ * - ● **label**: عنوان سری (نمایش در Legend)
45
+ * - ● **data**: مقادیر هر نقطه – مقدار `null` باعث حذف نقطه از نمودار می‌شود.
46
+ * - ● **backgroundColor**: رنگ میله یا رنگ پرشدگی خط
47
+ * - ● **borderColor**: (اختیاری) رنگ خط دور میله یا خط
48
+ * - ● **borderWidth**: (اختیاری) ضخامت خط دور میله یا خط
49
+ * - ● **type**: اگر `"line"` باشد، سری به صورت نمودار خطی نمایش داده می‌شود (Combo chart)
50
+ * - ● **order**: ترتیب رسم (سری با order بزرگ‌تر روی سایر سری‌ها قرار می‌گیرد)
51
+ * - ● **tension**: (خطی) میزان خمیدگی منحنی (۰ = خط صاف)
52
+ * - ● **pointRadius**: (خطی) شعاع نقاط
53
+ * - ● **fill**: (خطی) پر شدن زیر نمودار خطی
54
+ *
55
+ *
56
+ * @param {number} [height=600]
57
+ * ارتفاع نمودار بر حسب پیکسل.
58
+ *
59
+ *
60
+ * @description
61
+ * این کامپوننت یک نمودار میله‌ای (BarChart) با پشتیبانی از **نمودار ترکیبی Bar + Line**
62
+ * است و برای نمایش داده‌ها در محیط فارسی و راست‌چین بهینه‌سازی شده است.
63
+ *
64
+ * ✔ پشتیبانی از فونت وزیر
65
+ * ✔ پشتیبانی از RTL
66
+ * ✔ امکان ترکیب چند سری میله‌ای یا خطی
67
+ * ✔ مقیاس‌دهی خودکار محور Y
68
+ * ✔ تشخیص خودکار بین `linear` و `logarithmic`
69
+ * (اگر اختلاف min/max بیش از ۵۰ برابر باشد، محور Y به حالت لگاریتمی تغییر می‌کند)
70
+ *
71
+ * 🔹 تعامل Legend:
72
+ * کلیک روی هر سری در Legend آن را مخفی/ظاهر می‌کند و محور Y با توجه به مقدار سری‌های
73
+ * قابل‌مشاهده مجدداً محاسبه می‌شود.
74
+ *
75
+ *
76
+ * @returns {JSX.Element}
77
+ * یک نمودار میله‌ای یا ترکیبی با قابلیت شخصی‌سازی کامل.
78
+ *
79
+ *
80
+ * @example
81
+ * ```jsx
82
+ * <BarChart
83
+ * labels={["شنبه", "یکشنبه", "دوشنبه"]}
84
+ * datasets={[
85
+ * {
86
+ * label: "فروش",
87
+ * data: [10, 20, 15],
88
+ * backgroundColor: "rgba(75,192,192,0.7)",
89
+ * },
90
+ * {
91
+ * label: "میانگین",
92
+ * data: [12, 18, 14],
93
+ * type: "line",
94
+ * borderColor: "red",
95
+ * backgroundColor: "transparent",
96
+ * borderWidth: 3,
97
+ * tension: 0.4,
98
+ * pointRadius: 4,
99
+ * fill: false,
100
+ * order: 0
101
+ * }
102
+ * ]}
103
+ * height={400}
104
+ * />
105
+ * ```
106
+ */
20
107
  declare function BarChart({ labels, datasets, height }: Props$1): React.JSX.Element;
21
108
 
22
109
  interface Props {
@@ -186,7 +186,6 @@ function PieChart({
186
186
  const chart = chartRef.current;
187
187
  const meta = chart.getDatasetMeta(0);
188
188
  const data = chart.data.datasets[0].data;
189
- const chartArea = chart.chartArea;
190
189
  const visibleTotal = data.reduce((sum, val, index) => {
191
190
  if (!meta.data[index] || meta.data[index].hidden !== true) {
192
191
  return sum + val;
@@ -194,14 +193,23 @@ function PieChart({
194
193
  return sum;
195
194
  }, 0);
196
195
  const newLabels = [];
196
+ const canvas = chart.canvas;
197
+ const canvasRect = canvas.getBoundingClientRect();
198
+ const containerRect = containerRef.current.getBoundingClientRect();
199
+ const scaleX = chart.width / canvasRect.width;
200
+ const scaleY = chart.height / canvasRect.height;
197
201
  meta.data.forEach((arc, index) => {
198
202
  if (arc.hidden) return;
199
203
  const value = data[index];
200
204
  if (value === 0) return;
201
205
  const centerAngle = (arc.startAngle + arc.endAngle) / 2;
202
206
  const midRadius = arc.innerRadius + (arc.outerRadius - arc.innerRadius) * 0.65;
203
- const x = arc.x - Math.cos(centerAngle) * midRadius;
204
- const y = arc.y + Math.sin(centerAngle) * midRadius;
207
+ const xInternal = arc.x - Math.cos(centerAngle) * midRadius;
208
+ const yInternal = arc.y + Math.sin(centerAngle) * midRadius;
209
+ const xDom = canvasRect.left + xInternal / scaleX;
210
+ const yDom = canvasRect.top + yInternal / scaleY;
211
+ const leftRelative = xDom - containerRect.left;
212
+ const topRelative = yDom - containerRect.top;
205
213
  let text;
206
214
  if (showPercentage) {
207
215
  const percentage = (value / visibleTotal * 100).toFixed(1);
@@ -209,7 +217,7 @@ function PieChart({
209
217
  } else {
210
218
  text = String(value);
211
219
  }
212
- newLabels.push({ x, y, text, opacity: 1 });
220
+ newLabels.push({ left: leftRelative, top: topRelative, text, opacity: 1 });
213
221
  });
214
222
  setDataLabels(newLabels);
215
223
  };
@@ -223,6 +231,27 @@ function PieChart({
223
231
  }, 500);
224
232
  return () => clearTimeout(timeout);
225
233
  }, [datasets, showDataLabels, showPercentage]);
234
+ (0, import_react2.useEffect)(() => {
235
+ const chart = chartRef.current;
236
+ if (!chart) return;
237
+ const prevOnComplete = chart.options.animation?.onComplete;
238
+ chart.options.animation = {
239
+ ...chart.options.animation,
240
+ onComplete: () => {
241
+ try {
242
+ prevOnComplete && prevOnComplete();
243
+ } catch (e) {
244
+ }
245
+ calculateLabels();
246
+ }
247
+ };
248
+ chart.update();
249
+ return () => {
250
+ if (chart && chart.options && chart.options.animation) {
251
+ chart.options.animation.onComplete = prevOnComplete;
252
+ }
253
+ };
254
+ }, [showDataLabels, showPercentage, datasets]);
226
255
  (0, import_react2.useEffect)(() => {
227
256
  if (!chartRef.current || !showDataLabels) return;
228
257
  const chart = chartRef.current;
@@ -246,6 +275,7 @@ function PieChart({
246
275
  animateRotate: true,
247
276
  animateScale: true,
248
277
  duration: 400
278
+ // onComplete تنظیم می‌شود در useEffect بالا تا فقط رفتار محاسبه لیبل را تحت تاثیر قرار دهیم
249
279
  },
250
280
  plugins: {
251
281
  tooltip: {
@@ -341,8 +371,8 @@ function PieChart({
341
371
  key: index,
342
372
  sx: {
343
373
  position: "absolute",
344
- left: label.x / (window.devicePixelRatio || 1),
345
- top: label.y / (window.devicePixelRatio || 1),
374
+ left: label.left,
375
+ top: label.top,
346
376
  transform: "translate(-50%, -50%)",
347
377
  color: "#fff",
348
378
  fontWeight: "bold",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/charts/index.ts","../../react-shim.js","../../src/charts/bar/index.tsx","../../src/charts/pie/index.tsx"],"sourcesContent":["export { default as BarChart } from \"./bar\";\nexport { default as PieChart } from \"./pie\";\n","import * as React from \"react\";\nexport { React };\n","\"use client\";\nimport { useRef, useState } from \"react\";\nimport { Chart } from \"react-chartjs-2\";\nimport {\n Chart as ChartJS,\n CategoryScale,\n LinearScale,\n LogarithmicScale,\n BarElement,\n LineElement,\n PointElement,\n Tooltip,\n Legend,\n BarController,\n LineController,\n Chart as ChartType,\n} from \"chart.js\";\nimport { Box } from \"@mui/material\";\n\nChartJS.register(\n CategoryScale,\n LinearScale,\n LogarithmicScale,\n BarElement,\n LineElement,\n PointElement,\n Tooltip,\n Legend,\n BarController,\n LineController\n);\n\ninterface Dataset {\n label: string;\n data: (number | null)[];\n backgroundColor: string;\n borderColor?: string;\n borderWidth?: number;\n type?: \"line\";\n order?: number;\n tension?: number;\n pointRadius?: number;\n fill?: boolean;\n}\n\ninterface Props {\n labels: string[];\n datasets: Dataset[];\n height?: number;\n}\n\nexport default function BarChart({ labels, datasets, height }: Props) {\n const chartRef = useRef<ChartType | null>(null);\n const [hiddenIndices, setHiddenIndices] = useState<Set<number>>(new Set());\n\n // --- داده‌های visible ---\n const visibleDatasets = datasets.filter((_, i) => !hiddenIndices.has(i));\n const allValues = ([] as number[]).concat(\n ...visibleDatasets.map((ds) =>\n ds.data.filter((v): v is number => v !== null)\n )\n );\n\n const minValue = allValues.length ? Math.min(...allValues) : 0;\n const maxValue = allValues.length ? Math.max(...allValues) : 1;\n\n // --- تصمیم هوشمند برای scale ---\n const useLogScale = maxValue / (minValue || 1) > 50; // اگر اختلاف >50 برابر باشد log scale\n const scaleType: \"linear\" | \"logarithmic\" = useLogScale\n ? \"logarithmic\"\n : \"linear\";\n\n // --- محاسبه محور Y ---\n let yMin = minValue;\n let yMax = maxValue;\n let stepSize: number | undefined = 1;\n\n if (scaleType === \"linear\") {\n const range = yMax - yMin;\n const targetLines = 8;\n let rawStep = range / targetLines;\n\n const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));\n const normalized = rawStep / magnitude;\n if (normalized <= 1) stepSize = 1 * magnitude;\n else if (normalized <= 2) stepSize = 2 * magnitude;\n else if (normalized <= 5) stepSize = 5 * magnitude;\n else stepSize = 10 * magnitude;\n\n yMin = Math.floor(yMin / stepSize) * stepSize;\n yMax = Math.ceil(yMax / stepSize) * stepSize;\n } else {\n yMin = Math.max(minValue, 1);\n yMax = maxValue;\n stepSize = undefined;\n }\n\n // --- تنظیمات Chart.js ---\n const options = {\n responsive: true,\n maintainAspectRatio: false,\n animation: { duration: 500 },\n scales: {\n y: {\n type: scaleType,\n min: yMin,\n max: yMax,\n ticks: {\n ...(stepSize !== undefined ? { stepSize } : {}),\n callback: (value: any) => {\n // محدود کردن تعداد اعشار به حداکثر 2\n const num = Number(value);\n if (scaleType === \"logarithmic\") return num.toLocaleString();\n // اگر عدد خیلی بزرگ است، بدون اعشار\n if (num >= 1000) return num.toLocaleString();\n // اعشار برای اعداد کوچک\n if (stepSize && stepSize < 1) return num.toFixed(2);\n return num;\n },\n font: { family: \"'Vazir', sans-serif\", size: 14 },\n },\n },\n x: {\n ticks: {\n autoSkip: false,\n font: { family: \"'Vazir', sans-serif\", size: 13 },\n },\n },\n },\n plugins: {\n legend: {\n labels: {\n usePointStyle: true, // دایره‌ای\n font: { size: 16, family: \"'Vazir', sans-serif\" },\n },\n onClick: (e: any, legendItem: any, legend: any) => {\n const index = legendItem.datasetIndex as number;\n const newHidden = new Set(hiddenIndices);\n if (hiddenIndices.has(index)) newHidden.delete(index);\n else newHidden.add(index);\n setHiddenIndices(newHidden);\n },\n },\n tooltip: {\n bodyFont: { family: \"'Vazir', sans-serif\", size: 14 },\n titleFont: { family: \"'Vazir', sans-serif\", size: 16 },\n },\n datalabels: { display: false },\n },\n };\n\n // --- تنظیمات نقاط ---\n ChartJS.defaults.elements.point.radius = 5;\n ChartJS.defaults.elements.point.hoverRadius = 9;\n ChartJS.defaults.elements.point.borderWidth = 0.2;\n ChartJS.defaults.elements.point.backgroundColor = \"red\";\n ChartJS.defaults.elements.point.borderColor = \"black\";\n\n return (\n <Box height={height ?? 600}>\n <Chart\n ref={chartRef}\n type=\"bar\"\n data={{\n labels,\n datasets: datasets.map((ds, i) => ({\n ...ds,\n hidden: hiddenIndices.has(i),\n })),\n }}\n options={options}\n />\n </Box>\n );\n}\n","'use client'\nimport { Pie } from \"react-chartjs-2\";\nimport { Chart as ChartJS, ArcElement, Tooltip, Legend, Chart } from \"chart.js\";\nimport { useMemo, useRef, useEffect, useState } from \"react\";\nimport { Box, Typography } from \"@mui/material\";\nimport Image from \"next/image\";\nimport ChartDataLabels from \"chartjs-plugin-datalabels\";\n\nChartJS.register(ArcElement, Tooltip, Legend, ChartDataLabels);\n\n// تنظیم فونت پیش‌فرض Chart.js به Vazir\nChartJS.defaults.font.family = \"Vazir, sans-serif\";\n\ninterface Props {\n labels: string[];\n datasets: {\n label: string;\n data: number[];\n backgroundColor: string | string[];\n borderWidth?: number;\n }[];\n height?: number;\n disableLogo?: boolean;\n logoSRC?: string;\n showDataLabels?: boolean;\n showPercentage?: boolean;\n}\n/**\n * 📊 PieChart — کامپوننت نمودار دایره‌ای (Pie)\n *\n * @component PieChart\n *\n * @param {string[]} labels - آرایه‌ای از برچسب‌ها برای هر بخش نمودار.\n * @param {boolean} [showDataLabels] - نمایش یا عدم نمایش برچسب‌های داده‌ها\n * @param {boolean} [showPercentage] - نمایش درصد به جای مقدار عددی در برچسب‌های داده‌ها (در صورت فعال بودن showDataLabels). درصد بر اساس داده‌های قابل مشاهده محاسبه می‌شود.\n * @param {Array<{\n * label: string,\n * data: number[],\n * backgroundColor: string[],\n * borderWidth?: number\n * }>} datasets - آرایه‌ای شامل یک آبجکت داده برای مقداردهی بخش‌های نمودار.\n * - label: عنوان داده‌ها (نمایش در legend)\n * - data: آرایه‌ای از مقادیر هر بخش\n * - backgroundColor: آرایه‌ای از رنگ‌ها برای هر بخش\n * - borderWidth: (اختیاری) ضخامت خط دور هر بخش\n * @param {number} [height] - ارتفاع نمودار (پیش‌فرض: 600 پیکسل)\n *\n * @description\n * این کامپوننت یک نمودار دایره‌ای با قابلیت شخصی‌سازی رنگ، داده و فونت (هماهنگ با وزیر) است.\n * - ریسپانسیو و مناسب صفحات فارسی\n * - امکان نمایش لوگو یا کامپوننت دلخواه در مرکز نمودار\n * - امکان نمایش درصد یا مقدار عددی در برچسب‌های داده‌ها بر اساس داده‌های قابل مشاهده\n *\n * @returns {JSX.Element} یک نمودار دایره‌ای با داده‌های ورودی\n *\n * @example\n * ```jsx\n * <PieChart\n * labels={[\"بخش اول\", \"بخش دوم\", \"بخش سوم\"]}\n * datasets={[\n * {\n * label: \"مقدار\",\n * data: [10, 20, 30],\n * backgroundColor: [\n * \"rgba(75,192,192,1)\",\n * \"rgba(255,99,132,1)\",\n * \"rgba(153,102,255,1)\",\n * ],\n * borderWidth: 2,\n * },\n * ]}\n * showDataLabels={true}\n * showPercentage={true}\n * />\n * ```\n */\nexport default function PieChart({\n labels,\n datasets,\n height,\n disableLogo,\n logoSRC,\n showDataLabels = false,\n showPercentage = false,\n}: Props) {\n const chartRef = useRef<ChartJS<\"pie\">>(null);\n const [dataLabels, setDataLabels] = useState<{ x: number; y: number; text: string; opacity: number }[]>([]);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // تابع محاسبه موقعیت لیبل‌ها\n const calculateLabels = () => {\n if (!showDataLabels || !chartRef.current || !containerRef.current) return;\n\n const chart = chartRef.current;\n const meta = chart.getDatasetMeta(0);\n const data = chart.data.datasets[0].data as number[];\n\n // گرفتن اطلاعات chart area\n const chartArea = chart.chartArea;\n\n // محاسبه مجموع داده‌های قابل مشاهده\n const visibleTotal = data.reduce((sum, val, index) => {\n if (!meta.data[index] || (meta.data[index] as any).hidden !== true) {\n return sum + val;\n }\n return sum;\n }, 0);\n\n const newLabels: { x: number; y: number; text: string; opacity: number }[] = [];\n\n meta.data.forEach((arc: any, index: number) => {\n if (arc.hidden) return;\n\n const value = data[index];\n if (value === 0) return;\n\n // محاسبه مرکز arc\n const centerAngle = (arc.startAngle + arc.endAngle) / 2;\n // نزدیک‌تر به دیواره (0.7 = بین مرکز و لبه، هرچه بیشتر به 1 نزدیک‌تر = نزدیک‌تر به لبه)\n const midRadius = arc.innerRadius + (arc.outerRadius - arc.innerRadius) * 0.65;\n\n // موقعیت در chart area - آینه کردن روی محور X\n const x = arc.x - Math.cos(centerAngle) * midRadius;\n const y = arc.y + Math.sin(centerAngle) * midRadius;\n\n let text: string;\n if (showPercentage) {\n const percentage = ((value / visibleTotal) * 100).toFixed(1);\n text = percentage + \"%\";\n } else {\n text = String(value);\n }\n\n newLabels.push({ x, y, text, opacity: 1 });\n });\n\n setDataLabels(newLabels);\n };\n\n // محاسبه موقعیت لیبل‌ها بعد از اتمام انیمیشن\n useEffect(() => {\n if (!showDataLabels) {\n setDataLabels([]);\n return;\n }\n\n // صبر برای اتمام انیمیشن اولیه (500ms)\n const timeout = setTimeout(() => {\n calculateLabels();\n }, 500);\n\n return () => clearTimeout(timeout);\n }, [datasets, showDataLabels, showPercentage]);\n\n // آپدیت لیبل‌ها بعد از هر تغییر در chart (مثل کلیک روی legend)\n useEffect(() => {\n if (!chartRef.current || !showDataLabels) return;\n\n const chart = chartRef.current;\n const originalUpdate = chart.update.bind(chart);\n\n chart.update = function (...args: any[]) {\n // مخفی کردن لیبل‌ها قبل از آپدیت\n setDataLabels(prev => prev.map(l => ({ ...l, opacity: 0 })));\n\n originalUpdate(...args);\n\n // محاسبه مجدد لیبل‌ها بعد از انیمیشن\n setTimeout(() => {\n calculateLabels();\n }, 250);\n };\n\n return () => {\n chart.update = originalUpdate;\n };\n }, [showDataLabels, showPercentage]);\n\n const options = useMemo(() => ({\n responsive: true,\n maintainAspectRatio: false,\n cutout: !disableLogo ? \"59%\" : \"0%\",\n animation: {\n animateRotate: true,\n animateScale: true,\n duration: 400,\n },\n plugins: {\n tooltip: {\n bodyFont: {\n family: \"Vazir, sans-serif\",\n size: 14,\n },\n titleFont: {\n family: \"Vazir, sans-serif\",\n size: 16,\n },\n },\n legend: {\n labels: {\n padding: 15,\n usePointStyle: true,\n color: '#666', // رنگ متن legend را نرم‌تر می‌کند\n font: {\n size: 16,\n family: \"Vazir, sans-serif\",\n },\n boxWidth: 40,\n paddingBottom: 10,\n generateLabels: (chart: any) => {\n const data = chart.data;\n const meta = chart.getDatasetMeta(0);\n return data.labels.map((label: string, index: number) => {\n const hidden = meta.data[index] ? meta.data[index].hidden : false;\n return {\n text: label,\n fillStyle: data.datasets[0].backgroundColor[index] || '#000',\n hidden: hidden,\n index: index,\n datasetIndex: 0,\n textDecoration: hidden ? 'line-through' : undefined,\n };\n });\n },\n },\n onClick: (e: any, legendItem: any, legend: any) => {\n const ci = legend.chart;\n const meta = ci.getDatasetMeta(legendItem.datasetIndex || 0);\n const index = legendItem.index;\n if (meta.data[index]) {\n meta.data[index].hidden = !meta.data[index].hidden;\n }\n ci.update();\n },\n },\n datalabels: {\n display: false, // غیرفعال - لیبل‌ها با React رندر می‌شوند\n },\n },\n }), [disableLogo]);\n\n // کامپوننتی که می‌خواهید در مرکز نمودار نمایش داده شود\n const CenterComponent = () => {\n return (\n <div\n style={{\n padding: \"10px\",\n borderRadius: \"8px\",\n textAlign: \"center\",\n width: 220,\n }}\n >\n <Image\n alt=\"\"\n width={220}\n height={220}\n src={logoSRC ?? \"/assets/images/pilogo.png\"}\n unoptimized\n />\n </div>\n );\n };\n\n return (\n <Box ref={containerRef} height={height ?? 600} sx={{ position: \"relative\" }}>\n <Pie\n ref={chartRef}\n data={{\n labels: labels,\n datasets: datasets,\n }}\n options={options}\n />\n {/* لیبل‌های سفارشی با فونت Vazir */}\n {showDataLabels && dataLabels.map((label, index) => (\n <Typography\n key={index}\n sx={{\n position: \"absolute\",\n left: label.x / (window.devicePixelRatio || 1),\n top: label.y / (window.devicePixelRatio || 1),\n transform: \"translate(-50%, -50%)\",\n color: \"#fff\",\n fontWeight: \"bold\",\n fontSize: 14,\n fontFamily: \"Vazir, sans-serif\",\n pointerEvents: \"none\",\n textShadow: \"0 1px 2px rgba(0,0,0,0.5)\",\n opacity: label.opacity,\n transition: \"opacity 0.2s ease-in-out, left 0.2s ease-in-out, top 0.2s ease-in-out\",\n }}\n >\n {label.text}\n </Typography>\n ))}\n {!disableLogo && (\n <div\n style={{\n position: \"absolute\",\n top: \"53%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n pointerEvents: \"none\", // جلوگیری از دریافت event روی این لایه\n }}\n >\n <CenterComponent />\n </div>\n )}\n </Box>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,YAAuB;;;ACCvB,mBAAiC;AACjC,6BAAsB;AACtB,mBAaO;AACP,sBAAoB;AAEpB,aAAAA,MAAQ;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAqBe,SAAR,SAA0B,EAAE,QAAQ,UAAU,OAAO,GAAU;AACpE,QAAM,eAAW,qBAAyB,IAAI;AAC9C,QAAM,CAAC,eAAe,gBAAgB,QAAI,uBAAsB,oBAAI,IAAI,CAAC;AAGzE,QAAM,kBAAkB,SAAS,OAAO,CAAC,GAAG,MAAM,CAAC,cAAc,IAAI,CAAC,CAAC;AACvE,QAAM,YAAa,CAAC,EAAe;AAAA,IACjC,GAAG,gBAAgB;AAAA,MAAI,CAAC,OACtB,GAAG,KAAK,OAAO,CAAC,MAAmB,MAAM,IAAI;AAAA,IAC/C;AAAA,EACF;AAEA,QAAM,WAAW,UAAU,SAAS,KAAK,IAAI,GAAG,SAAS,IAAI;AAC7D,QAAM,WAAW,UAAU,SAAS,KAAK,IAAI,GAAG,SAAS,IAAI;AAG7D,QAAM,cAAc,YAAY,YAAY,KAAK;AACjD,QAAM,YAAsC,cACxC,gBACA;AAGJ,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,WAA+B;AAEnC,MAAI,cAAc,UAAU;AAC1B,UAAM,QAAQ,OAAO;AACrB,UAAM,cAAc;AACpB,QAAI,UAAU,QAAQ;AAEtB,UAAM,YAAY,KAAK,IAAI,IAAI,KAAK,MAAM,KAAK,MAAM,OAAO,CAAC,CAAC;AAC9D,UAAM,aAAa,UAAU;AAC7B,QAAI,cAAc,EAAG,YAAW,IAAI;AAAA,aAC3B,cAAc,EAAG,YAAW,IAAI;AAAA,aAChC,cAAc,EAAG,YAAW,IAAI;AAAA,QACpC,YAAW,KAAK;AAErB,WAAO,KAAK,MAAM,OAAO,QAAQ,IAAI;AACrC,WAAO,KAAK,KAAK,OAAO,QAAQ,IAAI;AAAA,EACtC,OAAO;AACL,WAAO,KAAK,IAAI,UAAU,CAAC;AAC3B,WAAO;AACP,eAAW;AAAA,EACb;AAGA,QAAM,UAAU;AAAA,IACd,YAAY;AAAA,IACZ,qBAAqB;AAAA,IACrB,WAAW,EAAE,UAAU,IAAI;AAAA,IAC3B,QAAQ;AAAA,MACN,GAAG;AAAA,QACD,MAAM;AAAA,QACN,KAAK;AAAA,QACL,KAAK;AAAA,QACL,OAAO;AAAA,UACL,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,UAC7C,UAAU,CAAC,UAAe;AAExB,kBAAM,MAAM,OAAO,KAAK;AACxB,gBAAI,cAAc,cAAe,QAAO,IAAI,eAAe;AAE3D,gBAAI,OAAO,IAAM,QAAO,IAAI,eAAe;AAE3C,gBAAI,YAAY,WAAW,EAAG,QAAO,IAAI,QAAQ,CAAC;AAClD,mBAAO;AAAA,UACT;AAAA,UACA,MAAM,EAAE,QAAQ,uBAAuB,MAAM,GAAG;AAAA,QAClD;AAAA,MACF;AAAA,MACA,GAAG;AAAA,QACD,OAAO;AAAA,UACL,UAAU;AAAA,UACV,MAAM,EAAE,QAAQ,uBAAuB,MAAM,GAAG;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,QAAQ;AAAA,QACN,QAAQ;AAAA,UACN,eAAe;AAAA;AAAA,UACf,MAAM,EAAE,MAAM,IAAI,QAAQ,sBAAsB;AAAA,QAClD;AAAA,QACA,SAAS,CAAC,GAAQ,YAAiB,WAAgB;AACjD,gBAAM,QAAQ,WAAW;AACzB,gBAAM,YAAY,IAAI,IAAI,aAAa;AACvC,cAAI,cAAc,IAAI,KAAK,EAAG,WAAU,OAAO,KAAK;AAAA,cAC/C,WAAU,IAAI,KAAK;AACxB,2BAAiB,SAAS;AAAA,QAC5B;AAAA,MACF;AAAA,MACA,SAAS;AAAA,QACP,UAAU,EAAE,QAAQ,uBAAuB,MAAM,GAAG;AAAA,QACpD,WAAW,EAAE,QAAQ,uBAAuB,MAAM,GAAG;AAAA,MACvD;AAAA,MACA,YAAY,EAAE,SAAS,MAAM;AAAA,IAC/B;AAAA,EACF;AAGA,eAAAA,MAAQ,SAAS,SAAS,MAAM,SAAS;AACzC,eAAAA,MAAQ,SAAS,SAAS,MAAM,cAAc;AAC9C,eAAAA,MAAQ,SAAS,SAAS,MAAM,cAAc;AAC9C,eAAAA,MAAQ,SAAS,SAAS,MAAM,kBAAkB;AAClD,eAAAA,MAAQ,SAAS,SAAS,MAAM,cAAc;AAE9C,SACE,oCAAC,uBAAI,QAAQ,UAAU,OACrB;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,MAAK;AAAA,MACL,MAAM;AAAA,QACJ;AAAA,QACA,UAAU,SAAS,IAAI,CAAC,IAAI,OAAO;AAAA,UACjC,GAAG;AAAA,UACH,QAAQ,cAAc,IAAI,CAAC;AAAA,QAC7B,EAAE;AAAA,MACJ;AAAA,MACA;AAAA;AAAA,EACF,CACF;AAEJ;;;AC7KA,IAAAC,0BAAoB;AACpB,IAAAC,gBAAqE;AACrE,IAAAC,gBAAqD;AACrD,IAAAC,mBAAgC;AAChC,mBAAkB;AAClB,uCAA4B;AAE5B,cAAAC,MAAQ,SAAS,0BAAY,uBAAS,sBAAQ,iCAAAC,OAAe;AAG7D,cAAAD,MAAQ,SAAS,KAAK,SAAS;AAiEhB,SAAR,SAA0B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,iBAAiB;AACnB,GAAU;AACR,QAAM,eAAW,sBAAuB,IAAI;AAC5C,QAAM,CAAC,YAAY,aAAa,QAAI,wBAAoE,CAAC,CAAC;AAC1G,QAAM,mBAAe,sBAAuB,IAAI;AAGhD,QAAM,kBAAkB,MAAM;AAC5B,QAAI,CAAC,kBAAkB,CAAC,SAAS,WAAW,CAAC,aAAa,QAAS;AAEnE,UAAM,QAAQ,SAAS;AACvB,UAAM,OAAO,MAAM,eAAe,CAAC;AACnC,UAAM,OAAO,MAAM,KAAK,SAAS,CAAC,EAAE;AAGpC,UAAM,YAAY,MAAM;AAGxB,UAAM,eAAe,KAAK,OAAO,CAAC,KAAK,KAAK,UAAU;AACpD,UAAI,CAAC,KAAK,KAAK,KAAK,KAAM,KAAK,KAAK,KAAK,EAAU,WAAW,MAAM;AAClE,eAAO,MAAM;AAAA,MACf;AACA,aAAO;AAAA,IACT,GAAG,CAAC;AAEJ,UAAM,YAAuE,CAAC;AAE9E,SAAK,KAAK,QAAQ,CAAC,KAAU,UAAkB;AAC7C,UAAI,IAAI,OAAQ;AAEhB,YAAM,QAAQ,KAAK,KAAK;AACxB,UAAI,UAAU,EAAG;AAGjB,YAAM,eAAe,IAAI,aAAa,IAAI,YAAY;AAEtD,YAAM,YAAY,IAAI,eAAe,IAAI,cAAc,IAAI,eAAe;AAG1E,YAAM,IAAI,IAAI,IAAI,KAAK,IAAI,WAAW,IAAI;AAC1C,YAAM,IAAI,IAAI,IAAI,KAAK,IAAI,WAAW,IAAI;AAE1C,UAAI;AACJ,UAAI,gBAAgB;AAClB,cAAM,cAAe,QAAQ,eAAgB,KAAK,QAAQ,CAAC;AAC3D,eAAO,aAAa;AAAA,MACtB,OAAO;AACL,eAAO,OAAO,KAAK;AAAA,MACrB;AAEA,gBAAU,KAAK,EAAE,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;AAAA,IAC3C,CAAC;AAED,kBAAc,SAAS;AAAA,EACzB;AAGA,+BAAU,MAAM;AACd,QAAI,CAAC,gBAAgB;AACnB,oBAAc,CAAC,CAAC;AAChB;AAAA,IACF;AAGA,UAAM,UAAU,WAAW,MAAM;AAC/B,sBAAgB;AAAA,IAClB,GAAG,GAAG;AAEN,WAAO,MAAM,aAAa,OAAO;AAAA,EACnC,GAAG,CAAC,UAAU,gBAAgB,cAAc,CAAC;AAG7C,+BAAU,MAAM;AACd,QAAI,CAAC,SAAS,WAAW,CAAC,eAAgB;AAE1C,UAAM,QAAQ,SAAS;AACvB,UAAM,iBAAiB,MAAM,OAAO,KAAK,KAAK;AAE9C,UAAM,SAAS,YAAa,MAAa;AAEvC,oBAAc,UAAQ,KAAK,IAAI,QAAM,EAAE,GAAG,GAAG,SAAS,EAAE,EAAE,CAAC;AAE3D,qBAAe,GAAG,IAAI;AAGtB,iBAAW,MAAM;AACf,wBAAgB;AAAA,MAClB,GAAG,GAAG;AAAA,IACR;AAEA,WAAO,MAAM;AACX,YAAM,SAAS;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,gBAAgB,cAAc,CAAC;AAEnC,QAAM,cAAU,uBAAQ,OAAO;AAAA,IAC7B,YAAY;AAAA,IACZ,qBAAqB;AAAA,IACrB,QAAQ,CAAC,cAAc,QAAQ;AAAA,IAC/B,WAAW;AAAA,MACT,eAAe;AAAA,MACf,cAAc;AAAA,MACd,UAAU;AAAA,IACZ;AAAA,IACA,SAAS;AAAA,MACP,SAAS;AAAA,QACP,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,MAAM;AAAA,QACR;AAAA,QACA,WAAW;AAAA,UACT,QAAQ;AAAA,UACR,MAAM;AAAA,QACR;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,QAAQ;AAAA,UACN,SAAS;AAAA,UACT,eAAe;AAAA,UACf,OAAO;AAAA;AAAA,UACP,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ;AAAA,UACV;AAAA,UACA,UAAU;AAAA,UACV,eAAe;AAAA,UACf,gBAAgB,CAAC,UAAe;AAC9B,kBAAM,OAAO,MAAM;AACnB,kBAAM,OAAO,MAAM,eAAe,CAAC;AACnC,mBAAO,KAAK,OAAO,IAAI,CAAC,OAAe,UAAkB;AACvD,oBAAM,SAAS,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,EAAE,SAAS;AAC5D,qBAAO;AAAA,gBACL,MAAM;AAAA,gBACN,WAAW,KAAK,SAAS,CAAC,EAAE,gBAAgB,KAAK,KAAK;AAAA,gBACtD;AAAA,gBACA;AAAA,gBACA,cAAc;AAAA,gBACd,gBAAgB,SAAS,iBAAiB;AAAA,cAC5C;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,QACA,SAAS,CAAC,GAAQ,YAAiB,WAAgB;AACjD,gBAAM,KAAK,OAAO;AAClB,gBAAM,OAAO,GAAG,eAAe,WAAW,gBAAgB,CAAC;AAC3D,gBAAM,QAAQ,WAAW;AACzB,cAAI,KAAK,KAAK,KAAK,GAAG;AACpB,iBAAK,KAAK,KAAK,EAAE,SAAS,CAAC,KAAK,KAAK,KAAK,EAAE;AAAA,UAC9C;AACA,aAAG,OAAO;AAAA,QACZ;AAAA,MACF;AAAA,MACA,YAAY;AAAA,QACV,SAAS;AAAA;AAAA,MACX;AAAA,IACF;AAAA,EACF,IAAI,CAAC,WAAW,CAAC;AAGjB,QAAM,kBAAkB,MAAM;AAC5B,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,cAAc;AAAA,UACd,WAAW;AAAA,UACX,OAAO;AAAA,QACT;AAAA;AAAA,MAEA;AAAA,QAAC,aAAAE;AAAA,QAAA;AAAA,UACC,KAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,KAAK,WAAW;AAAA,UAChB,aAAW;AAAA;AAAA,MACb;AAAA,IACF;AAAA,EAEJ;AAEA,SACE,oCAAC,wBAAI,KAAK,cAAc,QAAQ,UAAU,KAAK,IAAI,EAAE,UAAU,WAAW,KACxE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA;AAAA,EACF,GAEC,kBAAkB,WAAW,IAAI,CAAC,OAAO,UACxC;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,IAAI;AAAA,QACF,UAAU;AAAA,QACV,MAAM,MAAM,KAAK,OAAO,oBAAoB;AAAA,QAC5C,KAAK,MAAM,KAAK,OAAO,oBAAoB;AAAA,QAC3C,WAAW;AAAA,QACX,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,YAAY;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,YAAY;AAAA,MACd;AAAA;AAAA,IAEC,MAAM;AAAA,EACT,CACD,GACA,CAAC,eACA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,UAAU;AAAA,QACV,KAAK;AAAA,QACL,MAAM;AAAA,QACN,WAAW;AAAA,QACX,eAAe;AAAA;AAAA,MACjB;AAAA;AAAA,IAEA,oCAAC,qBAAgB;AAAA,EACnB,CAEJ;AAEJ;","names":["ChartJS","import_react_chartjs_2","import_chart","import_react","import_material","ChartJS","ChartDataLabels","Image"]}
1
+ {"version":3,"sources":["../../src/charts/index.ts","../../react-shim.js","../../src/charts/bar/index.tsx","../../src/charts/pie/index.tsx"],"sourcesContent":["export { default as BarChart } from \"./bar\";\nexport { default as PieChart } from \"./pie\";\n","import * as React from \"react\";\nexport { React };\n","\"use client\";\nimport { useRef, useState } from \"react\";\nimport { Chart } from \"react-chartjs-2\";\nimport {\n Chart as ChartJS,\n CategoryScale,\n LinearScale,\n LogarithmicScale,\n BarElement,\n LineElement,\n PointElement,\n Tooltip,\n Legend,\n BarController,\n LineController,\n Chart as ChartType,\n} from \"chart.js\";\nimport { Box } from \"@mui/material\";\n\nChartJS.register(\n CategoryScale,\n LinearScale,\n LogarithmicScale,\n BarElement,\n LineElement,\n PointElement,\n Tooltip,\n Legend,\n BarController,\n LineController\n);\n\ninterface Dataset {\n label: string;\n data: (number | null)[];\n backgroundColor: string;\n borderColor?: string;\n borderWidth?: number;\n type?: \"line\";\n order?: number;\n tension?: number;\n pointRadius?: number;\n fill?: boolean;\n}\n\ninterface Props {\n labels: string[];\n datasets: Dataset[];\n height?: number;\n}\n/**\n * 📊 BarChart — کامپوننت نمودار میله‌ای (Bar / Combo Bar+Line)\n *\n * @component BarChart\n *\n * @param {string[]} labels\n * آرایه‌ای از برچسب‌های محور افقی (X). طول این آرایه مبنای تمام داده‌هاست.\n *\n * @param {Array<{\n * label: string,\n * data: (number | null)[],\n * backgroundColor: string,\n * borderColor?: string,\n * borderWidth?: number,\n * type?: \"line\",\n * order?: number,\n * tension?: number,\n * pointRadius?: number,\n * fill?: boolean\n * }>} datasets\n *\n * آرایه‌ای از سری‌های داده برای نمایش در نمودار.\n * هر آبجکت یک سری داده است که می‌تواند میله‌ای (Bar) یا خطی (Line) باشد:\n *\n * - ● **label**: عنوان سری (نمایش در Legend)\n * - ● **data**: مقادیر هر نقطه – مقدار `null` باعث حذف نقطه از نمودار می‌شود.\n * - ● **backgroundColor**: رنگ میله یا رنگ پرشدگی خط\n * - ● **borderColor**: (اختیاری) رنگ خط دور میله یا خط\n * - ● **borderWidth**: (اختیاری) ضخامت خط دور میله یا خط\n * - ● **type**: اگر `\"line\"` باشد، سری به صورت نمودار خطی نمایش داده می‌شود (Combo chart)\n * - ● **order**: ترتیب رسم (سری با order بزرگ‌تر روی سایر سری‌ها قرار می‌گیرد)\n * - ● **tension**: (خطی) میزان خمیدگی منحنی (۰ = خط صاف)\n * - ● **pointRadius**: (خطی) شعاع نقاط\n * - ● **fill**: (خطی) پر شدن زیر نمودار خطی\n *\n *\n * @param {number} [height=600]\n * ارتفاع نمودار بر حسب پیکسل.\n *\n *\n * @description\n * این کامپوننت یک نمودار میله‌ای (BarChart) با پشتیبانی از **نمودار ترکیبی Bar + Line**\n * است و برای نمایش داده‌ها در محیط فارسی و راست‌چین بهینه‌سازی شده است.\n *\n * ✔ پشتیبانی از فونت وزیر \n * ✔ پشتیبانی از RTL \n * ✔ امکان ترکیب چند سری میله‌ای یا خطی \n * ✔ مقیاس‌دهی خودکار محور Y \n * ✔ تشخیص خودکار بین `linear` و `logarithmic` \n * (اگر اختلاف min/max بیش از ۵۰ برابر باشد، محور Y به حالت لگاریتمی تغییر می‌کند)\n *\n * 🔹 تعامل Legend:\n * کلیک روی هر سری در Legend آن را مخفی/ظاهر می‌کند و محور Y با توجه به مقدار سری‌های\n * قابل‌مشاهده مجدداً محاسبه می‌شود.\n *\n *\n * @returns {JSX.Element}\n * یک نمودار میله‌ای یا ترکیبی با قابلیت شخصی‌سازی کامل.\n *\n *\n * @example\n * ```jsx\n * <BarChart\n * labels={[\"شنبه\", \"یکشنبه\", \"دوشنبه\"]}\n * datasets={[\n * {\n * label: \"فروش\",\n * data: [10, 20, 15],\n * backgroundColor: \"rgba(75,192,192,0.7)\",\n * },\n * {\n * label: \"میانگین\",\n * data: [12, 18, 14],\n * type: \"line\",\n * borderColor: \"red\",\n * backgroundColor: \"transparent\",\n * borderWidth: 3,\n * tension: 0.4,\n * pointRadius: 4,\n * fill: false,\n * order: 0\n * }\n * ]}\n * height={400}\n * />\n * ```\n */\n\nexport default function BarChart({ labels, datasets, height }: Props) {\n const chartRef = useRef<ChartType | null>(null);\n const [hiddenIndices, setHiddenIndices] = useState<Set<number>>(new Set());\n\n // --- داده‌های visible ---\n const visibleDatasets = datasets.filter((_, i) => !hiddenIndices.has(i));\n const allValues = ([] as number[]).concat(\n ...visibleDatasets.map((ds) =>\n ds.data.filter((v): v is number => v !== null)\n )\n );\n\n const minValue = allValues.length ? Math.min(...allValues) : 0;\n const maxValue = allValues.length ? Math.max(...allValues) : 1;\n\n // --- تصمیم هوشمند برای scale ---\n const useLogScale = maxValue / (minValue || 1) > 50; // اگر اختلاف >50 برابر باشد log scale\n const scaleType: \"linear\" | \"logarithmic\" = useLogScale\n ? \"logarithmic\"\n : \"linear\";\n\n // --- محاسبه محور Y ---\n let yMin = minValue;\n let yMax = maxValue;\n let stepSize: number | undefined = 1;\n\n if (scaleType === \"linear\") {\n const range = yMax - yMin;\n const targetLines = 8;\n let rawStep = range / targetLines;\n\n const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));\n const normalized = rawStep / magnitude;\n if (normalized <= 1) stepSize = 1 * magnitude;\n else if (normalized <= 2) stepSize = 2 * magnitude;\n else if (normalized <= 5) stepSize = 5 * magnitude;\n else stepSize = 10 * magnitude;\n\n yMin = Math.floor(yMin / stepSize) * stepSize;\n yMax = Math.ceil(yMax / stepSize) * stepSize;\n } else {\n yMin = Math.max(minValue, 1);\n yMax = maxValue;\n stepSize = undefined;\n }\n\n // --- تنظیمات Chart.js ---\n const options = {\n responsive: true,\n maintainAspectRatio: false,\n animation: { duration: 500 },\n scales: {\n y: {\n type: scaleType,\n min: yMin,\n max: yMax,\n ticks: {\n ...(stepSize !== undefined ? { stepSize } : {}),\n callback: (value: any) => {\n // محدود کردن تعداد اعشار به حداکثر 2\n const num = Number(value);\n if (scaleType === \"logarithmic\") return num.toLocaleString();\n // اگر عدد خیلی بزرگ است، بدون اعشار\n if (num >= 1000) return num.toLocaleString();\n // اعشار برای اعداد کوچک\n if (stepSize && stepSize < 1) return num.toFixed(2);\n return num;\n },\n font: { family: \"'Vazir', sans-serif\", size: 14 },\n },\n },\n x: {\n ticks: {\n autoSkip: false,\n font: { family: \"'Vazir', sans-serif\", size: 13 },\n },\n },\n },\n plugins: {\n legend: {\n labels: {\n usePointStyle: true, // دایره‌ای\n font: { size: 16, family: \"'Vazir', sans-serif\" },\n },\n onClick: (e: any, legendItem: any, legend: any) => {\n const index = legendItem.datasetIndex as number;\n const newHidden = new Set(hiddenIndices);\n if (hiddenIndices.has(index)) newHidden.delete(index);\n else newHidden.add(index);\n setHiddenIndices(newHidden);\n },\n },\n tooltip: {\n bodyFont: { family: \"'Vazir', sans-serif\", size: 14 },\n titleFont: { family: \"'Vazir', sans-serif\", size: 16 },\n },\n datalabels: { display: false },\n },\n };\n\n // --- تنظیمات نقاط ---\n ChartJS.defaults.elements.point.radius = 5;\n ChartJS.defaults.elements.point.hoverRadius = 9;\n ChartJS.defaults.elements.point.borderWidth = 0.2;\n ChartJS.defaults.elements.point.backgroundColor = \"red\";\n ChartJS.defaults.elements.point.borderColor = \"black\";\n\n return (\n <Box height={height ?? 600}>\n <Chart\n ref={chartRef}\n type=\"bar\"\n data={{\n labels,\n datasets: datasets.map((ds, i) => ({\n ...ds,\n hidden: hiddenIndices.has(i),\n })),\n }}\n options={options}\n />\n </Box>\n );\n}\n","'use client'\nimport { Pie } from \"react-chartjs-2\";\nimport { Chart as ChartJS, ArcElement, Tooltip, Legend, Chart } from \"chart.js\";\nimport { useMemo, useRef, useEffect, useState } from \"react\";\nimport { Box, Typography } from \"@mui/material\";\nimport Image from \"next/image\";\nimport ChartDataLabels from \"chartjs-plugin-datalabels\";\n\nChartJS.register(ArcElement, Tooltip, Legend, ChartDataLabels);\n\n// تنظیم فونت پیش‌فرض Chart.js به Vazir\nChartJS.defaults.font.family = \"Vazir, sans-serif\";\n\ninterface Props {\n labels: string[];\n datasets: {\n label: string;\n data: number[];\n backgroundColor: string | string[];\n borderWidth?: number;\n }[];\n height?: number;\n disableLogo?: boolean;\n logoSRC?: string;\n showDataLabels?: boolean;\n showPercentage?: boolean;\n}\n/**\n * 📊 PieChart — کامپوننت نمودار دایره‌ای (Pie)\n *\n * @component PieChart\n *\n * @param {string[]} labels - آرایه‌ای از برچسب‌ها برای هر بخش نمودار.\n * @param {boolean} [showDataLabels] - نمایش یا عدم نمایش برچسب‌های داده‌ها\n * @param {boolean} [showPercentage] - نمایش درصد به جای مقدار عددی در برچسب‌های داده‌ها (در صورت فعال بودن showDataLabels). درصد بر اساس داده‌های قابل مشاهده محاسبه می‌شود.\n * @param {Array<{\n * label: string,\n * data: number[],\n * backgroundColor: string[],\n * borderWidth?: number\n * }>} datasets - آرایه‌ای شامل یک آبجکت داده برای مقداردهی بخش‌های نمودار.\n * - label: عنوان داده‌ها (نمایش در legend)\n * - data: آرایه‌ای از مقادیر هر بخش\n * - backgroundColor: آرایه‌ای از رنگ‌ها برای هر بخش\n * - borderWidth: (اختیاری) ضخامت خط دور هر بخش\n * @param {number} [height] - ارتفاع نمودار (پیش‌فرض: 600 پیکسل)\n *\n * @description\n * این کامپوننت یک نمودار دایره‌ای با قابلیت شخصی‌سازی رنگ، داده و فونت (هماهنگ با وزیر) است.\n * - ریسپانسیو و مناسب صفحات فارسی\n * - امکان نمایش لوگو یا کامپوننت دلخواه در مرکز نمودار\n * - امکان نمایش درصد یا مقدار عددی در برچسب‌های داده‌ها بر اساس داده‌های قابل مشاهده\n *\n * @returns {JSX.Element} یک نمودار دایره‌ای با داده‌های ورودی\n *\n * @example\n * ```jsx\n * <PieChart\n * labels={[\"بخش اول\", \"بخش دوم\", \"بخش سوم\"]}\n * datasets={[\n * {\n * label: \"مقدار\",\n * data: [10, 20, 30],\n * backgroundColor: [\n * \"rgba(75,192,192,1)\",\n * \"rgba(255,99,132,1)\",\n * \"rgba(153,102,255,1)\",\n * ],\n * borderWidth: 2,\n * },\n * ]}\n * showDataLabels={true}\n * showPercentage={true}\n * />\n * ```\n */\nexport default function PieChart({\n labels,\n datasets,\n height,\n disableLogo,\n logoSRC,\n showDataLabels = false,\n showPercentage = false,\n}: Props) {\n const chartRef = useRef<ChartJS<\"pie\">>(null);\n const [dataLabels, setDataLabels] = useState<{ left: number; top: number; text: string; opacity: number }[]>([]);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // تابع محاسبه موقعیت لیبل‌ها\n const calculateLabels = () => {\n if (!showDataLabels || !chartRef.current || !containerRef.current) return;\n\n const chart = chartRef.current;\n const meta = chart.getDatasetMeta(0);\n const data = chart.data.datasets[0].data as number[];\n\n // گرفتن اطلاعات chart area\n // محاسبه مجموع داده‌های قابل مشاهده\n const visibleTotal = data.reduce((sum, val, index) => {\n if (!meta.data[index] || (meta.data[index] as any).hidden !== true) {\n return sum + val;\n }\n return sum;\n }, 0);\n\n const newLabels: { left: number; top: number; text: string; opacity: number }[] = [];\n\n // ابعاد و scale برای تبدیل مختصات داخلی canvas به مختصات DOM\n const canvas = chart.canvas as HTMLCanvasElement;\n const canvasRect = canvas.getBoundingClientRect();\n const containerRect = containerRef.current.getBoundingClientRect();\n\n // chart.width/chart.height => internal canvas pixel size (device pixel scaled)\n // canvasRect.width/canvasRect.height => displayed CSS size\n const scaleX = chart.width / canvasRect.width;\n const scaleY = chart.height / canvasRect.height;\n\n meta.data.forEach((arc: any, index: number) => {\n if (arc.hidden) return;\n\n const value = data[index];\n if (value === 0) return;\n\n // محاسبه مرکز arc در واحد internal canvas pixels\n const centerAngle = (arc.startAngle + arc.endAngle) / 2;\n const midRadius = arc.innerRadius + (arc.outerRadius - arc.innerRadius) * 0.65;\n\n const xInternal = arc.x - Math.cos(centerAngle) * midRadius;\n const yInternal = arc.y + Math.sin(centerAngle) * midRadius;\n\n // تبدیل به مختصات DOM (نسبت به viewport)\n const xDom = canvasRect.left + (xInternal / scaleX);\n const yDom = canvasRect.top + (yInternal / scaleY);\n\n // تبدیل به مختصات نسبی به container (برای absolute positioning داخل container)\n const leftRelative = xDom - containerRect.left;\n const topRelative = yDom - containerRect.top;\n\n let text: string;\n if (showPercentage) {\n const percentage = ((value / visibleTotal) * 100).toFixed(1);\n text = percentage + \"%\";\n } else {\n text = String(value);\n }\n\n newLabels.push({ left: leftRelative, top: topRelative, text, opacity: 1 });\n });\n\n setDataLabels(newLabels);\n };\n\n // محاسبه موقعیت لیبل‌ها بعد از اتمام انیمیشن\n useEffect(() => {\n if (!showDataLabels) {\n setDataLabels([]);\n return;\n }\n\n // صبر برای اتمام انیمیشن اولیه (فقط fallback) — animation.onComplete نیز تنظیم می‌شود.\n const timeout = setTimeout(() => {\n calculateLabels();\n }, 500);\n\n return () => clearTimeout(timeout);\n }, [datasets, showDataLabels, showPercentage]);\n\n // ثبت callback برای onComplete انیمیشن تا دقیقاً بعد از پایان انیمیشن محاسبه انجام شود\n useEffect(() => {\n const chart = chartRef.current;\n if (!chart) return;\n\n // نگهداری مقدار قبلی تا در cleanup به حالت قبل برگردد\n const prevOnComplete = (chart.options.animation as any)?.onComplete;\n\n (chart.options.animation as any) = {\n ...(chart.options.animation as any),\n onComplete: () => {\n // اگر callback قبلی هم بود، آن را اجرا کن\n try { prevOnComplete && prevOnComplete(); } catch (e) { /* ignore */ }\n calculateLabels();\n },\n };\n\n // اعمال تغییرات در chart (بدون trigger کردن انیمیشن)\n chart.update();\n\n return () => {\n // بازیابی onComplete قبلی (در صورت وجود)\n if (chart && chart.options && chart.options.animation) {\n (chart.options.animation as any).onComplete = prevOnComplete;\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [showDataLabels, showPercentage, datasets]);\n\n // آپدیت لیبل‌ها بعد از هر تغییر در chart (مثل کلیک روی legend)\n useEffect(() => {\n if (!chartRef.current || !showDataLabels) return;\n\n const chart = chartRef.current;\n const originalUpdate = chart.update.bind(chart);\n\n chart.update = function (...args: any[]) {\n // مخفی کردن لیبل‌ها قبل از آپدیت\n setDataLabels(prev => prev.map(l => ({ ...l, opacity: 0 })));\n\n originalUpdate(...args);\n\n // محاسبه مجدد لیبل‌ها بعد از انیمیشن\n setTimeout(() => {\n calculateLabels();\n }, 250);\n };\n\n return () => {\n chart.update = originalUpdate;\n };\n }, [showDataLabels, showPercentage]);\n\n const options = useMemo(() => ({\n responsive: true,\n maintainAspectRatio: false,\n cutout: !disableLogo ? \"59%\" : \"0%\",\n animation: {\n animateRotate: true,\n animateScale: true,\n duration: 400,\n // onComplete تنظیم می‌شود در useEffect بالا تا فقط رفتار محاسبه لیبل را تحت تاثیر قرار دهیم\n },\n plugins: {\n tooltip: {\n bodyFont: {\n family: \"Vazir, sans-serif\",\n size: 14,\n },\n titleFont: {\n family: \"Vazir, sans-serif\",\n size: 16,\n },\n },\n legend: {\n labels: {\n padding: 15,\n usePointStyle: true,\n color: '#666', // رنگ متن legend را نرم‌تر می‌کند\n font: {\n size: 16,\n family: \"Vazir, sans-serif\",\n },\n boxWidth: 40,\n paddingBottom: 10,\n generateLabels: (chart: any) => {\n const data = chart.data;\n const meta = chart.getDatasetMeta(0);\n return data.labels.map((label: string, index: number) => {\n const hidden = meta.data[index] ? meta.data[index].hidden : false;\n return {\n text: label,\n fillStyle: data.datasets[0].backgroundColor[index] || '#000',\n hidden: hidden,\n index: index,\n datasetIndex: 0,\n textDecoration: hidden ? 'line-through' : undefined,\n };\n });\n },\n },\n onClick: (e: any, legendItem: any, legend: any) => {\n const ci = legend.chart;\n const meta = ci.getDatasetMeta(legendItem.datasetIndex || 0);\n const index = legendItem.index;\n if (meta.data[index]) {\n meta.data[index].hidden = !meta.data[index].hidden;\n }\n ci.update();\n },\n },\n datalabels: {\n display: false, // غیرفعال - لیبل‌ها با React رندر می‌شوند\n },\n },\n }), [disableLogo]);\n\n // کامپوننتی که می‌خواهید در مرکز نمودار نمایش داده شود\n const CenterComponent = () => {\n return (\n <div\n style={{\n padding: \"10px\",\n borderRadius: \"8px\",\n textAlign: \"center\",\n width: 220,\n }}\n >\n <Image\n alt=\"\"\n width={220}\n height={220}\n src={logoSRC ?? \"/assets/images/pilogo.png\"}\n unoptimized\n />\n </div>\n );\n };\n\n return (\n <Box ref={containerRef} height={height ?? 600} sx={{ position: \"relative\" }}>\n <Pie\n ref={chartRef}\n data={{\n labels: labels,\n datasets: datasets,\n }}\n options={options}\n />\n {/* لیبل‌های سفارشی با فونت Vazir */}\n {showDataLabels && dataLabels.map((label, index) => (\n <Typography\n key={index}\n sx={{\n position: \"absolute\",\n left: label.left,\n top: label.top,\n transform: \"translate(-50%, -50%)\",\n color: \"#fff\",\n fontWeight: \"bold\",\n fontSize: 14,\n fontFamily: \"Vazir, sans-serif\",\n pointerEvents: \"none\",\n textShadow: \"0 1px 2px rgba(0,0,0,0.5)\",\n opacity: label.opacity,\n transition: \"opacity 0.2s ease-in-out, left 0.2s ease-in-out, top 0.2s ease-in-out\",\n }}\n >\n {label.text}\n </Typography>\n ))}\n {!disableLogo && (\n <div\n style={{\n position: \"absolute\",\n top: \"53%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n pointerEvents: \"none\", // جلوگیری از دریافت event روی این لایه\n }}\n >\n <CenterComponent />\n </div>\n )}\n </Box>\n );\n}\n"],"mappings":"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","names":["ChartJS","import_react_chartjs_2","import_chart","import_react","import_material","ChartJS","ChartDataLabels","Image"]}
@@ -161,7 +161,6 @@ function PieChart({
161
161
  const chart = chartRef.current;
162
162
  const meta = chart.getDatasetMeta(0);
163
163
  const data = chart.data.datasets[0].data;
164
- const chartArea = chart.chartArea;
165
164
  const visibleTotal = data.reduce((sum, val, index) => {
166
165
  if (!meta.data[index] || meta.data[index].hidden !== true) {
167
166
  return sum + val;
@@ -169,14 +168,23 @@ function PieChart({
169
168
  return sum;
170
169
  }, 0);
171
170
  const newLabels = [];
171
+ const canvas = chart.canvas;
172
+ const canvasRect = canvas.getBoundingClientRect();
173
+ const containerRect = containerRef.current.getBoundingClientRect();
174
+ const scaleX = chart.width / canvasRect.width;
175
+ const scaleY = chart.height / canvasRect.height;
172
176
  meta.data.forEach((arc, index) => {
173
177
  if (arc.hidden) return;
174
178
  const value = data[index];
175
179
  if (value === 0) return;
176
180
  const centerAngle = (arc.startAngle + arc.endAngle) / 2;
177
181
  const midRadius = arc.innerRadius + (arc.outerRadius - arc.innerRadius) * 0.65;
178
- const x = arc.x - Math.cos(centerAngle) * midRadius;
179
- const y = arc.y + Math.sin(centerAngle) * midRadius;
182
+ const xInternal = arc.x - Math.cos(centerAngle) * midRadius;
183
+ const yInternal = arc.y + Math.sin(centerAngle) * midRadius;
184
+ const xDom = canvasRect.left + xInternal / scaleX;
185
+ const yDom = canvasRect.top + yInternal / scaleY;
186
+ const leftRelative = xDom - containerRect.left;
187
+ const topRelative = yDom - containerRect.top;
180
188
  let text;
181
189
  if (showPercentage) {
182
190
  const percentage = (value / visibleTotal * 100).toFixed(1);
@@ -184,7 +192,7 @@ function PieChart({
184
192
  } else {
185
193
  text = String(value);
186
194
  }
187
- newLabels.push({ x, y, text, opacity: 1 });
195
+ newLabels.push({ left: leftRelative, top: topRelative, text, opacity: 1 });
188
196
  });
189
197
  setDataLabels(newLabels);
190
198
  };
@@ -198,6 +206,27 @@ function PieChart({
198
206
  }, 500);
199
207
  return () => clearTimeout(timeout);
200
208
  }, [datasets, showDataLabels, showPercentage]);
209
+ useEffect(() => {
210
+ const chart = chartRef.current;
211
+ if (!chart) return;
212
+ const prevOnComplete = chart.options.animation?.onComplete;
213
+ chart.options.animation = {
214
+ ...chart.options.animation,
215
+ onComplete: () => {
216
+ try {
217
+ prevOnComplete && prevOnComplete();
218
+ } catch (e) {
219
+ }
220
+ calculateLabels();
221
+ }
222
+ };
223
+ chart.update();
224
+ return () => {
225
+ if (chart && chart.options && chart.options.animation) {
226
+ chart.options.animation.onComplete = prevOnComplete;
227
+ }
228
+ };
229
+ }, [showDataLabels, showPercentage, datasets]);
201
230
  useEffect(() => {
202
231
  if (!chartRef.current || !showDataLabels) return;
203
232
  const chart = chartRef.current;
@@ -221,6 +250,7 @@ function PieChart({
221
250
  animateRotate: true,
222
251
  animateScale: true,
223
252
  duration: 400
253
+ // onComplete تنظیم می‌شود در useEffect بالا تا فقط رفتار محاسبه لیبل را تحت تاثیر قرار دهیم
224
254
  },
225
255
  plugins: {
226
256
  tooltip: {
@@ -316,8 +346,8 @@ function PieChart({
316
346
  key: index,
317
347
  sx: {
318
348
  position: "absolute",
319
- left: label.x / (window.devicePixelRatio || 1),
320
- top: label.y / (window.devicePixelRatio || 1),
349
+ left: label.left,
350
+ top: label.top,
321
351
  transform: "translate(-50%, -50%)",
322
352
  color: "#fff",
323
353
  fontWeight: "bold",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../react-shim.js","../../src/charts/bar/index.tsx","../../src/charts/pie/index.tsx"],"sourcesContent":["import * as React from \"react\";\nexport { React };\n","\"use client\";\nimport { useRef, useState } from \"react\";\nimport { Chart } from \"react-chartjs-2\";\nimport {\n Chart as ChartJS,\n CategoryScale,\n LinearScale,\n LogarithmicScale,\n BarElement,\n LineElement,\n PointElement,\n Tooltip,\n Legend,\n BarController,\n LineController,\n Chart as ChartType,\n} from \"chart.js\";\nimport { Box } from \"@mui/material\";\n\nChartJS.register(\n CategoryScale,\n LinearScale,\n LogarithmicScale,\n BarElement,\n LineElement,\n PointElement,\n Tooltip,\n Legend,\n BarController,\n LineController\n);\n\ninterface Dataset {\n label: string;\n data: (number | null)[];\n backgroundColor: string;\n borderColor?: string;\n borderWidth?: number;\n type?: \"line\";\n order?: number;\n tension?: number;\n pointRadius?: number;\n fill?: boolean;\n}\n\ninterface Props {\n labels: string[];\n datasets: Dataset[];\n height?: number;\n}\n\nexport default function BarChart({ labels, datasets, height }: Props) {\n const chartRef = useRef<ChartType | null>(null);\n const [hiddenIndices, setHiddenIndices] = useState<Set<number>>(new Set());\n\n // --- داده‌های visible ---\n const visibleDatasets = datasets.filter((_, i) => !hiddenIndices.has(i));\n const allValues = ([] as number[]).concat(\n ...visibleDatasets.map((ds) =>\n ds.data.filter((v): v is number => v !== null)\n )\n );\n\n const minValue = allValues.length ? Math.min(...allValues) : 0;\n const maxValue = allValues.length ? Math.max(...allValues) : 1;\n\n // --- تصمیم هوشمند برای scale ---\n const useLogScale = maxValue / (minValue || 1) > 50; // اگر اختلاف >50 برابر باشد log scale\n const scaleType: \"linear\" | \"logarithmic\" = useLogScale\n ? \"logarithmic\"\n : \"linear\";\n\n // --- محاسبه محور Y ---\n let yMin = minValue;\n let yMax = maxValue;\n let stepSize: number | undefined = 1;\n\n if (scaleType === \"linear\") {\n const range = yMax - yMin;\n const targetLines = 8;\n let rawStep = range / targetLines;\n\n const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));\n const normalized = rawStep / magnitude;\n if (normalized <= 1) stepSize = 1 * magnitude;\n else if (normalized <= 2) stepSize = 2 * magnitude;\n else if (normalized <= 5) stepSize = 5 * magnitude;\n else stepSize = 10 * magnitude;\n\n yMin = Math.floor(yMin / stepSize) * stepSize;\n yMax = Math.ceil(yMax / stepSize) * stepSize;\n } else {\n yMin = Math.max(minValue, 1);\n yMax = maxValue;\n stepSize = undefined;\n }\n\n // --- تنظیمات Chart.js ---\n const options = {\n responsive: true,\n maintainAspectRatio: false,\n animation: { duration: 500 },\n scales: {\n y: {\n type: scaleType,\n min: yMin,\n max: yMax,\n ticks: {\n ...(stepSize !== undefined ? { stepSize } : {}),\n callback: (value: any) => {\n // محدود کردن تعداد اعشار به حداکثر 2\n const num = Number(value);\n if (scaleType === \"logarithmic\") return num.toLocaleString();\n // اگر عدد خیلی بزرگ است، بدون اعشار\n if (num >= 1000) return num.toLocaleString();\n // اعشار برای اعداد کوچک\n if (stepSize && stepSize < 1) return num.toFixed(2);\n return num;\n },\n font: { family: \"'Vazir', sans-serif\", size: 14 },\n },\n },\n x: {\n ticks: {\n autoSkip: false,\n font: { family: \"'Vazir', sans-serif\", size: 13 },\n },\n },\n },\n plugins: {\n legend: {\n labels: {\n usePointStyle: true, // دایره‌ای\n font: { size: 16, family: \"'Vazir', sans-serif\" },\n },\n onClick: (e: any, legendItem: any, legend: any) => {\n const index = legendItem.datasetIndex as number;\n const newHidden = new Set(hiddenIndices);\n if (hiddenIndices.has(index)) newHidden.delete(index);\n else newHidden.add(index);\n setHiddenIndices(newHidden);\n },\n },\n tooltip: {\n bodyFont: { family: \"'Vazir', sans-serif\", size: 14 },\n titleFont: { family: \"'Vazir', sans-serif\", size: 16 },\n },\n datalabels: { display: false },\n },\n };\n\n // --- تنظیمات نقاط ---\n ChartJS.defaults.elements.point.radius = 5;\n ChartJS.defaults.elements.point.hoverRadius = 9;\n ChartJS.defaults.elements.point.borderWidth = 0.2;\n ChartJS.defaults.elements.point.backgroundColor = \"red\";\n ChartJS.defaults.elements.point.borderColor = \"black\";\n\n return (\n <Box height={height ?? 600}>\n <Chart\n ref={chartRef}\n type=\"bar\"\n data={{\n labels,\n datasets: datasets.map((ds, i) => ({\n ...ds,\n hidden: hiddenIndices.has(i),\n })),\n }}\n options={options}\n />\n </Box>\n );\n}\n","'use client'\nimport { Pie } from \"react-chartjs-2\";\nimport { Chart as ChartJS, ArcElement, Tooltip, Legend, Chart } from \"chart.js\";\nimport { useMemo, useRef, useEffect, useState } from \"react\";\nimport { Box, Typography } from \"@mui/material\";\nimport Image from \"next/image\";\nimport ChartDataLabels from \"chartjs-plugin-datalabels\";\n\nChartJS.register(ArcElement, Tooltip, Legend, ChartDataLabels);\n\n// تنظیم فونت پیش‌فرض Chart.js به Vazir\nChartJS.defaults.font.family = \"Vazir, sans-serif\";\n\ninterface Props {\n labels: string[];\n datasets: {\n label: string;\n data: number[];\n backgroundColor: string | string[];\n borderWidth?: number;\n }[];\n height?: number;\n disableLogo?: boolean;\n logoSRC?: string;\n showDataLabels?: boolean;\n showPercentage?: boolean;\n}\n/**\n * 📊 PieChart — کامپوننت نمودار دایره‌ای (Pie)\n *\n * @component PieChart\n *\n * @param {string[]} labels - آرایه‌ای از برچسب‌ها برای هر بخش نمودار.\n * @param {boolean} [showDataLabels] - نمایش یا عدم نمایش برچسب‌های داده‌ها\n * @param {boolean} [showPercentage] - نمایش درصد به جای مقدار عددی در برچسب‌های داده‌ها (در صورت فعال بودن showDataLabels). درصد بر اساس داده‌های قابل مشاهده محاسبه می‌شود.\n * @param {Array<{\n * label: string,\n * data: number[],\n * backgroundColor: string[],\n * borderWidth?: number\n * }>} datasets - آرایه‌ای شامل یک آبجکت داده برای مقداردهی بخش‌های نمودار.\n * - label: عنوان داده‌ها (نمایش در legend)\n * - data: آرایه‌ای از مقادیر هر بخش\n * - backgroundColor: آرایه‌ای از رنگ‌ها برای هر بخش\n * - borderWidth: (اختیاری) ضخامت خط دور هر بخش\n * @param {number} [height] - ارتفاع نمودار (پیش‌فرض: 600 پیکسل)\n *\n * @description\n * این کامپوننت یک نمودار دایره‌ای با قابلیت شخصی‌سازی رنگ، داده و فونت (هماهنگ با وزیر) است.\n * - ریسپانسیو و مناسب صفحات فارسی\n * - امکان نمایش لوگو یا کامپوننت دلخواه در مرکز نمودار\n * - امکان نمایش درصد یا مقدار عددی در برچسب‌های داده‌ها بر اساس داده‌های قابل مشاهده\n *\n * @returns {JSX.Element} یک نمودار دایره‌ای با داده‌های ورودی\n *\n * @example\n * ```jsx\n * <PieChart\n * labels={[\"بخش اول\", \"بخش دوم\", \"بخش سوم\"]}\n * datasets={[\n * {\n * label: \"مقدار\",\n * data: [10, 20, 30],\n * backgroundColor: [\n * \"rgba(75,192,192,1)\",\n * \"rgba(255,99,132,1)\",\n * \"rgba(153,102,255,1)\",\n * ],\n * borderWidth: 2,\n * },\n * ]}\n * showDataLabels={true}\n * showPercentage={true}\n * />\n * ```\n */\nexport default function PieChart({\n labels,\n datasets,\n height,\n disableLogo,\n logoSRC,\n showDataLabels = false,\n showPercentage = false,\n}: Props) {\n const chartRef = useRef<ChartJS<\"pie\">>(null);\n const [dataLabels, setDataLabels] = useState<{ x: number; y: number; text: string; opacity: number }[]>([]);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // تابع محاسبه موقعیت لیبل‌ها\n const calculateLabels = () => {\n if (!showDataLabels || !chartRef.current || !containerRef.current) return;\n\n const chart = chartRef.current;\n const meta = chart.getDatasetMeta(0);\n const data = chart.data.datasets[0].data as number[];\n\n // گرفتن اطلاعات chart area\n const chartArea = chart.chartArea;\n\n // محاسبه مجموع داده‌های قابل مشاهده\n const visibleTotal = data.reduce((sum, val, index) => {\n if (!meta.data[index] || (meta.data[index] as any).hidden !== true) {\n return sum + val;\n }\n return sum;\n }, 0);\n\n const newLabels: { x: number; y: number; text: string; opacity: number }[] = [];\n\n meta.data.forEach((arc: any, index: number) => {\n if (arc.hidden) return;\n\n const value = data[index];\n if (value === 0) return;\n\n // محاسبه مرکز arc\n const centerAngle = (arc.startAngle + arc.endAngle) / 2;\n // نزدیک‌تر به دیواره (0.7 = بین مرکز و لبه، هرچه بیشتر به 1 نزدیک‌تر = نزدیک‌تر به لبه)\n const midRadius = arc.innerRadius + (arc.outerRadius - arc.innerRadius) * 0.65;\n\n // موقعیت در chart area - آینه کردن روی محور X\n const x = arc.x - Math.cos(centerAngle) * midRadius;\n const y = arc.y + Math.sin(centerAngle) * midRadius;\n\n let text: string;\n if (showPercentage) {\n const percentage = ((value / visibleTotal) * 100).toFixed(1);\n text = percentage + \"%\";\n } else {\n text = String(value);\n }\n\n newLabels.push({ x, y, text, opacity: 1 });\n });\n\n setDataLabels(newLabels);\n };\n\n // محاسبه موقعیت لیبل‌ها بعد از اتمام انیمیشن\n useEffect(() => {\n if (!showDataLabels) {\n setDataLabels([]);\n return;\n }\n\n // صبر برای اتمام انیمیشن اولیه (500ms)\n const timeout = setTimeout(() => {\n calculateLabels();\n }, 500);\n\n return () => clearTimeout(timeout);\n }, [datasets, showDataLabels, showPercentage]);\n\n // آپدیت لیبل‌ها بعد از هر تغییر در chart (مثل کلیک روی legend)\n useEffect(() => {\n if (!chartRef.current || !showDataLabels) return;\n\n const chart = chartRef.current;\n const originalUpdate = chart.update.bind(chart);\n\n chart.update = function (...args: any[]) {\n // مخفی کردن لیبل‌ها قبل از آپدیت\n setDataLabels(prev => prev.map(l => ({ ...l, opacity: 0 })));\n\n originalUpdate(...args);\n\n // محاسبه مجدد لیبل‌ها بعد از انیمیشن\n setTimeout(() => {\n calculateLabels();\n }, 250);\n };\n\n return () => {\n chart.update = originalUpdate;\n };\n }, [showDataLabels, showPercentage]);\n\n const options = useMemo(() => ({\n responsive: true,\n maintainAspectRatio: false,\n cutout: !disableLogo ? \"59%\" : \"0%\",\n animation: {\n animateRotate: true,\n animateScale: true,\n duration: 400,\n },\n plugins: {\n tooltip: {\n bodyFont: {\n family: \"Vazir, sans-serif\",\n size: 14,\n },\n titleFont: {\n family: \"Vazir, sans-serif\",\n size: 16,\n },\n },\n legend: {\n labels: {\n padding: 15,\n usePointStyle: true,\n color: '#666', // رنگ متن legend را نرم‌تر می‌کند\n font: {\n size: 16,\n family: \"Vazir, sans-serif\",\n },\n boxWidth: 40,\n paddingBottom: 10,\n generateLabels: (chart: any) => {\n const data = chart.data;\n const meta = chart.getDatasetMeta(0);\n return data.labels.map((label: string, index: number) => {\n const hidden = meta.data[index] ? meta.data[index].hidden : false;\n return {\n text: label,\n fillStyle: data.datasets[0].backgroundColor[index] || '#000',\n hidden: hidden,\n index: index,\n datasetIndex: 0,\n textDecoration: hidden ? 'line-through' : undefined,\n };\n });\n },\n },\n onClick: (e: any, legendItem: any, legend: any) => {\n const ci = legend.chart;\n const meta = ci.getDatasetMeta(legendItem.datasetIndex || 0);\n const index = legendItem.index;\n if (meta.data[index]) {\n meta.data[index].hidden = !meta.data[index].hidden;\n }\n ci.update();\n },\n },\n datalabels: {\n display: false, // غیرفعال - لیبل‌ها با React رندر می‌شوند\n },\n },\n }), [disableLogo]);\n\n // کامپوننتی که می‌خواهید در مرکز نمودار نمایش داده شود\n const CenterComponent = () => {\n return (\n <div\n style={{\n padding: \"10px\",\n borderRadius: \"8px\",\n textAlign: \"center\",\n width: 220,\n }}\n >\n <Image\n alt=\"\"\n width={220}\n height={220}\n src={logoSRC ?? \"/assets/images/pilogo.png\"}\n unoptimized\n />\n </div>\n );\n };\n\n return (\n <Box ref={containerRef} height={height ?? 600} sx={{ position: \"relative\" }}>\n <Pie\n ref={chartRef}\n data={{\n labels: labels,\n datasets: datasets,\n }}\n options={options}\n />\n {/* لیبل‌های سفارشی با فونت Vazir */}\n {showDataLabels && dataLabels.map((label, index) => (\n <Typography\n key={index}\n sx={{\n position: \"absolute\",\n left: label.x / (window.devicePixelRatio || 1),\n top: label.y / (window.devicePixelRatio || 1),\n transform: \"translate(-50%, -50%)\",\n color: \"#fff\",\n fontWeight: \"bold\",\n fontSize: 14,\n fontFamily: \"Vazir, sans-serif\",\n pointerEvents: \"none\",\n textShadow: \"0 1px 2px rgba(0,0,0,0.5)\",\n opacity: label.opacity,\n transition: \"opacity 0.2s ease-in-out, left 0.2s ease-in-out, top 0.2s ease-in-out\",\n }}\n >\n {label.text}\n </Typography>\n ))}\n {!disableLogo && (\n <div\n style={{\n position: \"absolute\",\n top: \"53%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n pointerEvents: \"none\", // جلوگیری از دریافت event روی این لایه\n }}\n >\n <CenterComponent />\n </div>\n )}\n </Box>\n );\n}\n"],"mappings":"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","names":["ChartJS","Tooltip","Legend","useRef","useState","Box"]}
1
+ {"version":3,"sources":["../../react-shim.js","../../src/charts/bar/index.tsx","../../src/charts/pie/index.tsx"],"sourcesContent":["import * as React from \"react\";\nexport { React };\n","\"use client\";\nimport { useRef, useState } from \"react\";\nimport { Chart } from \"react-chartjs-2\";\nimport {\n Chart as ChartJS,\n CategoryScale,\n LinearScale,\n LogarithmicScale,\n BarElement,\n LineElement,\n PointElement,\n Tooltip,\n Legend,\n BarController,\n LineController,\n Chart as ChartType,\n} from \"chart.js\";\nimport { Box } from \"@mui/material\";\n\nChartJS.register(\n CategoryScale,\n LinearScale,\n LogarithmicScale,\n BarElement,\n LineElement,\n PointElement,\n Tooltip,\n Legend,\n BarController,\n LineController\n);\n\ninterface Dataset {\n label: string;\n data: (number | null)[];\n backgroundColor: string;\n borderColor?: string;\n borderWidth?: number;\n type?: \"line\";\n order?: number;\n tension?: number;\n pointRadius?: number;\n fill?: boolean;\n}\n\ninterface Props {\n labels: string[];\n datasets: Dataset[];\n height?: number;\n}\n/**\n * 📊 BarChart — کامپوننت نمودار میله‌ای (Bar / Combo Bar+Line)\n *\n * @component BarChart\n *\n * @param {string[]} labels\n * آرایه‌ای از برچسب‌های محور افقی (X). طول این آرایه مبنای تمام داده‌هاست.\n *\n * @param {Array<{\n * label: string,\n * data: (number | null)[],\n * backgroundColor: string,\n * borderColor?: string,\n * borderWidth?: number,\n * type?: \"line\",\n * order?: number,\n * tension?: number,\n * pointRadius?: number,\n * fill?: boolean\n * }>} datasets\n *\n * آرایه‌ای از سری‌های داده برای نمایش در نمودار.\n * هر آبجکت یک سری داده است که می‌تواند میله‌ای (Bar) یا خطی (Line) باشد:\n *\n * - ● **label**: عنوان سری (نمایش در Legend)\n * - ● **data**: مقادیر هر نقطه – مقدار `null` باعث حذف نقطه از نمودار می‌شود.\n * - ● **backgroundColor**: رنگ میله یا رنگ پرشدگی خط\n * - ● **borderColor**: (اختیاری) رنگ خط دور میله یا خط\n * - ● **borderWidth**: (اختیاری) ضخامت خط دور میله یا خط\n * - ● **type**: اگر `\"line\"` باشد، سری به صورت نمودار خطی نمایش داده می‌شود (Combo chart)\n * - ● **order**: ترتیب رسم (سری با order بزرگ‌تر روی سایر سری‌ها قرار می‌گیرد)\n * - ● **tension**: (خطی) میزان خمیدگی منحنی (۰ = خط صاف)\n * - ● **pointRadius**: (خطی) شعاع نقاط\n * - ● **fill**: (خطی) پر شدن زیر نمودار خطی\n *\n *\n * @param {number} [height=600]\n * ارتفاع نمودار بر حسب پیکسل.\n *\n *\n * @description\n * این کامپوننت یک نمودار میله‌ای (BarChart) با پشتیبانی از **نمودار ترکیبی Bar + Line**\n * است و برای نمایش داده‌ها در محیط فارسی و راست‌چین بهینه‌سازی شده است.\n *\n * ✔ پشتیبانی از فونت وزیر \n * ✔ پشتیبانی از RTL \n * ✔ امکان ترکیب چند سری میله‌ای یا خطی \n * ✔ مقیاس‌دهی خودکار محور Y \n * ✔ تشخیص خودکار بین `linear` و `logarithmic` \n * (اگر اختلاف min/max بیش از ۵۰ برابر باشد، محور Y به حالت لگاریتمی تغییر می‌کند)\n *\n * 🔹 تعامل Legend:\n * کلیک روی هر سری در Legend آن را مخفی/ظاهر می‌کند و محور Y با توجه به مقدار سری‌های\n * قابل‌مشاهده مجدداً محاسبه می‌شود.\n *\n *\n * @returns {JSX.Element}\n * یک نمودار میله‌ای یا ترکیبی با قابلیت شخصی‌سازی کامل.\n *\n *\n * @example\n * ```jsx\n * <BarChart\n * labels={[\"شنبه\", \"یکشنبه\", \"دوشنبه\"]}\n * datasets={[\n * {\n * label: \"فروش\",\n * data: [10, 20, 15],\n * backgroundColor: \"rgba(75,192,192,0.7)\",\n * },\n * {\n * label: \"میانگین\",\n * data: [12, 18, 14],\n * type: \"line\",\n * borderColor: \"red\",\n * backgroundColor: \"transparent\",\n * borderWidth: 3,\n * tension: 0.4,\n * pointRadius: 4,\n * fill: false,\n * order: 0\n * }\n * ]}\n * height={400}\n * />\n * ```\n */\n\nexport default function BarChart({ labels, datasets, height }: Props) {\n const chartRef = useRef<ChartType | null>(null);\n const [hiddenIndices, setHiddenIndices] = useState<Set<number>>(new Set());\n\n // --- داده‌های visible ---\n const visibleDatasets = datasets.filter((_, i) => !hiddenIndices.has(i));\n const allValues = ([] as number[]).concat(\n ...visibleDatasets.map((ds) =>\n ds.data.filter((v): v is number => v !== null)\n )\n );\n\n const minValue = allValues.length ? Math.min(...allValues) : 0;\n const maxValue = allValues.length ? Math.max(...allValues) : 1;\n\n // --- تصمیم هوشمند برای scale ---\n const useLogScale = maxValue / (minValue || 1) > 50; // اگر اختلاف >50 برابر باشد log scale\n const scaleType: \"linear\" | \"logarithmic\" = useLogScale\n ? \"logarithmic\"\n : \"linear\";\n\n // --- محاسبه محور Y ---\n let yMin = minValue;\n let yMax = maxValue;\n let stepSize: number | undefined = 1;\n\n if (scaleType === \"linear\") {\n const range = yMax - yMin;\n const targetLines = 8;\n let rawStep = range / targetLines;\n\n const magnitude = Math.pow(10, Math.floor(Math.log10(rawStep)));\n const normalized = rawStep / magnitude;\n if (normalized <= 1) stepSize = 1 * magnitude;\n else if (normalized <= 2) stepSize = 2 * magnitude;\n else if (normalized <= 5) stepSize = 5 * magnitude;\n else stepSize = 10 * magnitude;\n\n yMin = Math.floor(yMin / stepSize) * stepSize;\n yMax = Math.ceil(yMax / stepSize) * stepSize;\n } else {\n yMin = Math.max(minValue, 1);\n yMax = maxValue;\n stepSize = undefined;\n }\n\n // --- تنظیمات Chart.js ---\n const options = {\n responsive: true,\n maintainAspectRatio: false,\n animation: { duration: 500 },\n scales: {\n y: {\n type: scaleType,\n min: yMin,\n max: yMax,\n ticks: {\n ...(stepSize !== undefined ? { stepSize } : {}),\n callback: (value: any) => {\n // محدود کردن تعداد اعشار به حداکثر 2\n const num = Number(value);\n if (scaleType === \"logarithmic\") return num.toLocaleString();\n // اگر عدد خیلی بزرگ است، بدون اعشار\n if (num >= 1000) return num.toLocaleString();\n // اعشار برای اعداد کوچک\n if (stepSize && stepSize < 1) return num.toFixed(2);\n return num;\n },\n font: { family: \"'Vazir', sans-serif\", size: 14 },\n },\n },\n x: {\n ticks: {\n autoSkip: false,\n font: { family: \"'Vazir', sans-serif\", size: 13 },\n },\n },\n },\n plugins: {\n legend: {\n labels: {\n usePointStyle: true, // دایره‌ای\n font: { size: 16, family: \"'Vazir', sans-serif\" },\n },\n onClick: (e: any, legendItem: any, legend: any) => {\n const index = legendItem.datasetIndex as number;\n const newHidden = new Set(hiddenIndices);\n if (hiddenIndices.has(index)) newHidden.delete(index);\n else newHidden.add(index);\n setHiddenIndices(newHidden);\n },\n },\n tooltip: {\n bodyFont: { family: \"'Vazir', sans-serif\", size: 14 },\n titleFont: { family: \"'Vazir', sans-serif\", size: 16 },\n },\n datalabels: { display: false },\n },\n };\n\n // --- تنظیمات نقاط ---\n ChartJS.defaults.elements.point.radius = 5;\n ChartJS.defaults.elements.point.hoverRadius = 9;\n ChartJS.defaults.elements.point.borderWidth = 0.2;\n ChartJS.defaults.elements.point.backgroundColor = \"red\";\n ChartJS.defaults.elements.point.borderColor = \"black\";\n\n return (\n <Box height={height ?? 600}>\n <Chart\n ref={chartRef}\n type=\"bar\"\n data={{\n labels,\n datasets: datasets.map((ds, i) => ({\n ...ds,\n hidden: hiddenIndices.has(i),\n })),\n }}\n options={options}\n />\n </Box>\n );\n}\n","'use client'\nimport { Pie } from \"react-chartjs-2\";\nimport { Chart as ChartJS, ArcElement, Tooltip, Legend, Chart } from \"chart.js\";\nimport { useMemo, useRef, useEffect, useState } from \"react\";\nimport { Box, Typography } from \"@mui/material\";\nimport Image from \"next/image\";\nimport ChartDataLabels from \"chartjs-plugin-datalabels\";\n\nChartJS.register(ArcElement, Tooltip, Legend, ChartDataLabels);\n\n// تنظیم فونت پیش‌فرض Chart.js به Vazir\nChartJS.defaults.font.family = \"Vazir, sans-serif\";\n\ninterface Props {\n labels: string[];\n datasets: {\n label: string;\n data: number[];\n backgroundColor: string | string[];\n borderWidth?: number;\n }[];\n height?: number;\n disableLogo?: boolean;\n logoSRC?: string;\n showDataLabels?: boolean;\n showPercentage?: boolean;\n}\n/**\n * 📊 PieChart — کامپوننت نمودار دایره‌ای (Pie)\n *\n * @component PieChart\n *\n * @param {string[]} labels - آرایه‌ای از برچسب‌ها برای هر بخش نمودار.\n * @param {boolean} [showDataLabels] - نمایش یا عدم نمایش برچسب‌های داده‌ها\n * @param {boolean} [showPercentage] - نمایش درصد به جای مقدار عددی در برچسب‌های داده‌ها (در صورت فعال بودن showDataLabels). درصد بر اساس داده‌های قابل مشاهده محاسبه می‌شود.\n * @param {Array<{\n * label: string,\n * data: number[],\n * backgroundColor: string[],\n * borderWidth?: number\n * }>} datasets - آرایه‌ای شامل یک آبجکت داده برای مقداردهی بخش‌های نمودار.\n * - label: عنوان داده‌ها (نمایش در legend)\n * - data: آرایه‌ای از مقادیر هر بخش\n * - backgroundColor: آرایه‌ای از رنگ‌ها برای هر بخش\n * - borderWidth: (اختیاری) ضخامت خط دور هر بخش\n * @param {number} [height] - ارتفاع نمودار (پیش‌فرض: 600 پیکسل)\n *\n * @description\n * این کامپوننت یک نمودار دایره‌ای با قابلیت شخصی‌سازی رنگ، داده و فونت (هماهنگ با وزیر) است.\n * - ریسپانسیو و مناسب صفحات فارسی\n * - امکان نمایش لوگو یا کامپوننت دلخواه در مرکز نمودار\n * - امکان نمایش درصد یا مقدار عددی در برچسب‌های داده‌ها بر اساس داده‌های قابل مشاهده\n *\n * @returns {JSX.Element} یک نمودار دایره‌ای با داده‌های ورودی\n *\n * @example\n * ```jsx\n * <PieChart\n * labels={[\"بخش اول\", \"بخش دوم\", \"بخش سوم\"]}\n * datasets={[\n * {\n * label: \"مقدار\",\n * data: [10, 20, 30],\n * backgroundColor: [\n * \"rgba(75,192,192,1)\",\n * \"rgba(255,99,132,1)\",\n * \"rgba(153,102,255,1)\",\n * ],\n * borderWidth: 2,\n * },\n * ]}\n * showDataLabels={true}\n * showPercentage={true}\n * />\n * ```\n */\nexport default function PieChart({\n labels,\n datasets,\n height,\n disableLogo,\n logoSRC,\n showDataLabels = false,\n showPercentage = false,\n}: Props) {\n const chartRef = useRef<ChartJS<\"pie\">>(null);\n const [dataLabels, setDataLabels] = useState<{ left: number; top: number; text: string; opacity: number }[]>([]);\n const containerRef = useRef<HTMLDivElement>(null);\n\n // تابع محاسبه موقعیت لیبل‌ها\n const calculateLabels = () => {\n if (!showDataLabels || !chartRef.current || !containerRef.current) return;\n\n const chart = chartRef.current;\n const meta = chart.getDatasetMeta(0);\n const data = chart.data.datasets[0].data as number[];\n\n // گرفتن اطلاعات chart area\n // محاسبه مجموع داده‌های قابل مشاهده\n const visibleTotal = data.reduce((sum, val, index) => {\n if (!meta.data[index] || (meta.data[index] as any).hidden !== true) {\n return sum + val;\n }\n return sum;\n }, 0);\n\n const newLabels: { left: number; top: number; text: string; opacity: number }[] = [];\n\n // ابعاد و scale برای تبدیل مختصات داخلی canvas به مختصات DOM\n const canvas = chart.canvas as HTMLCanvasElement;\n const canvasRect = canvas.getBoundingClientRect();\n const containerRect = containerRef.current.getBoundingClientRect();\n\n // chart.width/chart.height => internal canvas pixel size (device pixel scaled)\n // canvasRect.width/canvasRect.height => displayed CSS size\n const scaleX = chart.width / canvasRect.width;\n const scaleY = chart.height / canvasRect.height;\n\n meta.data.forEach((arc: any, index: number) => {\n if (arc.hidden) return;\n\n const value = data[index];\n if (value === 0) return;\n\n // محاسبه مرکز arc در واحد internal canvas pixels\n const centerAngle = (arc.startAngle + arc.endAngle) / 2;\n const midRadius = arc.innerRadius + (arc.outerRadius - arc.innerRadius) * 0.65;\n\n const xInternal = arc.x - Math.cos(centerAngle) * midRadius;\n const yInternal = arc.y + Math.sin(centerAngle) * midRadius;\n\n // تبدیل به مختصات DOM (نسبت به viewport)\n const xDom = canvasRect.left + (xInternal / scaleX);\n const yDom = canvasRect.top + (yInternal / scaleY);\n\n // تبدیل به مختصات نسبی به container (برای absolute positioning داخل container)\n const leftRelative = xDom - containerRect.left;\n const topRelative = yDom - containerRect.top;\n\n let text: string;\n if (showPercentage) {\n const percentage = ((value / visibleTotal) * 100).toFixed(1);\n text = percentage + \"%\";\n } else {\n text = String(value);\n }\n\n newLabels.push({ left: leftRelative, top: topRelative, text, opacity: 1 });\n });\n\n setDataLabels(newLabels);\n };\n\n // محاسبه موقعیت لیبل‌ها بعد از اتمام انیمیشن\n useEffect(() => {\n if (!showDataLabels) {\n setDataLabels([]);\n return;\n }\n\n // صبر برای اتمام انیمیشن اولیه (فقط fallback) — animation.onComplete نیز تنظیم می‌شود.\n const timeout = setTimeout(() => {\n calculateLabels();\n }, 500);\n\n return () => clearTimeout(timeout);\n }, [datasets, showDataLabels, showPercentage]);\n\n // ثبت callback برای onComplete انیمیشن تا دقیقاً بعد از پایان انیمیشن محاسبه انجام شود\n useEffect(() => {\n const chart = chartRef.current;\n if (!chart) return;\n\n // نگهداری مقدار قبلی تا در cleanup به حالت قبل برگردد\n const prevOnComplete = (chart.options.animation as any)?.onComplete;\n\n (chart.options.animation as any) = {\n ...(chart.options.animation as any),\n onComplete: () => {\n // اگر callback قبلی هم بود، آن را اجرا کن\n try { prevOnComplete && prevOnComplete(); } catch (e) { /* ignore */ }\n calculateLabels();\n },\n };\n\n // اعمال تغییرات در chart (بدون trigger کردن انیمیشن)\n chart.update();\n\n return () => {\n // بازیابی onComplete قبلی (در صورت وجود)\n if (chart && chart.options && chart.options.animation) {\n (chart.options.animation as any).onComplete = prevOnComplete;\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [showDataLabels, showPercentage, datasets]);\n\n // آپدیت لیبل‌ها بعد از هر تغییر در chart (مثل کلیک روی legend)\n useEffect(() => {\n if (!chartRef.current || !showDataLabels) return;\n\n const chart = chartRef.current;\n const originalUpdate = chart.update.bind(chart);\n\n chart.update = function (...args: any[]) {\n // مخفی کردن لیبل‌ها قبل از آپدیت\n setDataLabels(prev => prev.map(l => ({ ...l, opacity: 0 })));\n\n originalUpdate(...args);\n\n // محاسبه مجدد لیبل‌ها بعد از انیمیشن\n setTimeout(() => {\n calculateLabels();\n }, 250);\n };\n\n return () => {\n chart.update = originalUpdate;\n };\n }, [showDataLabels, showPercentage]);\n\n const options = useMemo(() => ({\n responsive: true,\n maintainAspectRatio: false,\n cutout: !disableLogo ? \"59%\" : \"0%\",\n animation: {\n animateRotate: true,\n animateScale: true,\n duration: 400,\n // onComplete تنظیم می‌شود در useEffect بالا تا فقط رفتار محاسبه لیبل را تحت تاثیر قرار دهیم\n },\n plugins: {\n tooltip: {\n bodyFont: {\n family: \"Vazir, sans-serif\",\n size: 14,\n },\n titleFont: {\n family: \"Vazir, sans-serif\",\n size: 16,\n },\n },\n legend: {\n labels: {\n padding: 15,\n usePointStyle: true,\n color: '#666', // رنگ متن legend را نرم‌تر می‌کند\n font: {\n size: 16,\n family: \"Vazir, sans-serif\",\n },\n boxWidth: 40,\n paddingBottom: 10,\n generateLabels: (chart: any) => {\n const data = chart.data;\n const meta = chart.getDatasetMeta(0);\n return data.labels.map((label: string, index: number) => {\n const hidden = meta.data[index] ? meta.data[index].hidden : false;\n return {\n text: label,\n fillStyle: data.datasets[0].backgroundColor[index] || '#000',\n hidden: hidden,\n index: index,\n datasetIndex: 0,\n textDecoration: hidden ? 'line-through' : undefined,\n };\n });\n },\n },\n onClick: (e: any, legendItem: any, legend: any) => {\n const ci = legend.chart;\n const meta = ci.getDatasetMeta(legendItem.datasetIndex || 0);\n const index = legendItem.index;\n if (meta.data[index]) {\n meta.data[index].hidden = !meta.data[index].hidden;\n }\n ci.update();\n },\n },\n datalabels: {\n display: false, // غیرفعال - لیبل‌ها با React رندر می‌شوند\n },\n },\n }), [disableLogo]);\n\n // کامپوننتی که می‌خواهید در مرکز نمودار نمایش داده شود\n const CenterComponent = () => {\n return (\n <div\n style={{\n padding: \"10px\",\n borderRadius: \"8px\",\n textAlign: \"center\",\n width: 220,\n }}\n >\n <Image\n alt=\"\"\n width={220}\n height={220}\n src={logoSRC ?? \"/assets/images/pilogo.png\"}\n unoptimized\n />\n </div>\n );\n };\n\n return (\n <Box ref={containerRef} height={height ?? 600} sx={{ position: \"relative\" }}>\n <Pie\n ref={chartRef}\n data={{\n labels: labels,\n datasets: datasets,\n }}\n options={options}\n />\n {/* لیبل‌های سفارشی با فونت Vazir */}\n {showDataLabels && dataLabels.map((label, index) => (\n <Typography\n key={index}\n sx={{\n position: \"absolute\",\n left: label.left,\n top: label.top,\n transform: \"translate(-50%, -50%)\",\n color: \"#fff\",\n fontWeight: \"bold\",\n fontSize: 14,\n fontFamily: \"Vazir, sans-serif\",\n pointerEvents: \"none\",\n textShadow: \"0 1px 2px rgba(0,0,0,0.5)\",\n opacity: label.opacity,\n transition: \"opacity 0.2s ease-in-out, left 0.2s ease-in-out, top 0.2s ease-in-out\",\n }}\n >\n {label.text}\n </Typography>\n ))}\n {!disableLogo && (\n <div\n style={{\n position: \"absolute\",\n top: \"53%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n pointerEvents: \"none\", // جلوگیری از دریافت event روی این لایه\n }}\n >\n <CenterComponent />\n </div>\n )}\n </Box>\n );\n}\n"],"mappings":";AAAA,YAAY,WAAW;;;ACCvB,SAAS,QAAQ,gBAAgB;AACjC,SAAS,aAAa;AACtB;AAAA,EACE,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,WAAW;AAEpB,QAAQ;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AA4Ge,SAAR,SAA0B,EAAE,QAAQ,UAAU,OAAO,GAAU;AACpE,QAAM,WAAW,OAAyB,IAAI;AAC9C,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAsB,oBAAI,IAAI,CAAC;AAGzE,QAAM,kBAAkB,SAAS,OAAO,CAAC,GAAG,MAAM,CAAC,cAAc,IAAI,CAAC,CAAC;AACvE,QAAM,YAAa,CAAC,EAAe;AAAA,IACjC,GAAG,gBAAgB;AAAA,MAAI,CAAC,OACtB,GAAG,KAAK,OAAO,CAAC,MAAmB,MAAM,IAAI;AAAA,IAC/C;AAAA,EACF;AAEA,QAAM,WAAW,UAAU,SAAS,KAAK,IAAI,GAAG,SAAS,IAAI;AAC7D,QAAM,WAAW,UAAU,SAAS,KAAK,IAAI,GAAG,SAAS,IAAI;AAG7D,QAAM,cAAc,YAAY,YAAY,KAAK;AACjD,QAAM,YAAsC,cACxC,gBACA;AAGJ,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,WAA+B;AAEnC,MAAI,cAAc,UAAU;AAC1B,UAAM,QAAQ,OAAO;AACrB,UAAM,cAAc;AACpB,QAAI,UAAU,QAAQ;AAEtB,UAAM,YAAY,KAAK,IAAI,IAAI,KAAK,MAAM,KAAK,MAAM,OAAO,CAAC,CAAC;AAC9D,UAAM,aAAa,UAAU;AAC7B,QAAI,cAAc,EAAG,YAAW,IAAI;AAAA,aAC3B,cAAc,EAAG,YAAW,IAAI;AAAA,aAChC,cAAc,EAAG,YAAW,IAAI;AAAA,QACpC,YAAW,KAAK;AAErB,WAAO,KAAK,MAAM,OAAO,QAAQ,IAAI;AACrC,WAAO,KAAK,KAAK,OAAO,QAAQ,IAAI;AAAA,EACtC,OAAO;AACL,WAAO,KAAK,IAAI,UAAU,CAAC;AAC3B,WAAO;AACP,eAAW;AAAA,EACb;AAGA,QAAM,UAAU;AAAA,IACd,YAAY;AAAA,IACZ,qBAAqB;AAAA,IACrB,WAAW,EAAE,UAAU,IAAI;AAAA,IAC3B,QAAQ;AAAA,MACN,GAAG;AAAA,QACD,MAAM;AAAA,QACN,KAAK;AAAA,QACL,KAAK;AAAA,QACL,OAAO;AAAA,UACL,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,UAC7C,UAAU,CAAC,UAAe;AAExB,kBAAM,MAAM,OAAO,KAAK;AACxB,gBAAI,cAAc,cAAe,QAAO,IAAI,eAAe;AAE3D,gBAAI,OAAO,IAAM,QAAO,IAAI,eAAe;AAE3C,gBAAI,YAAY,WAAW,EAAG,QAAO,IAAI,QAAQ,CAAC;AAClD,mBAAO;AAAA,UACT;AAAA,UACA,MAAM,EAAE,QAAQ,uBAAuB,MAAM,GAAG;AAAA,QAClD;AAAA,MACF;AAAA,MACA,GAAG;AAAA,QACD,OAAO;AAAA,UACL,UAAU;AAAA,UACV,MAAM,EAAE,QAAQ,uBAAuB,MAAM,GAAG;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,QAAQ;AAAA,QACN,QAAQ;AAAA,UACN,eAAe;AAAA;AAAA,UACf,MAAM,EAAE,MAAM,IAAI,QAAQ,sBAAsB;AAAA,QAClD;AAAA,QACA,SAAS,CAAC,GAAQ,YAAiB,WAAgB;AACjD,gBAAM,QAAQ,WAAW;AACzB,gBAAM,YAAY,IAAI,IAAI,aAAa;AACvC,cAAI,cAAc,IAAI,KAAK,EAAG,WAAU,OAAO,KAAK;AAAA,cAC/C,WAAU,IAAI,KAAK;AACxB,2BAAiB,SAAS;AAAA,QAC5B;AAAA,MACF;AAAA,MACA,SAAS;AAAA,QACP,UAAU,EAAE,QAAQ,uBAAuB,MAAM,GAAG;AAAA,QACpD,WAAW,EAAE,QAAQ,uBAAuB,MAAM,GAAG;AAAA,MACvD;AAAA,MACA,YAAY,EAAE,SAAS,MAAM;AAAA,IAC/B;AAAA,EACF;AAGA,UAAQ,SAAS,SAAS,MAAM,SAAS;AACzC,UAAQ,SAAS,SAAS,MAAM,cAAc;AAC9C,UAAQ,SAAS,SAAS,MAAM,cAAc;AAC9C,UAAQ,SAAS,SAAS,MAAM,kBAAkB;AAClD,UAAQ,SAAS,SAAS,MAAM,cAAc;AAE9C,SACE,oCAAC,OAAI,QAAQ,UAAU,OACrB;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,MAAK;AAAA,MACL,MAAM;AAAA,QACJ;AAAA,QACA,UAAU,SAAS,IAAI,CAAC,IAAI,OAAO;AAAA,UACjC,GAAG;AAAA,UACH,QAAQ,cAAc,IAAI,CAAC;AAAA,QAC7B,EAAE;AAAA,MACJ;AAAA,MACA;AAAA;AAAA,EACF,CACF;AAEJ;;;ACpQA,SAAS,WAAW;AACpB,SAAS,SAASA,UAAS,YAAY,WAAAC,UAAS,UAAAC,eAAqB;AACrE,SAAS,SAAS,UAAAC,SAAQ,WAAW,YAAAC,iBAAgB;AACrD,SAAS,OAAAC,MAAK,kBAAkB;AAChC,OAAO,WAAW;AAClB,OAAO,qBAAqB;AAE5BL,SAAQ,SAAS,YAAYC,UAASC,SAAQ,eAAe;AAG7DF,SAAQ,SAAS,KAAK,SAAS;AAiEhB,SAAR,SAA0B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,iBAAiB;AACnB,GAAU;AACR,QAAM,WAAWG,QAAuB,IAAI;AAC5C,QAAM,CAAC,YAAY,aAAa,IAAIC,UAAyE,CAAC,CAAC;AAC/G,QAAM,eAAeD,QAAuB,IAAI;AAGhD,QAAM,kBAAkB,MAAM;AAC5B,QAAI,CAAC,kBAAkB,CAAC,SAAS,WAAW,CAAC,aAAa,QAAS;AAEnE,UAAM,QAAQ,SAAS;AACvB,UAAM,OAAO,MAAM,eAAe,CAAC;AACnC,UAAM,OAAO,MAAM,KAAK,SAAS,CAAC,EAAE;AAIpC,UAAM,eAAe,KAAK,OAAO,CAAC,KAAK,KAAK,UAAU;AACpD,UAAI,CAAC,KAAK,KAAK,KAAK,KAAM,KAAK,KAAK,KAAK,EAAU,WAAW,MAAM;AAClE,eAAO,MAAM;AAAA,MACf;AACA,aAAO;AAAA,IACT,GAAG,CAAC;AAEJ,UAAM,YAA4E,CAAC;AAGnF,UAAM,SAAS,MAAM;AACrB,UAAM,aAAa,OAAO,sBAAsB;AAChD,UAAM,gBAAgB,aAAa,QAAQ,sBAAsB;AAIjE,UAAM,SAAS,MAAM,QAAQ,WAAW;AACxC,UAAM,SAAS,MAAM,SAAS,WAAW;AAEzC,SAAK,KAAK,QAAQ,CAAC,KAAU,UAAkB;AAC7C,UAAI,IAAI,OAAQ;AAEhB,YAAM,QAAQ,KAAK,KAAK;AACxB,UAAI,UAAU,EAAG;AAGjB,YAAM,eAAe,IAAI,aAAa,IAAI,YAAY;AACtD,YAAM,YAAY,IAAI,eAAe,IAAI,cAAc,IAAI,eAAe;AAE1E,YAAM,YAAY,IAAI,IAAI,KAAK,IAAI,WAAW,IAAI;AAClD,YAAM,YAAY,IAAI,IAAI,KAAK,IAAI,WAAW,IAAI;AAGlD,YAAM,OAAO,WAAW,OAAQ,YAAY;AAC5C,YAAM,OAAO,WAAW,MAAO,YAAY;AAG3C,YAAM,eAAe,OAAO,cAAc;AAC1C,YAAM,cAAc,OAAO,cAAc;AAEzC,UAAI;AACJ,UAAI,gBAAgB;AAClB,cAAM,cAAe,QAAQ,eAAgB,KAAK,QAAQ,CAAC;AAC3D,eAAO,aAAa;AAAA,MACtB,OAAO;AACL,eAAO,OAAO,KAAK;AAAA,MACrB;AAEA,gBAAU,KAAK,EAAE,MAAM,cAAc,KAAK,aAAa,MAAM,SAAS,EAAE,CAAC;AAAA,IAC3E,CAAC;AAED,kBAAc,SAAS;AAAA,EACzB;AAGA,YAAU,MAAM;AACd,QAAI,CAAC,gBAAgB;AACnB,oBAAc,CAAC,CAAC;AAChB;AAAA,IACF;AAGA,UAAM,UAAU,WAAW,MAAM;AAC/B,sBAAgB;AAAA,IAClB,GAAG,GAAG;AAEN,WAAO,MAAM,aAAa,OAAO;AAAA,EACnC,GAAG,CAAC,UAAU,gBAAgB,cAAc,CAAC;AAG7C,YAAU,MAAM;AACd,UAAM,QAAQ,SAAS;AACvB,QAAI,CAAC,MAAO;AAGZ,UAAM,iBAAkB,MAAM,QAAQ,WAAmB;AAEzD,IAAC,MAAM,QAAQ,YAAoB;AAAA,MACjC,GAAI,MAAM,QAAQ;AAAA,MAClB,YAAY,MAAM;AAEhB,YAAI;AAAE,4BAAkB,eAAe;AAAA,QAAG,SAAS,GAAG;AAAA,QAAe;AACrE,wBAAgB;AAAA,MAClB;AAAA,IACF;AAGA,UAAM,OAAO;AAEb,WAAO,MAAM;AAEX,UAAI,SAAS,MAAM,WAAW,MAAM,QAAQ,WAAW;AACrD,QAAC,MAAM,QAAQ,UAAkB,aAAa;AAAA,MAChD;AAAA,IACF;AAAA,EAEF,GAAG,CAAC,gBAAgB,gBAAgB,QAAQ,CAAC;AAG7C,YAAU,MAAM;AACd,QAAI,CAAC,SAAS,WAAW,CAAC,eAAgB;AAE1C,UAAM,QAAQ,SAAS;AACvB,UAAM,iBAAiB,MAAM,OAAO,KAAK,KAAK;AAE9C,UAAM,SAAS,YAAa,MAAa;AAEvC,oBAAc,UAAQ,KAAK,IAAI,QAAM,EAAE,GAAG,GAAG,SAAS,EAAE,EAAE,CAAC;AAE3D,qBAAe,GAAG,IAAI;AAGtB,iBAAW,MAAM;AACf,wBAAgB;AAAA,MAClB,GAAG,GAAG;AAAA,IACR;AAEA,WAAO,MAAM;AACX,YAAM,SAAS;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,gBAAgB,cAAc,CAAC;AAEnC,QAAM,UAAU,QAAQ,OAAO;AAAA,IAC7B,YAAY;AAAA,IACZ,qBAAqB;AAAA,IACrB,QAAQ,CAAC,cAAc,QAAQ;AAAA,IAC/B,WAAW;AAAA,MACT,eAAe;AAAA,MACf,cAAc;AAAA,MACd,UAAU;AAAA;AAAA,IAEZ;AAAA,IACA,SAAS;AAAA,MACP,SAAS;AAAA,QACP,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,MAAM;AAAA,QACR;AAAA,QACA,WAAW;AAAA,UACT,QAAQ;AAAA,UACR,MAAM;AAAA,QACR;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,QAAQ;AAAA,UACN,SAAS;AAAA,UACT,eAAe;AAAA,UACf,OAAO;AAAA;AAAA,UACP,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ;AAAA,UACV;AAAA,UACA,UAAU;AAAA,UACV,eAAe;AAAA,UACf,gBAAgB,CAAC,UAAe;AAC9B,kBAAM,OAAO,MAAM;AACnB,kBAAM,OAAO,MAAM,eAAe,CAAC;AACnC,mBAAO,KAAK,OAAO,IAAI,CAAC,OAAe,UAAkB;AACvD,oBAAM,SAAS,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,EAAE,SAAS;AAC5D,qBAAO;AAAA,gBACL,MAAM;AAAA,gBACN,WAAW,KAAK,SAAS,CAAC,EAAE,gBAAgB,KAAK,KAAK;AAAA,gBACtD;AAAA,gBACA;AAAA,gBACA,cAAc;AAAA,gBACd,gBAAgB,SAAS,iBAAiB;AAAA,cAC5C;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,QACA,SAAS,CAAC,GAAQ,YAAiB,WAAgB;AACjD,gBAAM,KAAK,OAAO;AAClB,gBAAM,OAAO,GAAG,eAAe,WAAW,gBAAgB,CAAC;AAC3D,gBAAM,QAAQ,WAAW;AACzB,cAAI,KAAK,KAAK,KAAK,GAAG;AACpB,iBAAK,KAAK,KAAK,EAAE,SAAS,CAAC,KAAK,KAAK,KAAK,EAAE;AAAA,UAC9C;AACA,aAAG,OAAO;AAAA,QACZ;AAAA,MACF;AAAA,MACA,YAAY;AAAA,QACV,SAAS;AAAA;AAAA,MACX;AAAA,IACF;AAAA,EACF,IAAI,CAAC,WAAW,CAAC;AAGjB,QAAM,kBAAkB,MAAM;AAC5B,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,cAAc;AAAA,UACd,WAAW;AAAA,UACX,OAAO;AAAA,QACT;AAAA;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,KAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,KAAK,WAAW;AAAA,UAChB,aAAW;AAAA;AAAA,MACb;AAAA,IACF;AAAA,EAEJ;AAEA,SACE,oCAACE,MAAA,EAAI,KAAK,cAAc,QAAQ,UAAU,KAAK,IAAI,EAAE,UAAU,WAAW,KACxE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA;AAAA,EACF,GAEC,kBAAkB,WAAW,IAAI,CAAC,OAAO,UACxC;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,IAAI;AAAA,QACF,UAAU;AAAA,QACV,MAAM,MAAM;AAAA,QACZ,KAAK,MAAM;AAAA,QACX,WAAW;AAAA,QACX,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,YAAY;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,YAAY;AAAA,MACd;AAAA;AAAA,IAEC,MAAM;AAAA,EACT,CACD,GACA,CAAC,eACA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,UAAU;AAAA,QACV,KAAK;AAAA,QACL,MAAM;AAAA,QACN,WAAW;AAAA,QACX,eAAe;AAAA;AAAA,MACjB;AAAA;AAAA,IAEA,oCAAC,qBAAgB;AAAA,EACnB,CAEJ;AAEJ;","names":["ChartJS","Tooltip","Legend","useRef","useState","Box"]}
package/dist/index.js CHANGED
@@ -898,7 +898,6 @@ var import_DialogContent3 = __toESM(require("@mui/material/DialogContent"));
898
898
  var import_DialogTitle3 = __toESM(require("@mui/material/DialogTitle"));
899
899
  var import_react6 = require("react");
900
900
  var import_md2 = require("react-icons/md");
901
- var import_Tooltip = __toESM(require("@mui/material/Tooltip"));
902
901
  var import_react_hook_form3 = require("react-hook-form");
903
902
  var import_common = require("@mamrp/icons/common");
904
903
  function CustomTimePicker({
@@ -1038,7 +1037,7 @@ var TimePickerComponent = ({
1038
1037
  },
1039
1038
  InputProps: {
1040
1039
  ...!disabled && {
1041
- endAdornment: /* @__PURE__ */ React.createElement(import_material8.InputAdornment, { position: "end" }, /* @__PURE__ */ React.createElement(import_Tooltip.default, { title: "\u0627\u0646\u062A\u062E\u0627\u0628 \u0632\u0645\u0627\u0646" }, /* @__PURE__ */ React.createElement(import_material8.IconButton, { onClick: () => setIsModalOpen(true) }, /* @__PURE__ */ React.createElement(import_common.Clock, { size: 22, color: theme3.palette.text.primary }))))
1040
+ endAdornment: /* @__PURE__ */ React.createElement(import_material8.InputAdornment, { position: "end" }, /* @__PURE__ */ React.createElement(import_material8.Tooltip, { title: "\u0627\u0646\u062A\u062E\u0627\u0628 \u0632\u0645\u0627\u0646" }, /* @__PURE__ */ React.createElement(import_material8.IconButton, { onClick: () => setIsModalOpen(true) }, /* @__PURE__ */ React.createElement(import_common.Clock, { size: 22, color: theme3.palette.text.primary }))))
1042
1041
  }
1043
1042
  },
1044
1043
  sx: { width: fullwidth ? "100%" : "8rem" },