update chart theme and ticker

This commit is contained in:
Nate Kelley 2025-04-18 14:42:15 -06:00
parent 27aed66397
commit e54194d018
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
4 changed files with 52 additions and 90 deletions

View File

@ -32,10 +32,9 @@ import { isServer } from '@tanstack/react-query';
import './core/plugins/chartjs-plugin-dayjs';
import { truncateText } from '@/lib/text';
import { DeduplicatedTimeScale } from './core/plugins/chartjs-scale-tick-duplicate';
import './core/plugins/chartjs-scale-tick-duplicate';
// Register the scale properly
registry.addScales(DeduplicatedTimeScale);
const fontFamily = isServer
? 'Roobert_Pro'

View File

@ -23,13 +23,12 @@ declare module 'chart.js' {
const originalBuildTicks = TimeScale.prototype.buildTicks;
// Override buildTicks
// // Override buildTicks
TimeScale.prototype.buildTicks = function () {
// Step 1: Get default ticks using the original method
// Generate default ticks
const defaultTicks = originalBuildTicks.call(this);
console.log('defaultTicks', defaultTicks);
// Step 2: Access tick callback and display format
// Access tick callback and display format
const tickCallback = this.options.ticks?.callback;
const displayFormat =
this.options.time?.displayFormats?.[this._unit] ||
@ -37,30 +36,17 @@ TimeScale.prototype.buildTicks = function () {
'MMM';
const format = this._adapter.format.bind(this._adapter);
// Step 3: Track seen labels and collect unique ticks
// Deduplicate 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') {
label = tickCallback.call(this, tick.value, i, defaultTicks);
} else {
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
let label = tickCallback
? tickCallback.call(this, tick.value, i, defaultTicks)
: format(tick.value, displayFormat);
const stringLabel = String(label ?? '');
// Step 5: Only include tick if label is unique
if (!seen.has(stringLabel)) {
seen.add(stringLabel);
uniqueTicks.push({
@ -70,67 +56,8 @@ TimeScale.prototype.buildTicks = function () {
}
}
// Step 6: Return the filtered ticks
// Set the filtered ticks on the axis instance
this.ticks = uniqueTicks;
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

@ -155,8 +155,8 @@ export const useXAxis = ({
| 'month'
| 'quarter'
| 'year';
console.log('selected unit', unit);
const format = DATE_FORMATS[unit];
console.log('auto unit?', { unit, format });
return formatLabel(rawValue, { ...xColumnLabelFormat, dateFormat: format });
}
const res = formatLabel(rawValue, xColumnLabelFormat);
@ -201,8 +201,6 @@ export const useXAxis = ({
return derivedTimeUnit;
}, [type, derivedTimeUnit, xAxisTimeInterval]);
console.log('timeUnit', { timeUnit, derivedTimeUnit });
const offset = useMemo(() => {
if (isScatterChart) return false;
if (isLineChart) return lineGroupType !== 'percentage-stack';
@ -212,7 +210,7 @@ export const useXAxis = ({
const memoizedXAxisOptions: DeepPartial<ScaleChartOptions<'bar'>['scales']['x']> | undefined =
useMemo(() => {
if (isPieChart) return undefined;
console.log('type', { type, timeUnit });
console.log('type', { type, timeUnit, derivedTimeUnit });
return {
type,
offset,
@ -231,7 +229,7 @@ export const useXAxis = ({
enabled: false //test
},
autoSkip: false,
maxTicksLimit: type === 'time' ? (timeUnit === 'month' ? 11 : 18) : undefined,
maxTicksLimit: type === 'time' ? (timeUnit === 'month' ? 12 : 18) : undefined,
sampleSize: type === 'time' ? 24 : undefined,
display: xAxisShowAxisLabel,
callback: tickCallback as any, //I need to use null for auto date

View File

@ -377,6 +377,44 @@ export const FixedDateFormat_TimeIntervalTest_Days_WithAutoUnit_UnevenDays: Stor
}
};
export const XAxisTimeIntervalWithMismatchingData_Days: Story = {
args: {
...AutoDateFormat_TimeIntervalTest_MonthWithForcedUnit_ManyMonths.args,
xAxisTimeInterval: 'day',
data: Array.from({ length: 31 }, (_, i) => ({
date: dayjs('2024-01-01').add(i, 'day').toISOString(),
sales: addNoise(i * 15 + 55, 10)
})),
columnLabelFormats: {
...AutoDateFormat_TimeIntervalTest_MonthWithForcedUnit_ManyMonths.args!.columnLabelFormats,
date: {
columnType: 'date',
style: 'date',
dateFormat: 'MMM DD'
} satisfies IColumnLabelFormat
}
}
};
export const XAxisTimeIntervalWithMismatchingData_Months: Story = {
args: {
...AutoDateFormat_TimeIntervalTest_MonthWithForcedUnit_ManyMonths.args,
xAxisTimeInterval: 'month',
data: Array.from({ length: 14 }, (_, i) => ({
date: dayjs('2024-01-01').add(i, 'month').toISOString(),
sales: addNoise(i * 15 + 55, 10)
})),
columnLabelFormats: {
...AutoDateFormat_TimeIntervalTest_MonthWithForcedUnit_ManyMonths.args!.columnLabelFormats,
date: {
columnType: 'date',
style: 'date',
dateFormat: 'MMM DD'
} satisfies IColumnLabelFormat
}
}
};
// Simple X and Y axis with numeric values
export const NumericXY: Story = {
args: {