add scales

This commit is contained in:
Nate Kelley 2025-04-18 13:12:55 -06:00
parent 67ec530a5a
commit 0a43738992
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
3 changed files with 89 additions and 7 deletions

View File

@ -20,7 +20,8 @@ import {
BubbleController,
PieController,
ScatterController,
DoughnutController
DoughnutController,
registry
} from 'chart.js';
import { ChartMountedPlugin } from './core/plugins';
import ChartDeferred from 'chartjs-plugin-deferred';
@ -31,6 +32,11 @@ import { isServer } from '@tanstack/react-query';
import './core/plugins/chartjs-plugin-dayjs';
import { truncateText } from '@/lib/text';
import { DeduplicatedTimeScale } from './core/plugins/chartjs-plugin-tick-duplicate';
// Register the scale properly
registry.addScales(DeduplicatedTimeScale);
const fontFamily = isServer
? 'Roobert_Pro'
: getComputedStyle(document.documentElement).getPropertyValue('--font-sans');

View File

@ -1,10 +1,25 @@
import { ChartType, Chart, Plugin } from 'chart.js';
import { ChartType, TimeScale } from 'chart.js';
declare module 'chart.js' {
interface PluginOptionsByType<TType extends ChartType> {}
}
import { TimeScale } from 'chart.js';
// Add interface extension for TimeScale
interface TimeScale {
_unit:
| 'millisecond'
| 'second'
| 'minute'
| 'hour'
| 'day'
| 'week'
| 'month'
| 'year'
| 'quarter';
_adapter: {
format(time: unknown, format: string): string;
};
}
}
const originalBuildTicks = TimeScale.prototype.buildTicks;
@ -12,6 +27,7 @@ const originalBuildTicks = TimeScale.prototype.buildTicks;
TimeScale.prototype.buildTicks = function () {
// Step 1: Get default ticks using the original method
const defaultTicks = originalBuildTicks.call(this);
console.log('defaultTicks', defaultTicks);
// Step 2: Access tick callback and display format
const tickCallback = this.options.ticks?.callback;
@ -57,3 +73,64 @@ TimeScale.prototype.buildTicks = function () {
// Step 6: Return the filtered ticks
return uniqueTicks;
};
export class DeduplicatedTimeScale extends TimeScale {
static id = 'deduplicated-time';
static defaults = TimeScale.defaults;
/**
* Override buildTicks to eliminate duplicate ticks based on formatted values.
* @returns {Array} Array of unique tick objects
*/
buildTicks() {
console.log('buildTicks');
// Step 1: Get default ticks from parent TimeScale
const defaultTicks = super.buildTicks();
// Step 2: Access tick callback and display format
const tickCallback = this.options.ticks?.callback;
const displayFormat =
this.options.time?.displayFormats?.[this._unit] ||
this.options.time?.displayFormats?.month ||
'MMM';
const format = this._adapter.format.bind(this._adapter);
// Step 3: Track seen labels and collect unique ticks
const seen = new Set();
const uniqueTicks = [];
for (let i = 0; i < defaultTicks.length; i++) {
const tick = defaultTicks[i];
// Step 4: Generate tick label
let label;
try {
if (typeof tickCallback === 'function') {
// Pass tick value, index, and ticks array to callback
label = tickCallback.call(this, tick.value, i, defaultTicks);
} else {
// Format using the adapter with the appropriate display format
label = format(tick.value, displayFormat);
}
} catch (e) {
console.error('Tick callback error at index', i, e);
label = '???';
}
// Ensure label is a string for consistent comparison
const stringLabel = String(label ?? '');
// Step 5: Only include tick if label is unique
if (!seen.has(stringLabel)) {
seen.add(stringLabel);
uniqueTicks.push({
...tick,
label: stringLabel // Ensure the tick object has the correct label
});
}
}
// Step 6: Return the filtered ticks
return uniqueTicks;
}
}

View File

@ -10,7 +10,7 @@ import {
import { useMemoizedFn } from '@/hooks';
import { useMemo } from 'react';
import { DeepPartial } from 'utility-types';
import type { ScaleChartOptions, Scale, GridLineOptions } from 'chart.js';
import type { ScaleChartOptions, Scale, GridLineOptions, TimeScale } from 'chart.js';
import { useXAxisTitle } from '../../../../commonHelpers/useXAxisTitle';
import { useIsStacked } from '../useIsStacked';
import { formatLabel, isNumericColumnType, truncateText } from '@/lib';
@ -145,8 +145,7 @@ export const useXAxis = ({
const xColumnLabelFormat = xAxisColumnFormats[xKey];
const isAutoFormat = xColumnLabelFormat.dateFormat === 'auto';
if (isAutoFormat) {
//@ts-ignore
const unit = this.chart.scales['x']._unit as
const unit = (this.chart.scales['x'] as TimeScale)._unit as
| 'millisecond'
| 'second'
| 'minute'