@mamrp/components 1.7.28 → 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.
- package/dist/charts/index.d.mts +67 -11
- package/dist/charts/index.d.ts +67 -11
- package/dist/charts/index.js +207 -43
- package/dist/charts/index.js.map +1 -1
- package/dist/charts/index.mjs +209 -44
- package/dist/charts/index.mjs.map +1 -1
- package/dist/date-pickers/index.d.mts +13 -0
- package/dist/date-pickers/index.d.ts +13 -0
- package/dist/date-pickers/index.js +3 -1
- package/dist/date-pickers/index.js.map +1 -1
- package/dist/date-pickers/index.mjs +3 -1
- package/dist/date-pickers/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/charts/index.js.map
CHANGED
|
@@ -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\";\r\nimport { Chart } from \"react-chartjs-2\";\r\nimport {\r\n Chart as ChartJS,\r\n CategoryScale,\r\n LinearScale,\r\n BarElement,\r\n LineElement,\r\n PointElement,\r\n Tooltip,\r\n Legend,\r\n BarController,\r\n LineController,\r\n Chart as ChartType,\r\n} from \"chart.js\";\r\nimport { Box } from \"@mui/material\";\r\n\r\nChartJS.register(\r\n CategoryScale,\r\n LinearScale,\r\n BarElement,\r\n LineElement,\r\n PointElement,\r\n Tooltip,\r\n Legend,\r\n BarController,\r\n LineController\r\n);\r\n\r\ninterface Props {\r\n labels: string[];\r\n datasets: {\r\n label: string;\r\n data: (number | null)[];\r\n backgroundColor: string;\r\n borderColor?: string;\r\n borderWidth?: number;\r\n type?: \"line\";\r\n order?: number;\r\n tension?: number;\r\n pointRadius?: number;\r\n fill?: boolean;\r\n }[];\r\n height?: number;\r\n}\r\n/**\r\n * 📊 BarChart — کامپوننت نمودار میلهای (Bar/Combo)\r\n *\r\n * @component BarChart\r\n *\r\n * @param {string[]} labels - آرایهای از برچسبها برای محور افقی (X).\r\n * @param {Array<{\r\n * label: string,\r\n * data: number[],\r\n * backgroundColor: string,\r\n * borderColor?: string,\r\n * borderWidth?: number,\r\n * type?: \"line\",\r\n * order?: number,\r\n * tension?: number,\r\n * pointRadius?: number,\r\n * fill?: boolean\r\n * }>} datasets - آرایهای از آبجکتهای داده برای هر سری نمودار.\r\n * - label: عنوان دادهها (نمایش در legend)\r\n * - data: آرایهای از مقادیر هر سری\r\n * - backgroundColor: رنگ میله یا خط\r\n * - borderColor: (اختیاری) رنگ خط دور میله یا خط\r\n * - borderWidth: (اختیاری) ضخامت خط دور میله یا خط\r\n * - type: (اختیاری) اگر \"line\" باشد، سری به صورت خطی نمایش داده میشود (نمودار ترکیبی)\r\n * - order: (اختیاری) ترتیب رسم سری (سری با order بالاتر روی بقیه قرار میگیرد)\r\n * - tension: (اختیاری) میزان خمیدگی خط (برای سریهای خطی)\r\n * - pointRadius: (اختیاری) شعاع نقاط روی خط (برای سریهای خطی)\r\n * - fill: (اختیاری) پر شدن زیر خط (برای سریهای خطی)\r\n *\r\n * @param {number} [height] - ارتفاع نمودار (پیشفرض: 600 پیکسل)\r\n *\r\n * @description\r\n * این کامپوننت یک نمودار میلهای (Bar) یا ترکیبی Bar/Line با قابلیت شخصیسازی کامل است.\r\n * - پشتیبانی از فونت وزیر و راستچین\r\n * - ریسپانسیو و مناسب صفحات فارسی\r\n * - امکان نمایش چند سری داده به صورت میلهای و خطی همزمان (Combo)\r\n * - شخصیسازی رنگ، ضخامت، ترتیب و استایل هر سری\r\n *\r\n * @returns {JSX.Element} یک نمودار میلهای یا ترکیبی با دادههای ورودی\r\n *\r\n * @example\r\n * ```jsx\r\n * <BarChart\r\n * labels={[\"شنبه\", \"یکشنبه\", \"دوشنبه\"]}\r\n * datasets={[\r\n * {\r\n * label: \"فروش\",\r\n * data: [10, 20, 15],\r\n * backgroundColor: \"rgba(75,192,192,0.7)\",\r\n * },\r\n * {\r\n * label: \"میانگین\",\r\n * data: [12, 18, 14],\r\n * borderColor: \"red\",\r\n * backgroundColor: \"transparent\",\r\n * type: \"line\",\r\n * order: 0,\r\n * borderWidth: 3,\r\n * tension: 0.4,\r\n * pointRadius: 4,\r\n * fill: false,\r\n * },\r\n * ]}\r\n * height={400}\r\n * />\r\n * ```\r\n */\r\nexport default function BarChart({ labels, datasets, height }: Props) {\r\n const options = {\r\n responsive: true,\r\n maintainAspectRatio: false,\r\n scales: {\r\n y: {\r\n ticks: {\r\n font: {\r\n family: \"'Vazir', sans-serif\",\r\n size: 14,\r\n },\r\n },\r\n },\r\n x: {\r\n ticks: {\r\n autoSkip: false,\r\n font: {\r\n family: \"'Vazir', sans-serif\",\r\n size: 13,\r\n },\r\n },\r\n },\r\n },\r\n plugins: {\r\n datalabels: {\r\n display: false, // ← غیرفعال\r\n },\r\n tooltip: {\r\n bodyFont: {\r\n family: \"'Vazir', sans-serif\",\r\n size: 14,\r\n },\r\n titleFont: {\r\n family: \"'Vazir', sans-serif\",\r\n size: 16,\r\n },\r\n },\r\n legend: {\r\n labels: {\r\n generateLabels: function (chart: ChartType) {\r\n const labels =\r\n ChartJS.defaults.plugins.legend.labels.generateLabels(chart);\r\n return labels.map((label) => ({\r\n ...label,\r\n text: \" \" + label.text + \" \",\r\n boxWidth: 40,\r\n boxHeight: 20,\r\n }));\r\n },\r\n padding: 15,\r\n usePointStyle: true,\r\n font: {\r\n size: 16,\r\n family: \"'Vazir', sans-serif\",\r\n },\r\n boxWidth: 40,\r\n paddingBottom: 10,\r\n },\r\n },\r\n },\r\n };\r\n\r\n return (\r\n <Box height={height ?? 600}>\r\n <Chart type=\"bar\" data={{ labels, datasets }} options={options} />\r\n </Box>\r\n );\r\n}\r\n","'use client'\nimport { Pie } from \"react-chartjs-2\";\nimport { Chart as ChartJS, ArcElement, Tooltip, Legend, Chart } from \"chart.js\";\nimport { useMemo } from \"react\";\nimport { Box } from \"@mui/material\";\nimport Image from \"next/image\";\nimport ChartDataLabels from \"chartjs-plugin-datalabels\";\n\nChartJS.register(ArcElement, Tooltip, Legend, ChartDataLabels);\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 options = {\n responsive: true,\n maintainAspectRatio: false,\n cutout: !disableLogo ? \"59%\" : \"0%\",\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: (context: any) => {\n return showDataLabels && !context.chart.getDatasetMeta(context.datasetIndex).data[context.dataIndex].hidden;\n },\n color: \"#fff\",\n font: {\n size: 14,\n weight: \"bold\",\n family: \"'Vazir', sans-serif\",\n } as const,\n anchor: \"center\" as const, // ← روی مرکز هر تکه\n align: \"center\" as const,\n offset: 20, // فاصله از مرکز (میتونی کم/زیاد کنی)\n formatter: showPercentage\n ? (value: number, context: any) => {\n if (value === 0) return \"\";\n // محاسبه مجموع دادههای قابل مشاهده\n const total = context.chart.data.datasets[context.datasetIndex].data.reduce(\n (sum: number, val: number, index: number) => {\n const meta = context.chart.getDatasetMeta(context.datasetIndex);\n if (!meta.data[index] || meta.data[index].hidden !== true) {\n return sum + val;\n }\n return sum;\n },\n 0\n );\n const percentage = ((value / total) * 100).toFixed(1);\n return percentage + \"%\";\n }\n : (value: number) => (value === 0 ? \"\" : value),\n },\n },\n };\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 height={height ?? 600} sx={{ position: \"relative\" }}>\n <Pie\n data={{\n labels: labels,\n datasets: datasets,\n }}\n options={options}\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","labels","import_react_chartjs_2","import_chart","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\";\r\nimport { Chart } from \"react-chartjs-2\";\r\nimport {\r\n Chart as ChartJS,\r\n CategoryScale,\r\n LinearScale,\r\n LogarithmicScale,\r\n BarElement,\r\n LineElement,\r\n PointElement,\r\n Tooltip,\r\n Legend,\r\n BarController,\r\n LineController,\r\n Chart as ChartType,\r\n} from \"chart.js\";\r\nimport { Box } from \"@mui/material\";\r\nimport { useRef, useEffect, useState } from \"react\";\r\n\r\nChartJS.register(\r\n CategoryScale,\r\n LinearScale,\r\n LogarithmicScale,\r\n BarElement,\r\n LineElement,\r\n PointElement,\r\n Tooltip,\r\n Legend,\r\n BarController,\r\n LineController\r\n);\r\n\r\n// تنظیم فونت پیشفرض Chart.js به Vazir\r\nChartJS.defaults.font.family = \"Vazir, sans-serif\";\r\n\r\ninterface Props {\r\n labels: string[];\r\n datasets: {\r\n label: string;\r\n data: (number | null)[];\r\n backgroundColor: string;\r\n borderColor?: string;\r\n borderWidth?: number;\r\n type?: \"line\";\r\n order?: number;\r\n tension?: number;\r\n pointRadius?: number;\r\n fill?: boolean;\r\n }[];\r\n height?: number;\r\n /**\r\n * حداقل مقدار محور Y (اختیاری)\r\n * اگر ست نشود، Chart.js خودش محاسبه میکند\r\n * ⚠️ نکته: اگر این مقدار ست شود، beginAtZero نادیده گرفته میشود\r\n */\r\n yAxisMin?: number;\r\n /**\r\n * حداکثر مقدار محور Y (اختیاری)\r\n * اگر ست نشود، Chart.js خودش محاسبه میکند\r\n */\r\n yAxisMax?: number;\r\n /**\r\n * آیا محور Y از صفر شروع شود؟\r\n * پیشفرض: true\r\n * ⚠️ نکته: اگر yAxisMin ست شود، این گزینه نادیده گرفته میشود\r\n */\r\n beginAtZero?: boolean;\r\n /**\r\n * استفاده از مقیاس لگاریتمی برای محور Y\r\n * مناسب برای دادههایی که اختلاف خیلی زیادی دارند\r\n * پیشفرض: false\r\n * ⚠️ نکته: مقادیر 0 یا منفی در مقیاس لگاریتمی نمایش داده نمیشوند\r\n */\r\n logarithmic?: boolean;\r\n /**\r\n * حداقل ارتفاع میله برای دادههای خیلی کوچک (پیکسل)\r\n * مقادیر خیلی کوچک (مثل 1) در کنار مقادیر بزرگ (مثل 10000) گم نمیشوند\r\n * پیشفرض: 0 (غیرفعال)\r\n */\r\n minBarLength?: number;\r\n}\r\n/**\r\n * 📊 BarChart — کامپوننت نمودار میلهای (Bar/Combo)\r\n *\r\n * @component BarChart\r\n *\r\n * @param {string[]} labels - آرایهای از برچسبها برای محور افقی (X).\r\n * @param {Array<{\r\n * label: string,\r\n * data: number[],\r\n * backgroundColor: string,\r\n * borderColor?: string,\r\n * borderWidth?: number,\r\n * type?: \"line\",\r\n * order?: number,\r\n * tension?: number,\r\n * pointRadius?: number,\r\n * fill?: boolean\r\n * }>} datasets - آرایهای از آبجکتهای داده برای هر سری نمودار.\r\n * - label: عنوان دادهها (نمایش در legend)\r\n * - data: آرایهای از مقادیر هر سری\r\n * - backgroundColor: رنگ میله یا خط\r\n * - borderColor: (اختیاری) رنگ خط دور میله یا خط\r\n * - borderWidth: (اختیاری) ضخامت خط دور میله یا خط\r\n * - type: (اختیاری) اگر \"line\" باشد، سری به صورت خطی نمایش داده میشود (نمودار ترکیبی)\r\n * - order: (اختیاری) ترتیب رسم سری (سری با order بالاتر روی بقیه قرار میگیرد)\r\n * - tension: (اختیاری) میزان خمیدگی خط (برای سریهای خطی)\r\n * - pointRadius: (اختیاری) شعاع نقاط روی خط (برای سریهای خطی)\r\n * - fill: (اختیاری) پر شدن زیر خط (برای سریهای خطی)\r\n *\r\n * @param {number} [height] - ارتفاع نمودار (پیشفرض: 600 پیکسل)\r\n * @param {number} [yAxisMin] - حداقل مقدار محور Y (نادیدهگرفتن beginAtZero)\r\n * @param {number} [yAxisMax] - حداکثر مقدار محور Y\r\n * @param {boolean} [beginAtZero=true] - آیا محور Y از صفر شروع شود؟ (اگر yAxisMin ست شود نادیده گرفته میشود)\r\n * @param {boolean} [logarithmic=false] - استفاده از مقیاس لگاریتمی (مقادیر 0 یا منفی نمایش داده نمیشوند)\r\n * @param {number} [minBarLength=0] - حداقل ارتفاع میله (پیکسل) - برای جلوگیری از گم شدن دادههای کوچک\r\n *\r\n * @description\r\n * این کامپوننت یک نمودار میلهای (Bar) یا ترکیبی Bar/Line با قابلیت شخصیسازی کامل است.\r\n * - پشتیبانی از فونت وزیر و راستچین\r\n * - ریسپانسیو و مناسب صفحات فارسی\r\n * - امکان نمایش چند سری داده به صورت میلهای و خطی همزمان (Combo)\r\n * - شخصیسازی رنگ، ضخامت، ترتیب و استایل هر سری\r\n * - پشتیبانی از مقیاس لگاریتمی برای دادههای با اختلاف زیاد\r\n * - minBarLength برای نمایش دادههای خیلی کوچک در کنار بزرگها\r\n *\r\n * @returns {JSX.Element} یک نمودار میلهای یا ترکیبی با دادههای ورودی\r\n *\r\n * @example\r\n * ```jsx\r\n * // نمودار ساده\r\n * <BarChart\r\n * labels={[\"شنبه\", \"یکشنبه\", \"دوشنبه\"]}\r\n * datasets={[\r\n * {\r\n * label: \"فروش\",\r\n * data: [10, 20, 15],\r\n * backgroundColor: \"rgba(75,192,192,0.7)\",\r\n * },\r\n * ]}\r\n * height={400}\r\n * />\r\n *\r\n * // نمودار با دادههای اختلاف زیاد (مقیاس لگاریتمی)\r\n * <BarChart\r\n * labels={[\"A\", \"B\", \"C\", \"D\"]}\r\n * datasets={[\r\n * {\r\n * label: \"مقادیر\",\r\n * data: [5, 50, 5000, 50000],\r\n * backgroundColor: \"rgba(75,192,192,0.7)\",\r\n * },\r\n * ]}\r\n * logarithmic={true}\r\n * height={400}\r\n * />\r\n *\r\n * // نمودار با کنترل دستی بازه محور Y\r\n * <BarChart\r\n * labels={[\"A\", \"B\", \"C\"]}\r\n * datasets={[\r\n * {\r\n * label: \"مقادیر\",\r\n * data: [100, 150, 120],\r\n * backgroundColor: \"rgba(75,192,192,0.7)\",\r\n * },\r\n * ]}\r\n * yAxisMin={80}\r\n * yAxisMax={200}\r\n * beginAtZero={false}\r\n * height={400}\r\n * />\r\n * ```\r\n */\r\nexport default function BarChart({\r\n labels,\r\n datasets,\r\n height,\r\n yAxisMin,\r\n yAxisMax,\r\n beginAtZero = true,\r\n logarithmic = false,\r\n minBarLength = 0,\r\n}: Props) {\r\n const chartRef = useRef<ChartJS>(null);\r\n const [fontLoaded, setFontLoaded] = useState(false);\r\n\r\n // صبر برای لود شدن فونت Vazir و سپس آپدیت chart\r\n useEffect(() => {\r\n let isMounted = true;\r\n\r\n const loadFont = async () => {\r\n if (typeof document !== \"undefined\" && document.fonts) {\r\n try {\r\n // منتظر لود شدن فونت Vazir به صورت مستقیم\r\n await document.fonts.load(\"16px Vazir\");\r\n await document.fonts.ready;\r\n } catch (e) {\r\n // اگر فونت پیدا نشد، ادامه بده\r\n }\r\n\r\n if (isMounted) {\r\n setFontLoaded(true);\r\n // آپدیت chart بعد از لود فونت\r\n setTimeout(() => {\r\n if (chartRef.current) {\r\n chartRef.current.update();\r\n }\r\n }, 100);\r\n }\r\n } else {\r\n if (isMounted) setFontLoaded(true);\r\n }\r\n };\r\n\r\n loadFont();\r\n\r\n return () => { isMounted = false; };\r\n }, []);\r\n\r\n // محاسبه min/max فقط بر اساس دادههای visible\r\n const getVisibleData = (): number[] => {\r\n if (!chartRef.current) return [];\r\n // فقط سریهایی که visible هستند و نوعشان bar است\r\n return datasets.reduce((acc: number[], ds, i) => {\r\n // اگر سری فعال است و نوعش bar است\r\n // @ts-ignore\r\n if ((ds.type === undefined || ds.type === \"bar\") && chartRef.current && typeof chartRef.current.isDatasetVisible === \"function\" && chartRef.current.isDatasetVisible(i)) {\r\n ds.data.forEach((v: number | null) => {\r\n if (typeof v === \"number\" && v > 0) acc.push(v);\r\n });\r\n }\r\n return acc;\r\n }, []);\r\n };\r\n\r\n let autoMin = yAxisMin;\r\n let autoMax = yAxisMax;\r\n if (logarithmic && yAxisMin === undefined && yAxisMax === undefined) {\r\n const visibleData = getVisibleData();\r\n if (visibleData.length) {\r\n const minVal = Math.min(...visibleData);\r\n const maxVal = Math.max(...visibleData);\r\n autoMin = minVal < 1 ? 0.5 : minVal * 0.7;\r\n autoMax = minVal === maxVal ? maxVal * 1.2 : maxVal * 1.1;\r\n }\r\n }\r\n\r\n // هر بار که legend تغییر کند، نمودار را آپدیت کن تا min/max درست شود\r\n useEffect(() => {\r\n if (!logarithmic || yAxisMin !== undefined || yAxisMax !== undefined) return;\r\n if (!chartRef.current) return;\r\n const handler = () => {\r\n // آپدیت min/max و نمودار\r\n const visibleData = getVisibleData();\r\n if (visibleData.length && chartRef.current && chartRef.current.options && chartRef.current.options.scales && chartRef.current.options.scales.y) {\r\n const minVal = Math.min(...visibleData);\r\n const maxVal = Math.max(...visibleData);\r\n chartRef.current.options.scales.y.min = minVal < 1 ? 0.5 : minVal * 0.7;\r\n chartRef.current.options.scales.y.max = minVal === maxVal ? maxVal * 1.2 : maxVal * 1.1;\r\n chartRef.current.update();\r\n }\r\n };\r\n // گوش دادن به event legend\r\n chartRef.current?.canvas?.addEventListener(\"click\", handler);\r\n return () => {\r\n chartRef.current?.canvas?.removeEventListener(\"click\", handler);\r\n };\r\n }, [logarithmic, yAxisMin, yAxisMax, datasets]);\r\n\r\n const options = {\r\n responsive: true,\r\n maintainAspectRatio: false,\r\n scales: {\r\n y: {\r\n type: logarithmic ? (\"logarithmic\" as const) : (\"linear\" as const),\r\n ...(yAxisMin === undefined && yAxisMax === undefined && !logarithmic && {\r\n beginAtZero: beginAtZero,\r\n }),\r\n ...(autoMin !== undefined && { min: autoMin }),\r\n ...(autoMax !== undefined && { max: autoMax }),\r\n ticks: {\r\n font: {\r\n family: \"Vazir, sans-serif\",\r\n size: 14,\r\n },\r\n ...(logarithmic && {\r\n callback: function (value: number | string) {\r\n const numValue = Number(value);\r\n // فقط توانهای ۱۰ را نمایش بده\r\n if (numValue === 0) return null;\r\n const log10 = Math.log10(numValue);\r\n if (Math.abs(log10 - Math.round(log10)) < 0.0001) {\r\n if (numValue >= 1000000) return (numValue / 1000000).toFixed(1) + \"M\";\r\n if (numValue >= 1000) return (numValue / 1000).toFixed(1) + \"K\";\r\n return numValue;\r\n }\r\n return null;\r\n },\r\n }),\r\n },\r\n },\r\n x: {\r\n ticks: {\r\n autoSkip: false,\r\n font: {\r\n family: \"Vazir, sans-serif\",\r\n size: 13,\r\n },\r\n },\r\n },\r\n },\r\n plugins: {\r\n datalabels: {\r\n display: false, // ← غیرفعال\r\n },\r\n tooltip: {\r\n bodyFont: {\r\n family: \"Vazir, sans-serif\",\r\n size: 14,\r\n },\r\n titleFont: {\r\n family: \"Vazir, sans-serif\",\r\n size: 16,\r\n },\r\n },\r\n legend: {\r\n labels: {\r\n generateLabels: function (chart: ChartType) {\r\n const labels =\r\n ChartJS.defaults.plugins.legend.labels.generateLabels(chart);\r\n return labels.map((label) => ({\r\n ...label,\r\n text: \" \" + label.text + \" \",\r\n boxWidth: 40,\r\n boxHeight: 20,\r\n }));\r\n },\r\n padding: 15,\r\n usePointStyle: true,\r\n font: {\r\n size: 16,\r\n family: \"Vazir, sans-serif\",\r\n },\r\n boxWidth: 40,\r\n paddingBottom: 10,\r\n },\r\n },\r\n },\r\n };\r\n\r\n // اضافه کردن minBarLength به همه datasets\r\n const processedDatasets = datasets.map((ds) => ({\r\n ...ds,\r\n minBarLength: minBarLength,\r\n }));\r\n\r\n return (\r\n <Box height={height ?? 600}>\r\n {fontLoaded && (\r\n <Chart ref={chartRef} type=\"bar\" data={{ labels, datasets: processedDatasets }} options={options} />\r\n )}\r\n </Box>\r\n );\r\n}\r\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","labels","import_react_chartjs_2","import_chart","import_react","import_material","ChartJS","ChartDataLabels","Image"]}
|
package/dist/charts/index.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
Chart as ChartJS,
|
|
8
8
|
CategoryScale,
|
|
9
9
|
LinearScale,
|
|
10
|
+
LogarithmicScale,
|
|
10
11
|
BarElement,
|
|
11
12
|
LineElement,
|
|
12
13
|
PointElement,
|
|
@@ -16,9 +17,11 @@ import {
|
|
|
16
17
|
LineController
|
|
17
18
|
} from "chart.js";
|
|
18
19
|
import { Box } from "@mui/material";
|
|
20
|
+
import { useRef, useEffect, useState } from "react";
|
|
19
21
|
ChartJS.register(
|
|
20
22
|
CategoryScale,
|
|
21
23
|
LinearScale,
|
|
24
|
+
LogarithmicScale,
|
|
22
25
|
BarElement,
|
|
23
26
|
LineElement,
|
|
24
27
|
PointElement,
|
|
@@ -27,16 +30,113 @@ ChartJS.register(
|
|
|
27
30
|
BarController,
|
|
28
31
|
LineController
|
|
29
32
|
);
|
|
30
|
-
|
|
33
|
+
ChartJS.defaults.font.family = "Vazir, sans-serif";
|
|
34
|
+
function BarChart({
|
|
35
|
+
labels,
|
|
36
|
+
datasets,
|
|
37
|
+
height,
|
|
38
|
+
yAxisMin,
|
|
39
|
+
yAxisMax,
|
|
40
|
+
beginAtZero = true,
|
|
41
|
+
logarithmic = false,
|
|
42
|
+
minBarLength = 0
|
|
43
|
+
}) {
|
|
44
|
+
const chartRef = useRef(null);
|
|
45
|
+
const [fontLoaded, setFontLoaded] = useState(false);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
let isMounted = true;
|
|
48
|
+
const loadFont = async () => {
|
|
49
|
+
if (typeof document !== "undefined" && document.fonts) {
|
|
50
|
+
try {
|
|
51
|
+
await document.fonts.load("16px Vazir");
|
|
52
|
+
await document.fonts.ready;
|
|
53
|
+
} catch (e) {
|
|
54
|
+
}
|
|
55
|
+
if (isMounted) {
|
|
56
|
+
setFontLoaded(true);
|
|
57
|
+
setTimeout(() => {
|
|
58
|
+
if (chartRef.current) {
|
|
59
|
+
chartRef.current.update();
|
|
60
|
+
}
|
|
61
|
+
}, 100);
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
if (isMounted) setFontLoaded(true);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
loadFont();
|
|
68
|
+
return () => {
|
|
69
|
+
isMounted = false;
|
|
70
|
+
};
|
|
71
|
+
}, []);
|
|
72
|
+
const getVisibleData = () => {
|
|
73
|
+
if (!chartRef.current) return [];
|
|
74
|
+
return datasets.reduce((acc, ds, i) => {
|
|
75
|
+
if ((ds.type === void 0 || ds.type === "bar") && chartRef.current && typeof chartRef.current.isDatasetVisible === "function" && chartRef.current.isDatasetVisible(i)) {
|
|
76
|
+
ds.data.forEach((v) => {
|
|
77
|
+
if (typeof v === "number" && v > 0) acc.push(v);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return acc;
|
|
81
|
+
}, []);
|
|
82
|
+
};
|
|
83
|
+
let autoMin = yAxisMin;
|
|
84
|
+
let autoMax = yAxisMax;
|
|
85
|
+
if (logarithmic && yAxisMin === void 0 && yAxisMax === void 0) {
|
|
86
|
+
const visibleData = getVisibleData();
|
|
87
|
+
if (visibleData.length) {
|
|
88
|
+
const minVal = Math.min(...visibleData);
|
|
89
|
+
const maxVal = Math.max(...visibleData);
|
|
90
|
+
autoMin = minVal < 1 ? 0.5 : minVal * 0.7;
|
|
91
|
+
autoMax = minVal === maxVal ? maxVal * 1.2 : maxVal * 1.1;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (!logarithmic || yAxisMin !== void 0 || yAxisMax !== void 0) return;
|
|
96
|
+
if (!chartRef.current) return;
|
|
97
|
+
const handler = () => {
|
|
98
|
+
const visibleData = getVisibleData();
|
|
99
|
+
if (visibleData.length && chartRef.current && chartRef.current.options && chartRef.current.options.scales && chartRef.current.options.scales.y) {
|
|
100
|
+
const minVal = Math.min(...visibleData);
|
|
101
|
+
const maxVal = Math.max(...visibleData);
|
|
102
|
+
chartRef.current.options.scales.y.min = minVal < 1 ? 0.5 : minVal * 0.7;
|
|
103
|
+
chartRef.current.options.scales.y.max = minVal === maxVal ? maxVal * 1.2 : maxVal * 1.1;
|
|
104
|
+
chartRef.current.update();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
chartRef.current?.canvas?.addEventListener("click", handler);
|
|
108
|
+
return () => {
|
|
109
|
+
chartRef.current?.canvas?.removeEventListener("click", handler);
|
|
110
|
+
};
|
|
111
|
+
}, [logarithmic, yAxisMin, yAxisMax, datasets]);
|
|
31
112
|
const options = {
|
|
32
113
|
responsive: true,
|
|
33
114
|
maintainAspectRatio: false,
|
|
34
115
|
scales: {
|
|
35
116
|
y: {
|
|
117
|
+
type: logarithmic ? "logarithmic" : "linear",
|
|
118
|
+
...yAxisMin === void 0 && yAxisMax === void 0 && !logarithmic && {
|
|
119
|
+
beginAtZero
|
|
120
|
+
},
|
|
121
|
+
...autoMin !== void 0 && { min: autoMin },
|
|
122
|
+
...autoMax !== void 0 && { max: autoMax },
|
|
36
123
|
ticks: {
|
|
37
124
|
font: {
|
|
38
|
-
family: "
|
|
125
|
+
family: "Vazir, sans-serif",
|
|
39
126
|
size: 14
|
|
127
|
+
},
|
|
128
|
+
...logarithmic && {
|
|
129
|
+
callback: function(value) {
|
|
130
|
+
const numValue = Number(value);
|
|
131
|
+
if (numValue === 0) return null;
|
|
132
|
+
const log10 = Math.log10(numValue);
|
|
133
|
+
if (Math.abs(log10 - Math.round(log10)) < 1e-4) {
|
|
134
|
+
if (numValue >= 1e6) return (numValue / 1e6).toFixed(1) + "M";
|
|
135
|
+
if (numValue >= 1e3) return (numValue / 1e3).toFixed(1) + "K";
|
|
136
|
+
return numValue;
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
40
140
|
}
|
|
41
141
|
}
|
|
42
142
|
},
|
|
@@ -44,7 +144,7 @@ function BarChart({ labels, datasets, height }) {
|
|
|
44
144
|
ticks: {
|
|
45
145
|
autoSkip: false,
|
|
46
146
|
font: {
|
|
47
|
-
family: "
|
|
147
|
+
family: "Vazir, sans-serif",
|
|
48
148
|
size: 13
|
|
49
149
|
}
|
|
50
150
|
}
|
|
@@ -57,11 +157,11 @@ function BarChart({ labels, datasets, height }) {
|
|
|
57
157
|
},
|
|
58
158
|
tooltip: {
|
|
59
159
|
bodyFont: {
|
|
60
|
-
family: "
|
|
160
|
+
family: "Vazir, sans-serif",
|
|
61
161
|
size: 14
|
|
62
162
|
},
|
|
63
163
|
titleFont: {
|
|
64
|
-
family: "
|
|
164
|
+
family: "Vazir, sans-serif",
|
|
65
165
|
size: 16
|
|
66
166
|
}
|
|
67
167
|
},
|
|
@@ -80,7 +180,7 @@ function BarChart({ labels, datasets, height }) {
|
|
|
80
180
|
usePointStyle: true,
|
|
81
181
|
font: {
|
|
82
182
|
size: 16,
|
|
83
|
-
family: "
|
|
183
|
+
family: "Vazir, sans-serif"
|
|
84
184
|
},
|
|
85
185
|
boxWidth: 40,
|
|
86
186
|
paddingBottom: 10
|
|
@@ -88,16 +188,22 @@ function BarChart({ labels, datasets, height }) {
|
|
|
88
188
|
}
|
|
89
189
|
}
|
|
90
190
|
};
|
|
91
|
-
|
|
191
|
+
const processedDatasets = datasets.map((ds) => ({
|
|
192
|
+
...ds,
|
|
193
|
+
minBarLength
|
|
194
|
+
}));
|
|
195
|
+
return /* @__PURE__ */ React.createElement(Box, { height: height ?? 600 }, fontLoaded && /* @__PURE__ */ React.createElement(Chart, { ref: chartRef, type: "bar", data: { labels, datasets: processedDatasets }, options }));
|
|
92
196
|
}
|
|
93
197
|
|
|
94
198
|
// src/charts/pie/index.tsx
|
|
95
199
|
import { Pie } from "react-chartjs-2";
|
|
96
200
|
import { Chart as ChartJS2, ArcElement, Tooltip as Tooltip2, Legend as Legend2 } from "chart.js";
|
|
97
|
-
import {
|
|
201
|
+
import { useMemo, useRef as useRef2, useEffect as useEffect2, useState as useState2 } from "react";
|
|
202
|
+
import { Box as Box2, Typography } from "@mui/material";
|
|
98
203
|
import Image from "next/image";
|
|
99
204
|
import ChartDataLabels from "chartjs-plugin-datalabels";
|
|
100
205
|
ChartJS2.register(ArcElement, Tooltip2, Legend2, ChartDataLabels);
|
|
206
|
+
ChartJS2.defaults.font.family = "Vazir, sans-serif";
|
|
101
207
|
function PieChart({
|
|
102
208
|
labels,
|
|
103
209
|
datasets,
|
|
@@ -107,18 +213,83 @@ function PieChart({
|
|
|
107
213
|
showDataLabels = false,
|
|
108
214
|
showPercentage = false
|
|
109
215
|
}) {
|
|
110
|
-
const
|
|
216
|
+
const chartRef = useRef2(null);
|
|
217
|
+
const [dataLabels, setDataLabels] = useState2([]);
|
|
218
|
+
const containerRef = useRef2(null);
|
|
219
|
+
const calculateLabels = () => {
|
|
220
|
+
if (!showDataLabels || !chartRef.current || !containerRef.current) return;
|
|
221
|
+
const chart = chartRef.current;
|
|
222
|
+
const meta = chart.getDatasetMeta(0);
|
|
223
|
+
const data = chart.data.datasets[0].data;
|
|
224
|
+
const chartArea = chart.chartArea;
|
|
225
|
+
const visibleTotal = data.reduce((sum, val, index) => {
|
|
226
|
+
if (!meta.data[index] || meta.data[index].hidden !== true) {
|
|
227
|
+
return sum + val;
|
|
228
|
+
}
|
|
229
|
+
return sum;
|
|
230
|
+
}, 0);
|
|
231
|
+
const newLabels = [];
|
|
232
|
+
meta.data.forEach((arc, index) => {
|
|
233
|
+
if (arc.hidden) return;
|
|
234
|
+
const value = data[index];
|
|
235
|
+
if (value === 0) return;
|
|
236
|
+
const centerAngle = (arc.startAngle + arc.endAngle) / 2;
|
|
237
|
+
const midRadius = arc.innerRadius + (arc.outerRadius - arc.innerRadius) * 0.65;
|
|
238
|
+
const x = arc.x - Math.cos(centerAngle) * midRadius;
|
|
239
|
+
const y = arc.y + Math.sin(centerAngle) * midRadius;
|
|
240
|
+
let text;
|
|
241
|
+
if (showPercentage) {
|
|
242
|
+
const percentage = (value / visibleTotal * 100).toFixed(1);
|
|
243
|
+
text = percentage + "%";
|
|
244
|
+
} else {
|
|
245
|
+
text = String(value);
|
|
246
|
+
}
|
|
247
|
+
newLabels.push({ x, y, text, opacity: 1 });
|
|
248
|
+
});
|
|
249
|
+
setDataLabels(newLabels);
|
|
250
|
+
};
|
|
251
|
+
useEffect2(() => {
|
|
252
|
+
if (!showDataLabels) {
|
|
253
|
+
setDataLabels([]);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const timeout = setTimeout(() => {
|
|
257
|
+
calculateLabels();
|
|
258
|
+
}, 500);
|
|
259
|
+
return () => clearTimeout(timeout);
|
|
260
|
+
}, [datasets, showDataLabels, showPercentage]);
|
|
261
|
+
useEffect2(() => {
|
|
262
|
+
if (!chartRef.current || !showDataLabels) return;
|
|
263
|
+
const chart = chartRef.current;
|
|
264
|
+
const originalUpdate = chart.update.bind(chart);
|
|
265
|
+
chart.update = function(...args) {
|
|
266
|
+
setDataLabels((prev) => prev.map((l) => ({ ...l, opacity: 0 })));
|
|
267
|
+
originalUpdate(...args);
|
|
268
|
+
setTimeout(() => {
|
|
269
|
+
calculateLabels();
|
|
270
|
+
}, 250);
|
|
271
|
+
};
|
|
272
|
+
return () => {
|
|
273
|
+
chart.update = originalUpdate;
|
|
274
|
+
};
|
|
275
|
+
}, [showDataLabels, showPercentage]);
|
|
276
|
+
const options = useMemo(() => ({
|
|
111
277
|
responsive: true,
|
|
112
278
|
maintainAspectRatio: false,
|
|
113
279
|
cutout: !disableLogo ? "59%" : "0%",
|
|
280
|
+
animation: {
|
|
281
|
+
animateRotate: true,
|
|
282
|
+
animateScale: true,
|
|
283
|
+
duration: 400
|
|
284
|
+
},
|
|
114
285
|
plugins: {
|
|
115
286
|
tooltip: {
|
|
116
287
|
bodyFont: {
|
|
117
|
-
family: "
|
|
288
|
+
family: "Vazir, sans-serif",
|
|
118
289
|
size: 14
|
|
119
290
|
},
|
|
120
291
|
titleFont: {
|
|
121
|
-
family: "
|
|
292
|
+
family: "Vazir, sans-serif",
|
|
122
293
|
size: 16
|
|
123
294
|
}
|
|
124
295
|
},
|
|
@@ -130,7 +301,7 @@ function PieChart({
|
|
|
130
301
|
// رنگ متن legend را نرمتر میکند
|
|
131
302
|
font: {
|
|
132
303
|
size: 16,
|
|
133
|
-
family: "
|
|
304
|
+
family: "Vazir, sans-serif"
|
|
134
305
|
},
|
|
135
306
|
boxWidth: 40,
|
|
136
307
|
paddingBottom: 10,
|
|
@@ -161,38 +332,11 @@ function PieChart({
|
|
|
161
332
|
}
|
|
162
333
|
},
|
|
163
334
|
datalabels: {
|
|
164
|
-
display:
|
|
165
|
-
|
|
166
|
-
},
|
|
167
|
-
color: "#fff",
|
|
168
|
-
font: {
|
|
169
|
-
size: 14,
|
|
170
|
-
weight: "bold",
|
|
171
|
-
family: "'Vazir', sans-serif"
|
|
172
|
-
},
|
|
173
|
-
anchor: "center",
|
|
174
|
-
// ← روی مرکز هر تکه
|
|
175
|
-
align: "center",
|
|
176
|
-
offset: 20,
|
|
177
|
-
// فاصله از مرکز (میتونی کم/زیاد کنی)
|
|
178
|
-
formatter: showPercentage ? (value, context) => {
|
|
179
|
-
if (value === 0) return "";
|
|
180
|
-
const total = context.chart.data.datasets[context.datasetIndex].data.reduce(
|
|
181
|
-
(sum, val, index) => {
|
|
182
|
-
const meta = context.chart.getDatasetMeta(context.datasetIndex);
|
|
183
|
-
if (!meta.data[index] || meta.data[index].hidden !== true) {
|
|
184
|
-
return sum + val;
|
|
185
|
-
}
|
|
186
|
-
return sum;
|
|
187
|
-
},
|
|
188
|
-
0
|
|
189
|
-
);
|
|
190
|
-
const percentage = (value / total * 100).toFixed(1);
|
|
191
|
-
return percentage + "%";
|
|
192
|
-
} : (value) => value === 0 ? "" : value
|
|
335
|
+
display: false
|
|
336
|
+
// غیرفعال - لیبلها با React رندر میشوند
|
|
193
337
|
}
|
|
194
338
|
}
|
|
195
|
-
};
|
|
339
|
+
}), [disableLogo]);
|
|
196
340
|
const CenterComponent = () => {
|
|
197
341
|
return /* @__PURE__ */ React.createElement(
|
|
198
342
|
"div",
|
|
@@ -216,16 +360,37 @@ function PieChart({
|
|
|
216
360
|
)
|
|
217
361
|
);
|
|
218
362
|
};
|
|
219
|
-
return /* @__PURE__ */ React.createElement(Box2, { height: height ?? 600, sx: { position: "relative" } }, /* @__PURE__ */ React.createElement(
|
|
363
|
+
return /* @__PURE__ */ React.createElement(Box2, { ref: containerRef, height: height ?? 600, sx: { position: "relative" } }, /* @__PURE__ */ React.createElement(
|
|
220
364
|
Pie,
|
|
221
365
|
{
|
|
366
|
+
ref: chartRef,
|
|
222
367
|
data: {
|
|
223
368
|
labels,
|
|
224
369
|
datasets
|
|
225
370
|
},
|
|
226
371
|
options
|
|
227
372
|
}
|
|
228
|
-
),
|
|
373
|
+
), showDataLabels && dataLabels.map((label, index) => /* @__PURE__ */ React.createElement(
|
|
374
|
+
Typography,
|
|
375
|
+
{
|
|
376
|
+
key: index,
|
|
377
|
+
sx: {
|
|
378
|
+
position: "absolute",
|
|
379
|
+
left: label.x / (window.devicePixelRatio || 1),
|
|
380
|
+
top: label.y / (window.devicePixelRatio || 1),
|
|
381
|
+
transform: "translate(-50%, -50%)",
|
|
382
|
+
color: "#fff",
|
|
383
|
+
fontWeight: "bold",
|
|
384
|
+
fontSize: 14,
|
|
385
|
+
fontFamily: "Vazir, sans-serif",
|
|
386
|
+
pointerEvents: "none",
|
|
387
|
+
textShadow: "0 1px 2px rgba(0,0,0,0.5)",
|
|
388
|
+
opacity: label.opacity,
|
|
389
|
+
transition: "opacity 0.2s ease-in-out, left 0.2s ease-in-out, top 0.2s ease-in-out"
|
|
390
|
+
}
|
|
391
|
+
},
|
|
392
|
+
label.text
|
|
393
|
+
)), !disableLogo && /* @__PURE__ */ React.createElement(
|
|
229
394
|
"div",
|
|
230
395
|
{
|
|
231
396
|
style: {
|
|
@@ -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\";\r\nimport { Chart } from \"react-chartjs-2\";\r\nimport {\r\n Chart as ChartJS,\r\n CategoryScale,\r\n LinearScale,\r\n BarElement,\r\n LineElement,\r\n PointElement,\r\n Tooltip,\r\n Legend,\r\n BarController,\r\n LineController,\r\n Chart as ChartType,\r\n} from \"chart.js\";\r\nimport { Box } from \"@mui/material\";\r\n\r\nChartJS.register(\r\n CategoryScale,\r\n LinearScale,\r\n BarElement,\r\n LineElement,\r\n PointElement,\r\n Tooltip,\r\n Legend,\r\n BarController,\r\n LineController\r\n);\r\n\r\ninterface Props {\r\n labels: string[];\r\n datasets: {\r\n label: string;\r\n data: (number | null)[];\r\n backgroundColor: string;\r\n borderColor?: string;\r\n borderWidth?: number;\r\n type?: \"line\";\r\n order?: number;\r\n tension?: number;\r\n pointRadius?: number;\r\n fill?: boolean;\r\n }[];\r\n height?: number;\r\n}\r\n/**\r\n * 📊 BarChart — کامپوننت نمودار میلهای (Bar/Combo)\r\n *\r\n * @component BarChart\r\n *\r\n * @param {string[]} labels - آرایهای از برچسبها برای محور افقی (X).\r\n * @param {Array<{\r\n * label: string,\r\n * data: number[],\r\n * backgroundColor: string,\r\n * borderColor?: string,\r\n * borderWidth?: number,\r\n * type?: \"line\",\r\n * order?: number,\r\n * tension?: number,\r\n * pointRadius?: number,\r\n * fill?: boolean\r\n * }>} datasets - آرایهای از آبجکتهای داده برای هر سری نمودار.\r\n * - label: عنوان دادهها (نمایش در legend)\r\n * - data: آرایهای از مقادیر هر سری\r\n * - backgroundColor: رنگ میله یا خط\r\n * - borderColor: (اختیاری) رنگ خط دور میله یا خط\r\n * - borderWidth: (اختیاری) ضخامت خط دور میله یا خط\r\n * - type: (اختیاری) اگر \"line\" باشد، سری به صورت خطی نمایش داده میشود (نمودار ترکیبی)\r\n * - order: (اختیاری) ترتیب رسم سری (سری با order بالاتر روی بقیه قرار میگیرد)\r\n * - tension: (اختیاری) میزان خمیدگی خط (برای سریهای خطی)\r\n * - pointRadius: (اختیاری) شعاع نقاط روی خط (برای سریهای خطی)\r\n * - fill: (اختیاری) پر شدن زیر خط (برای سریهای خطی)\r\n *\r\n * @param {number} [height] - ارتفاع نمودار (پیشفرض: 600 پیکسل)\r\n *\r\n * @description\r\n * این کامپوننت یک نمودار میلهای (Bar) یا ترکیبی Bar/Line با قابلیت شخصیسازی کامل است.\r\n * - پشتیبانی از فونت وزیر و راستچین\r\n * - ریسپانسیو و مناسب صفحات فارسی\r\n * - امکان نمایش چند سری داده به صورت میلهای و خطی همزمان (Combo)\r\n * - شخصیسازی رنگ، ضخامت، ترتیب و استایل هر سری\r\n *\r\n * @returns {JSX.Element} یک نمودار میلهای یا ترکیبی با دادههای ورودی\r\n *\r\n * @example\r\n * ```jsx\r\n * <BarChart\r\n * labels={[\"شنبه\", \"یکشنبه\", \"دوشنبه\"]}\r\n * datasets={[\r\n * {\r\n * label: \"فروش\",\r\n * data: [10, 20, 15],\r\n * backgroundColor: \"rgba(75,192,192,0.7)\",\r\n * },\r\n * {\r\n * label: \"میانگین\",\r\n * data: [12, 18, 14],\r\n * borderColor: \"red\",\r\n * backgroundColor: \"transparent\",\r\n * type: \"line\",\r\n * order: 0,\r\n * borderWidth: 3,\r\n * tension: 0.4,\r\n * pointRadius: 4,\r\n * fill: false,\r\n * },\r\n * ]}\r\n * height={400}\r\n * />\r\n * ```\r\n */\r\nexport default function BarChart({ labels, datasets, height }: Props) {\r\n const options = {\r\n responsive: true,\r\n maintainAspectRatio: false,\r\n scales: {\r\n y: {\r\n ticks: {\r\n font: {\r\n family: \"'Vazir', sans-serif\",\r\n size: 14,\r\n },\r\n },\r\n },\r\n x: {\r\n ticks: {\r\n autoSkip: false,\r\n font: {\r\n family: \"'Vazir', sans-serif\",\r\n size: 13,\r\n },\r\n },\r\n },\r\n },\r\n plugins: {\r\n datalabels: {\r\n display: false, // ← غیرفعال\r\n },\r\n tooltip: {\r\n bodyFont: {\r\n family: \"'Vazir', sans-serif\",\r\n size: 14,\r\n },\r\n titleFont: {\r\n family: \"'Vazir', sans-serif\",\r\n size: 16,\r\n },\r\n },\r\n legend: {\r\n labels: {\r\n generateLabels: function (chart: ChartType) {\r\n const labels =\r\n ChartJS.defaults.plugins.legend.labels.generateLabels(chart);\r\n return labels.map((label) => ({\r\n ...label,\r\n text: \" \" + label.text + \" \",\r\n boxWidth: 40,\r\n boxHeight: 20,\r\n }));\r\n },\r\n padding: 15,\r\n usePointStyle: true,\r\n font: {\r\n size: 16,\r\n family: \"'Vazir', sans-serif\",\r\n },\r\n boxWidth: 40,\r\n paddingBottom: 10,\r\n },\r\n },\r\n },\r\n };\r\n\r\n return (\r\n <Box height={height ?? 600}>\r\n <Chart type=\"bar\" data={{ labels, datasets }} options={options} />\r\n </Box>\r\n );\r\n}\r\n","'use client'\nimport { Pie } from \"react-chartjs-2\";\nimport { Chart as ChartJS, ArcElement, Tooltip, Legend, Chart } from \"chart.js\";\nimport { useMemo } from \"react\";\nimport { Box } from \"@mui/material\";\nimport Image from \"next/image\";\nimport ChartDataLabels from \"chartjs-plugin-datalabels\";\n\nChartJS.register(ArcElement, Tooltip, Legend, ChartDataLabels);\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 options = {\n responsive: true,\n maintainAspectRatio: false,\n cutout: !disableLogo ? \"59%\" : \"0%\",\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: (context: any) => {\n return showDataLabels && !context.chart.getDatasetMeta(context.datasetIndex).data[context.dataIndex].hidden;\n },\n color: \"#fff\",\n font: {\n size: 14,\n weight: \"bold\",\n family: \"'Vazir', sans-serif\",\n } as const,\n anchor: \"center\" as const, // ← روی مرکز هر تکه\n align: \"center\" as const,\n offset: 20, // فاصله از مرکز (میتونی کم/زیاد کنی)\n formatter: showPercentage\n ? (value: number, context: any) => {\n if (value === 0) return \"\";\n // محاسبه مجموع دادههای قابل مشاهده\n const total = context.chart.data.datasets[context.datasetIndex].data.reduce(\n (sum: number, val: number, index: number) => {\n const meta = context.chart.getDatasetMeta(context.datasetIndex);\n if (!meta.data[index] || meta.data[index].hidden !== true) {\n return sum + val;\n }\n return sum;\n },\n 0\n );\n const percentage = ((value / total) * 100).toFixed(1);\n return percentage + \"%\";\n }\n : (value: number) => (value === 0 ? \"\" : value),\n },\n },\n };\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 height={height ?? 600} sx={{ position: \"relative\" }}>\n <Pie\n data={{\n labels: labels,\n datasets: datasets,\n }}\n options={options}\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":["labels","ChartJS","Tooltip","Legend","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\";\r\nimport { Chart } from \"react-chartjs-2\";\r\nimport {\r\n Chart as ChartJS,\r\n CategoryScale,\r\n LinearScale,\r\n LogarithmicScale,\r\n BarElement,\r\n LineElement,\r\n PointElement,\r\n Tooltip,\r\n Legend,\r\n BarController,\r\n LineController,\r\n Chart as ChartType,\r\n} from \"chart.js\";\r\nimport { Box } from \"@mui/material\";\r\nimport { useRef, useEffect, useState } from \"react\";\r\n\r\nChartJS.register(\r\n CategoryScale,\r\n LinearScale,\r\n LogarithmicScale,\r\n BarElement,\r\n LineElement,\r\n PointElement,\r\n Tooltip,\r\n Legend,\r\n BarController,\r\n LineController\r\n);\r\n\r\n// تنظیم فونت پیشفرض Chart.js به Vazir\r\nChartJS.defaults.font.family = \"Vazir, sans-serif\";\r\n\r\ninterface Props {\r\n labels: string[];\r\n datasets: {\r\n label: string;\r\n data: (number | null)[];\r\n backgroundColor: string;\r\n borderColor?: string;\r\n borderWidth?: number;\r\n type?: \"line\";\r\n order?: number;\r\n tension?: number;\r\n pointRadius?: number;\r\n fill?: boolean;\r\n }[];\r\n height?: number;\r\n /**\r\n * حداقل مقدار محور Y (اختیاری)\r\n * اگر ست نشود، Chart.js خودش محاسبه میکند\r\n * ⚠️ نکته: اگر این مقدار ست شود، beginAtZero نادیده گرفته میشود\r\n */\r\n yAxisMin?: number;\r\n /**\r\n * حداکثر مقدار محور Y (اختیاری)\r\n * اگر ست نشود، Chart.js خودش محاسبه میکند\r\n */\r\n yAxisMax?: number;\r\n /**\r\n * آیا محور Y از صفر شروع شود؟\r\n * پیشفرض: true\r\n * ⚠️ نکته: اگر yAxisMin ست شود، این گزینه نادیده گرفته میشود\r\n */\r\n beginAtZero?: boolean;\r\n /**\r\n * استفاده از مقیاس لگاریتمی برای محور Y\r\n * مناسب برای دادههایی که اختلاف خیلی زیادی دارند\r\n * پیشفرض: false\r\n * ⚠️ نکته: مقادیر 0 یا منفی در مقیاس لگاریتمی نمایش داده نمیشوند\r\n */\r\n logarithmic?: boolean;\r\n /**\r\n * حداقل ارتفاع میله برای دادههای خیلی کوچک (پیکسل)\r\n * مقادیر خیلی کوچک (مثل 1) در کنار مقادیر بزرگ (مثل 10000) گم نمیشوند\r\n * پیشفرض: 0 (غیرفعال)\r\n */\r\n minBarLength?: number;\r\n}\r\n/**\r\n * 📊 BarChart — کامپوننت نمودار میلهای (Bar/Combo)\r\n *\r\n * @component BarChart\r\n *\r\n * @param {string[]} labels - آرایهای از برچسبها برای محور افقی (X).\r\n * @param {Array<{\r\n * label: string,\r\n * data: number[],\r\n * backgroundColor: string,\r\n * borderColor?: string,\r\n * borderWidth?: number,\r\n * type?: \"line\",\r\n * order?: number,\r\n * tension?: number,\r\n * pointRadius?: number,\r\n * fill?: boolean\r\n * }>} datasets - آرایهای از آبجکتهای داده برای هر سری نمودار.\r\n * - label: عنوان دادهها (نمایش در legend)\r\n * - data: آرایهای از مقادیر هر سری\r\n * - backgroundColor: رنگ میله یا خط\r\n * - borderColor: (اختیاری) رنگ خط دور میله یا خط\r\n * - borderWidth: (اختیاری) ضخامت خط دور میله یا خط\r\n * - type: (اختیاری) اگر \"line\" باشد، سری به صورت خطی نمایش داده میشود (نمودار ترکیبی)\r\n * - order: (اختیاری) ترتیب رسم سری (سری با order بالاتر روی بقیه قرار میگیرد)\r\n * - tension: (اختیاری) میزان خمیدگی خط (برای سریهای خطی)\r\n * - pointRadius: (اختیاری) شعاع نقاط روی خط (برای سریهای خطی)\r\n * - fill: (اختیاری) پر شدن زیر خط (برای سریهای خطی)\r\n *\r\n * @param {number} [height] - ارتفاع نمودار (پیشفرض: 600 پیکسل)\r\n * @param {number} [yAxisMin] - حداقل مقدار محور Y (نادیدهگرفتن beginAtZero)\r\n * @param {number} [yAxisMax] - حداکثر مقدار محور Y\r\n * @param {boolean} [beginAtZero=true] - آیا محور Y از صفر شروع شود؟ (اگر yAxisMin ست شود نادیده گرفته میشود)\r\n * @param {boolean} [logarithmic=false] - استفاده از مقیاس لگاریتمی (مقادیر 0 یا منفی نمایش داده نمیشوند)\r\n * @param {number} [minBarLength=0] - حداقل ارتفاع میله (پیکسل) - برای جلوگیری از گم شدن دادههای کوچک\r\n *\r\n * @description\r\n * این کامپوننت یک نمودار میلهای (Bar) یا ترکیبی Bar/Line با قابلیت شخصیسازی کامل است.\r\n * - پشتیبانی از فونت وزیر و راستچین\r\n * - ریسپانسیو و مناسب صفحات فارسی\r\n * - امکان نمایش چند سری داده به صورت میلهای و خطی همزمان (Combo)\r\n * - شخصیسازی رنگ، ضخامت، ترتیب و استایل هر سری\r\n * - پشتیبانی از مقیاس لگاریتمی برای دادههای با اختلاف زیاد\r\n * - minBarLength برای نمایش دادههای خیلی کوچک در کنار بزرگها\r\n *\r\n * @returns {JSX.Element} یک نمودار میلهای یا ترکیبی با دادههای ورودی\r\n *\r\n * @example\r\n * ```jsx\r\n * // نمودار ساده\r\n * <BarChart\r\n * labels={[\"شنبه\", \"یکشنبه\", \"دوشنبه\"]}\r\n * datasets={[\r\n * {\r\n * label: \"فروش\",\r\n * data: [10, 20, 15],\r\n * backgroundColor: \"rgba(75,192,192,0.7)\",\r\n * },\r\n * ]}\r\n * height={400}\r\n * />\r\n *\r\n * // نمودار با دادههای اختلاف زیاد (مقیاس لگاریتمی)\r\n * <BarChart\r\n * labels={[\"A\", \"B\", \"C\", \"D\"]}\r\n * datasets={[\r\n * {\r\n * label: \"مقادیر\",\r\n * data: [5, 50, 5000, 50000],\r\n * backgroundColor: \"rgba(75,192,192,0.7)\",\r\n * },\r\n * ]}\r\n * logarithmic={true}\r\n * height={400}\r\n * />\r\n *\r\n * // نمودار با کنترل دستی بازه محور Y\r\n * <BarChart\r\n * labels={[\"A\", \"B\", \"C\"]}\r\n * datasets={[\r\n * {\r\n * label: \"مقادیر\",\r\n * data: [100, 150, 120],\r\n * backgroundColor: \"rgba(75,192,192,0.7)\",\r\n * },\r\n * ]}\r\n * yAxisMin={80}\r\n * yAxisMax={200}\r\n * beginAtZero={false}\r\n * height={400}\r\n * />\r\n * ```\r\n */\r\nexport default function BarChart({\r\n labels,\r\n datasets,\r\n height,\r\n yAxisMin,\r\n yAxisMax,\r\n beginAtZero = true,\r\n logarithmic = false,\r\n minBarLength = 0,\r\n}: Props) {\r\n const chartRef = useRef<ChartJS>(null);\r\n const [fontLoaded, setFontLoaded] = useState(false);\r\n\r\n // صبر برای لود شدن فونت Vazir و سپس آپدیت chart\r\n useEffect(() => {\r\n let isMounted = true;\r\n\r\n const loadFont = async () => {\r\n if (typeof document !== \"undefined\" && document.fonts) {\r\n try {\r\n // منتظر لود شدن فونت Vazir به صورت مستقیم\r\n await document.fonts.load(\"16px Vazir\");\r\n await document.fonts.ready;\r\n } catch (e) {\r\n // اگر فونت پیدا نشد، ادامه بده\r\n }\r\n\r\n if (isMounted) {\r\n setFontLoaded(true);\r\n // آپدیت chart بعد از لود فونت\r\n setTimeout(() => {\r\n if (chartRef.current) {\r\n chartRef.current.update();\r\n }\r\n }, 100);\r\n }\r\n } else {\r\n if (isMounted) setFontLoaded(true);\r\n }\r\n };\r\n\r\n loadFont();\r\n\r\n return () => { isMounted = false; };\r\n }, []);\r\n\r\n // محاسبه min/max فقط بر اساس دادههای visible\r\n const getVisibleData = (): number[] => {\r\n if (!chartRef.current) return [];\r\n // فقط سریهایی که visible هستند و نوعشان bar است\r\n return datasets.reduce((acc: number[], ds, i) => {\r\n // اگر سری فعال است و نوعش bar است\r\n // @ts-ignore\r\n if ((ds.type === undefined || ds.type === \"bar\") && chartRef.current && typeof chartRef.current.isDatasetVisible === \"function\" && chartRef.current.isDatasetVisible(i)) {\r\n ds.data.forEach((v: number | null) => {\r\n if (typeof v === \"number\" && v > 0) acc.push(v);\r\n });\r\n }\r\n return acc;\r\n }, []);\r\n };\r\n\r\n let autoMin = yAxisMin;\r\n let autoMax = yAxisMax;\r\n if (logarithmic && yAxisMin === undefined && yAxisMax === undefined) {\r\n const visibleData = getVisibleData();\r\n if (visibleData.length) {\r\n const minVal = Math.min(...visibleData);\r\n const maxVal = Math.max(...visibleData);\r\n autoMin = minVal < 1 ? 0.5 : minVal * 0.7;\r\n autoMax = minVal === maxVal ? maxVal * 1.2 : maxVal * 1.1;\r\n }\r\n }\r\n\r\n // هر بار که legend تغییر کند، نمودار را آپدیت کن تا min/max درست شود\r\n useEffect(() => {\r\n if (!logarithmic || yAxisMin !== undefined || yAxisMax !== undefined) return;\r\n if (!chartRef.current) return;\r\n const handler = () => {\r\n // آپدیت min/max و نمودار\r\n const visibleData = getVisibleData();\r\n if (visibleData.length && chartRef.current && chartRef.current.options && chartRef.current.options.scales && chartRef.current.options.scales.y) {\r\n const minVal = Math.min(...visibleData);\r\n const maxVal = Math.max(...visibleData);\r\n chartRef.current.options.scales.y.min = minVal < 1 ? 0.5 : minVal * 0.7;\r\n chartRef.current.options.scales.y.max = minVal === maxVal ? maxVal * 1.2 : maxVal * 1.1;\r\n chartRef.current.update();\r\n }\r\n };\r\n // گوش دادن به event legend\r\n chartRef.current?.canvas?.addEventListener(\"click\", handler);\r\n return () => {\r\n chartRef.current?.canvas?.removeEventListener(\"click\", handler);\r\n };\r\n }, [logarithmic, yAxisMin, yAxisMax, datasets]);\r\n\r\n const options = {\r\n responsive: true,\r\n maintainAspectRatio: false,\r\n scales: {\r\n y: {\r\n type: logarithmic ? (\"logarithmic\" as const) : (\"linear\" as const),\r\n ...(yAxisMin === undefined && yAxisMax === undefined && !logarithmic && {\r\n beginAtZero: beginAtZero,\r\n }),\r\n ...(autoMin !== undefined && { min: autoMin }),\r\n ...(autoMax !== undefined && { max: autoMax }),\r\n ticks: {\r\n font: {\r\n family: \"Vazir, sans-serif\",\r\n size: 14,\r\n },\r\n ...(logarithmic && {\r\n callback: function (value: number | string) {\r\n const numValue = Number(value);\r\n // فقط توانهای ۱۰ را نمایش بده\r\n if (numValue === 0) return null;\r\n const log10 = Math.log10(numValue);\r\n if (Math.abs(log10 - Math.round(log10)) < 0.0001) {\r\n if (numValue >= 1000000) return (numValue / 1000000).toFixed(1) + \"M\";\r\n if (numValue >= 1000) return (numValue / 1000).toFixed(1) + \"K\";\r\n return numValue;\r\n }\r\n return null;\r\n },\r\n }),\r\n },\r\n },\r\n x: {\r\n ticks: {\r\n autoSkip: false,\r\n font: {\r\n family: \"Vazir, sans-serif\",\r\n size: 13,\r\n },\r\n },\r\n },\r\n },\r\n plugins: {\r\n datalabels: {\r\n display: false, // ← غیرفعال\r\n },\r\n tooltip: {\r\n bodyFont: {\r\n family: \"Vazir, sans-serif\",\r\n size: 14,\r\n },\r\n titleFont: {\r\n family: \"Vazir, sans-serif\",\r\n size: 16,\r\n },\r\n },\r\n legend: {\r\n labels: {\r\n generateLabels: function (chart: ChartType) {\r\n const labels =\r\n ChartJS.defaults.plugins.legend.labels.generateLabels(chart);\r\n return labels.map((label) => ({\r\n ...label,\r\n text: \" \" + label.text + \" \",\r\n boxWidth: 40,\r\n boxHeight: 20,\r\n }));\r\n },\r\n padding: 15,\r\n usePointStyle: true,\r\n font: {\r\n size: 16,\r\n family: \"Vazir, sans-serif\",\r\n },\r\n boxWidth: 40,\r\n paddingBottom: 10,\r\n },\r\n },\r\n },\r\n };\r\n\r\n // اضافه کردن minBarLength به همه datasets\r\n const processedDatasets = datasets.map((ds) => ({\r\n ...ds,\r\n minBarLength: minBarLength,\r\n }));\r\n\r\n return (\r\n <Box height={height ?? 600}>\r\n {fontLoaded && (\r\n <Chart ref={chartRef} type=\"bar\" data={{ labels, datasets: processedDatasets }} options={options} />\r\n )}\r\n </Box>\r\n );\r\n}\r\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":["labels","ChartJS","Tooltip","Legend","useRef","useEffect","useState","Box"]}
|
|
@@ -55,6 +55,7 @@ import { Moment } from 'moment-jalaali';
|
|
|
55
55
|
* dualCalendar={false} // جدید: کنترل تقویم دوم
|
|
56
56
|
* singleCalendar={false}
|
|
57
57
|
* useMobilePickers={false}
|
|
58
|
+
* disableSmartTabs={false}
|
|
58
59
|
* />
|
|
59
60
|
* );
|
|
60
61
|
* };
|
|
@@ -116,6 +117,16 @@ import { Moment } from 'moment-jalaali';
|
|
|
116
117
|
* />
|
|
117
118
|
* ```
|
|
118
119
|
*
|
|
120
|
+
* 6. پنهان کردن تبهای هوشمند (بدون تغییر عملکرد):
|
|
121
|
+
* ```tsx
|
|
122
|
+
* <DateRangePicker
|
|
123
|
+
* fromDate="from"
|
|
124
|
+
* toDate="to"
|
|
125
|
+
* control={control}
|
|
126
|
+
* disableSmartTabs={true}
|
|
127
|
+
* />
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
119
130
|
* ویژگیهای تبهای هوشمند (جدید در v3.0):
|
|
120
131
|
*
|
|
121
132
|
* ```tsx
|
|
@@ -242,6 +253,7 @@ interface DateRangePickerProps {
|
|
|
242
253
|
singleCalendar?: boolean;
|
|
243
254
|
useMobilePickers?: boolean;
|
|
244
255
|
dualCalendar?: boolean;
|
|
256
|
+
disableSmartTabs?: boolean;
|
|
245
257
|
variant?: TextFieldVariants;
|
|
246
258
|
placeholder?: string;
|
|
247
259
|
disableClearIcon?: boolean;
|
|
@@ -364,6 +376,7 @@ interface DateRangePickerProps {
|
|
|
364
376
|
* @property {boolean} [clear] - نمایش دکمه پاک کردن (پیشفرض: true)
|
|
365
377
|
* @property {boolean} [singleCalendar] - نمایش تک تقویم به جای دوتایی (پیشفرض: false)
|
|
366
378
|
* @property {boolean} [useMobilePickers] - استفاده از DatePicker جداگانه به جای popup (پیشفرض: false)
|
|
379
|
+
* @property {boolean} [disableSmartTabs] - پنهان کردن تبهای هوشمند بدون تغییر عملکرد (پیشفرض: false)
|
|
367
380
|
*
|
|
368
381
|
* نکات مهم:
|
|
369
382
|
* - کامپوننت خودکار mobile detection دارد (breakpoint: 700px)
|