From 62783dff709c738d6d1e88f08f5db3a5b0e0d492 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Fri, 18 Apr 2025 12:02:08 -0600 Subject: [PATCH] Create chartjs-plugin-tick-duplicate.ts --- .../plugins/chartjs-plugin-tick-duplicate.ts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 web/src/components/ui/charts/BusterChartJS/core/plugins/chartjs-plugin-tick-duplicate.ts diff --git a/web/src/components/ui/charts/BusterChartJS/core/plugins/chartjs-plugin-tick-duplicate.ts b/web/src/components/ui/charts/BusterChartJS/core/plugins/chartjs-plugin-tick-duplicate.ts new file mode 100644 index 000000000..05fb4bba2 --- /dev/null +++ b/web/src/components/ui/charts/BusterChartJS/core/plugins/chartjs-plugin-tick-duplicate.ts @@ -0,0 +1,51 @@ +import { ChartType, Chart, Plugin } from 'chart.js'; + +declare module 'chart.js' { + interface PluginOptionsByType {} +} + +export const ChartJSTickDuplicatePlugin: Plugin = { + id: 'chartjs-plugin-tick-duplicate', + afterBuildTicks(chart) { + const scale = chart.scales['x']; + if (!scale || scale.type !== 'time') return; + + const adapter = scale._adapter; + const format = (v) => adapter.format(v, scale.options.time.displayFormats?.month || 'MMM'); + + const allTicks = scale._generate(); // Chart.js's default generated ticks (raw values) + const seenLabels = new Set(); + const unique = []; + + for (const tick of allTicks) { + const label = format(tick.value ?? tick); + if (!seenLabels.has(label)) { + seenLabels.add(label); + unique.push({ value: tick.value ?? tick, label }); + } + } + + if (unique.length < 2) return; + + const min = scale.min ?? Math.min(...allTicks.map((t) => t.value ?? t)); + const max = scale.max ?? Math.max(...allTicks.map((t) => t.value ?? t)); + const spacing = (max - min) / (unique.length - 1); + + const evenlySpaced = unique.map((tick, i) => ({ + value: min + i * spacing, + label: tick.label + })); + + scale.ticks = evenlySpaced; + }, + beforeDraw(chart) { + // Prevent Chart.js from auto-reformatting tick labels + const scale = chart.scales['x']; + if (!scale || !scale.ticks) return; + scale.ticks.forEach((tick) => { + tick.label = tick.label; + }); + } +}; + +export default ChartJSTickDuplicatePlugin;