// Copyright 2017-2025 @pezkuwi/react-components authors & contributors // SPDX-License-Identifier: Apache-2.0 import type { ChartData, ChartOptions, TooltipItem } from 'chart.js'; import type { BN } from '@pezkuwi/util'; import React, { useEffect, useState } from 'react'; import { Bar } from 'react-chartjs-2'; import { bnToBn, isNumber } from '@pezkuwi/util'; import { alphaColor } from './utils.js'; interface Value { colors: string[]; label: string; tooltip?: string; value: number | BN; } export interface Props { aspectRatio?: number; className?: string; max?: number; showLabels?: boolean; values: Value[]; withColors?: boolean; } interface State { chartData?: ChartData; chartOptions?: ChartOptions; jsonValues?: string; } interface Config { labels: string[]; datasets: { data: number[]; backgroundColor: string[]; hoverBackgroundColor: string[]; }[]; } function calculateOptions (aspectRatio: number, values: Value[], jsonValues: string, max: number, showLabels: boolean): State { const chartData = values.reduce((data, { colors: [normalColor = '#00f', hoverColor], label, value }): Config => { const dataset = data.datasets[0]; dataset.backgroundColor.push(alphaColor(normalColor)); dataset.hoverBackgroundColor.push(alphaColor(hoverColor || normalColor)); dataset.data.push(isNumber(value) ? value : bnToBn(value).toNumber()); data.labels.push(label); return data; }, { datasets: [{ backgroundColor: [] as string[], data: [] as number[], hoverBackgroundColor: [] as string[] }], labels: [] as string[] }); return { chartData, chartOptions: { aspectRatio, plugins: { legend: { display: false }, tooltip: { callbacks: { label: (item: TooltipItem): string => values[item.dataIndex].tooltip || values[item.dataIndex].label } } }, scales: { x: showLabels ? { beginAtZero: true, max } : { display: false } } }, jsonValues }; } function ChartHorizBar ({ aspectRatio = 8, className = '', max = 100, showLabels = false, values }: Props): React.ReactElement | null { const [{ chartData, chartOptions, jsonValues }, setState] = useState({}); useEffect((): void => { const newJsonValues = JSON.stringify(values); if (newJsonValues !== jsonValues) { setState(calculateOptions(aspectRatio, values, newJsonValues, max, showLabels)); } }, [aspectRatio, jsonValues, max, showLabels, values]); if (!chartData) { return null; } // HACK on width/height to get the aspectRatio to work return (
); } export default React.memo(ChartHorizBar);