UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

1 lines 9.38 kB
{"version":3,"sources":["../src/components/SimpleBarChart/SimpleBarChart.tsx"],"sourcesContent":["import { type HTMLAttributes } from 'react';\nimport Text from '../Text/Text';\nimport { Tooltip } from '../Tooltip/Tooltip';\nimport { cn } from '../../utils/utils';\nimport { bgClassToCssVar } from '../../utils/chartUtils';\n\n/**\n * Data item for SimpleBarChart\n */\nexport interface SimpleBarChartDataItem {\n label: string;\n value: number;\n}\n\n/**\n * Props for the SimpleBarChart component\n */\nexport interface SimpleBarChartProps extends HTMLAttributes<HTMLDivElement> {\n /** Chart data with labels and values */\n data: SimpleBarChartDataItem[];\n /** Title for the chart card */\n title: string;\n /** Height of the bar chart area in pixels */\n chartHeight?: number;\n /** Tailwind bg- color class for the bars (e.g., \"bg-info-500\") */\n barColor?: string;\n}\n\n/**\n * Calculate Y-axis tick values for count display.\n * Rounds up to the nearest multiple of 4 so that dividing into 4 equal\n * intervals always produces integer ticks with uniform spacing.\n */\nconst calculateTicks = (maxValue: number): number[] => {\n if (maxValue <= 0) return [0];\n\n const niceMax = Math.ceil(maxValue / 4) * 4;\n const step = niceMax / 4;\n\n return [niceMax, step * 3, step * 2, step, 0];\n};\n\n// ─── Sub-components ──────────────────────────────────────────\n\nconst YAxis = ({\n ticks,\n chartHeight,\n}: {\n ticks: number[];\n chartHeight: number;\n}) => (\n <div\n className=\"flex flex-col justify-between items-end pr-3\"\n style={{ height: chartHeight }}\n aria-hidden=\"true\"\n >\n {ticks.map((tick, index) => (\n <Text\n key={`${tick}-${index}`}\n size=\"xs\"\n weight=\"medium\"\n className=\"text-text-500\"\n >\n {tick}\n </Text>\n ))}\n </div>\n);\n\nconst GridLines = ({\n ticks,\n chartHeight,\n}: {\n ticks: number[];\n chartHeight: number;\n}) => (\n <div\n className=\"absolute inset-0 flex flex-col justify-between pointer-events-none\"\n style={{ height: chartHeight }}\n >\n {ticks.map((tick, index) => (\n <div\n key={`grid-${tick}-${index}`}\n className=\"w-full border-t border-dashed border-border-200\"\n />\n ))}\n </div>\n);\n\nconst Bar = ({\n item,\n maxValue,\n chartHeight,\n barColor,\n}: {\n item: SimpleBarChartDataItem;\n maxValue: number;\n chartHeight: number;\n barColor: string;\n}) => {\n const barHeight = maxValue === 0 ? 0 : (item.value / maxValue) * chartHeight;\n\n const tooltipContent =\n item.value > 0 ? (\n <div className=\"flex items-center gap-2\">\n <div\n className=\"w-2 h-2 rounded-full shrink-0\"\n style={{ background: bgClassToCssVar(barColor) }}\n />\n <Text as=\"span\" size=\"xs\" weight=\"medium\" color=\"text-white\">\n {item.label}: {item.value}\n </Text>\n </div>\n ) : null;\n\n return (\n <Tooltip\n content={tooltipContent ?? ''}\n disabled={!tooltipContent}\n position=\"top\"\n className=\"flex-1\"\n contentClassName=\"whitespace-normal\"\n >\n <div className=\"flex flex-col items-center gap-2 w-full cursor-pointer group/bar\">\n <div\n className=\"w-full flex flex-col-reverse items-center justify-start relative\"\n style={{ height: chartHeight }}\n >\n {barHeight > 0 && (\n <div\n data-testid={`bar-${item.label}`}\n className={cn('w-8 rounded-md', barColor)}\n style={{ height: `${barHeight}px` }}\n aria-label={`${item.label}: ${item.value}`}\n />\n )}\n {item.value > 0 && (\n <div className=\"absolute inset-0 bg-white/50 opacity-0 group-hover/bar:opacity-100 transition-opacity duration-200 rounded-md pointer-events-none z-20\" />\n )}\n </div>\n <Text\n size=\"xs\"\n weight=\"medium\"\n className=\"text-text-600 text-center\"\n data-testid={`label-${item.label}`}\n >\n {item.label}\n </Text>\n </div>\n </Tooltip>\n );\n};\n\n// ─── Main component ──────────────────────────────────────────\n\n/**\n * SimpleBarChart component - displays a simple bar chart (non-stacked, single color)\n *\n * @example\n * ```tsx\n * <SimpleBarChart\n * data={[\n * { label: 'SEG', value: 150 },\n * { label: 'TER', value: 200 },\n * { label: 'QUA', value: 100 },\n * ]}\n * title=\"Quantidade de acessos por periodo\"\n * barColor=\"bg-info-500\"\n * />\n * ```\n */\nexport const SimpleBarChart = ({\n data,\n title,\n chartHeight = 180,\n barColor = 'bg-info-500',\n className,\n ...props\n}: SimpleBarChartProps) => {\n const maxValue = Math.max(...data.map((item) => item.value), 0);\n const yAxisTicks = calculateTicks(maxValue);\n const adjustedMax = yAxisTicks[0];\n\n return (\n <div\n className={cn(\n 'flex flex-col p-5 gap-4 bg-background border border-border-50 rounded-xl',\n className\n )}\n aria-label={title}\n {...props}\n >\n <Text\n as=\"h3\"\n size=\"lg\"\n weight=\"bold\"\n className=\"text-text-950 tracking-[0.2px]\"\n >\n {title}\n </Text>\n <div className=\"flex flex-row\">\n <YAxis ticks={yAxisTicks} chartHeight={chartHeight} />\n <div className=\"w-4\" />\n <div className=\"flex-1 relative\">\n <GridLines ticks={yAxisTicks} chartHeight={chartHeight} />\n <div className=\"flex flex-row flex-1 gap-2 relative z-10\">\n {data.map((item, index) => (\n // Equal-width column wrapper: keeps every bucket the same width even\n // when a bar's value is 0 (its Tooltip is disabled and would\n // otherwise drop the flex-1 class, collapsing the column).\n <div\n key={`${item.label}-${index}`}\n className=\"flex-1 flex min-w-0\"\n >\n <Bar\n item={item}\n maxValue={adjustedMax}\n chartHeight={chartHeight}\n barColor={barColor}\n />\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default SimpleBarChart;\n"],"mappings":"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","names":[]}