You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
3.3 KiB
143 lines
3.3 KiB
import { Chart, TooltipPosition } from 'chart.js';
|
|
import { format } from 'date-fns';
|
|
|
|
import {
|
|
DATE_FORMAT,
|
|
DATE_FORMAT_MONTHLY,
|
|
DATE_FORMAT_YEARLY,
|
|
getBackgroundColor,
|
|
getLocale,
|
|
getTextColor
|
|
} from './helper';
|
|
import { ColorScheme, GroupBy } from './types';
|
|
|
|
export function formatGroupedDate({
|
|
date,
|
|
groupBy
|
|
}: {
|
|
date: Date;
|
|
groupBy: GroupBy;
|
|
}) {
|
|
if (groupBy === 'month') {
|
|
return format(date, DATE_FORMAT_MONTHLY);
|
|
} else if (groupBy === 'year') {
|
|
return format(date, DATE_FORMAT_YEARLY);
|
|
}
|
|
|
|
return format(date, DATE_FORMAT);
|
|
}
|
|
|
|
export function getTooltipOptions({
|
|
colorScheme,
|
|
currency = '',
|
|
groupBy,
|
|
locale = getLocale(),
|
|
unit = ''
|
|
}: {
|
|
colorScheme?: ColorScheme;
|
|
currency?: string;
|
|
groupBy?: GroupBy;
|
|
locale?: string;
|
|
unit?: string;
|
|
} = {}) {
|
|
return {
|
|
backgroundColor: getBackgroundColor(colorScheme),
|
|
bodyColor: `rgb(${getTextColor(colorScheme)})`,
|
|
borderWidth: 1,
|
|
borderColor: `rgba(${getTextColor(colorScheme)}, 0.1)`,
|
|
callbacks: {
|
|
label: (context) => {
|
|
let label = context.dataset.label || '';
|
|
if (label) {
|
|
label += ': ';
|
|
}
|
|
if (context.parsed.y !== null) {
|
|
if (currency) {
|
|
label += `${context.parsed.y.toLocaleString(locale, {
|
|
maximumFractionDigits: 2,
|
|
minimumFractionDigits: 2
|
|
})} ${currency}`;
|
|
} else if (unit) {
|
|
label += `${context.parsed.y.toFixed(2)} ${unit}`;
|
|
} else {
|
|
label += context.parsed.y.toFixed(2);
|
|
}
|
|
}
|
|
return label;
|
|
},
|
|
title: (contexts) => {
|
|
if (groupBy) {
|
|
return formatGroupedDate({ groupBy, date: contexts[0].parsed.x });
|
|
}
|
|
|
|
return contexts[0].label;
|
|
}
|
|
},
|
|
caretSize: 0,
|
|
cornerRadius: 2,
|
|
footerColor: `rgb(${getTextColor(colorScheme)})`,
|
|
itemSort: (a, b) => {
|
|
// Reverse order
|
|
return b.datasetIndex - a.datasetIndex;
|
|
},
|
|
titleColor: `rgb(${getTextColor(colorScheme)})`,
|
|
usePointStyle: true
|
|
};
|
|
}
|
|
|
|
export function getTooltipPositionerMapTop(
|
|
chart: Chart,
|
|
position: TooltipPosition
|
|
) {
|
|
if (!position || !chart?.chartArea) {
|
|
return false;
|
|
}
|
|
return {
|
|
x: position.x,
|
|
y: chart.chartArea.top
|
|
};
|
|
}
|
|
|
|
export function getVerticalHoverLinePlugin(
|
|
chartCanvas,
|
|
colorScheme?: ColorScheme
|
|
) {
|
|
return {
|
|
afterDatasetsDraw: (chart, x, options) => {
|
|
const active = chart.getActiveElements();
|
|
|
|
if (!active || active.length === 0) {
|
|
return;
|
|
}
|
|
|
|
const color = options.color || `rgb(${getTextColor(colorScheme)})`;
|
|
const width = options.width || 1;
|
|
|
|
const {
|
|
chartArea: { bottom, top }
|
|
} = chart;
|
|
const xValue = active[0].element.x;
|
|
|
|
const context = chartCanvas.nativeElement.getContext('2d');
|
|
context.lineWidth = width;
|
|
context.strokeStyle = color;
|
|
|
|
context.beginPath();
|
|
context.moveTo(xValue, top);
|
|
context.lineTo(xValue, bottom);
|
|
context.stroke();
|
|
},
|
|
id: 'verticalHoverLine'
|
|
};
|
|
}
|
|
|
|
export function transformTickToAbbreviation(value: number) {
|
|
if (value >= -999 && value <= 999) {
|
|
return value.toString();
|
|
} else if (value >= -999999 && value <= 999999) {
|
|
return `${value / 1000}K`;
|
|
} else {
|
|
return `${value / 1000000}M`;
|
|
}
|
|
}
|