@mozaic-ds/chart
Version:
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
174 lines (159 loc) • 5.01 kB
text/typescript
import { ref } from 'vue';
import type { Ref } from 'vue';
import { getHtmlLegendPlugin } from '@/services/ChartsCommonLegend';
import { formatWithThousandsSeprators } from '@/services/FormatUtilities';
import { addAlpha } from './ColorFunctions';
import { DoughnutData, DoughnutPlugin } from '@/types/DoughnutData';
export default function () {
const doughnutRef: Ref = ref(null);
const onHoverIndex: Ref<number | null> = ref(null);
const backgroundColor: Ref<CanvasPattern[] | null> = ref(null);
const centeredLabel: Ref = ref(null);
function privateGetHtmlLegendPlugin(
legendContainer: Ref,
selectMode: Ref<boolean>,
disableAccessibility: Ref<boolean>,
patternsColors: Ref<string[]>,
patternsList: Ref<
((
hover: boolean,
color: string,
disableAccessibility: boolean
) => CanvasPattern)[]
>,
maxValueToDisplay: number,
doughnutData: any,
enableHoverFeature: Ref<boolean>
) {
return getHtmlLegendPlugin(
legendContainer,
selectMode,
onHoverIndex,
disableAccessibility,
patternsColors,
patternsList,
enableHoverFeature,
maxValueToDisplay,
doughnutData
);
}
function getBackgroundColor(
patternsColors: string[],
patternsList: ((
hover: boolean,
color: string,
disableAccessibility: boolean
) => CanvasPattern)[],
disableAccessibility: boolean,
enableHoverFeature: boolean
) {
if (onHoverIndex.value !== null && enableHoverFeature) {
return patternsList.map((pattern, index) =>
onHoverIndex.value === index
? pattern(false, patternsColors[index], disableAccessibility)
: pattern(true, patternsColors[index], disableAccessibility)
);
} else {
return patternsList.map((pattern, index) =>
pattern(false, patternsColors[index], disableAccessibility)
);
}
}
function getBorderColor(
patternsColors: string[],
enableHoverFeature: boolean
): string[] {
if (onHoverIndex.value !== null && enableHoverFeature) {
return patternsColors.map((color, index) =>
onHoverIndex.value === index ? color : addAlpha(color, 0.2)
);
} else {
return patternsColors;
}
}
function getOnHoverOptions() {
return (_ignore: unknown, activeElements: Array<any>): void => {
if (activeElements[0] !== undefined) {
onHoverIndex.value = activeElements[0].element.$context.index;
} else {
onHoverIndex.value = null;
}
};
}
const getFormatedText = (str: string) => {
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
};
function getCenteredLabelPlugin(
doughnutData: DoughnutData[]
): DoughnutPlugin {
return {
id: 'centeredLabelPlugin',
afterDatasetDraw: (chart) => {
const selectedIndexes: Number[] = [];
const arcElements = chart.getDatasetMeta(0).data;
arcElements.forEach((arcElement: any, index: Number) => {
if (arcElement.startAngle !== arcElement.endAngle) {
selectedIndexes.push(index);
}
});
const total = (chart as any)._metasets[0]?._dataset?.raw_value
?.filter((_: any, index: Number) => selectedIndexes.includes(index))
.reduce((acc: number, currentValue: any) => acc + currentValue, 0);
const unit = doughnutData[0].unit ?? '';
centeredLabel.value = `${formatWithThousandsSeprators(total)}${unit}`;
}
};
}
function getDoughnutLabels(
labels: string[],
data: DoughnutData[],
maxValues: number,
othersLabel: string
) {
let truncatedLabels = labels.slice(0);
let truncatedData = data.slice(0);
if (labels.length > maxValues) {
truncatedData = groupDataAfterNthValue(data, maxValues);
truncatedLabels = truncatedLabels.slice(0, maxValues - 1);
truncatedLabels.push(othersLabel);
}
return truncatedLabels.map(
(label: string, index: number) =>
`${getFormatedText(label)} (${formatWithThousandsSeprators(
truncatedData[index].rate as number
)} %)`
);
}
function groupDataAfterNthValue(data: DoughnutData[], maxValues: number) {
if (maxValues < 1) {
return data;
}
let truncatedData = data.slice(0);
if (data.length > maxValues) {
truncatedData = truncatedData.slice(0, maxValues);
truncatedData[maxValues - 1] = data.slice(maxValues).reduce(
(result, current) => {
result.rate += current.rate;
result.value += current.value;
return result;
},
{ ...data[maxValues - 1] }
);
}
return truncatedData;
}
return {
onHoverIndex,
privateGetHtmlLegendPlugin,
getOnHoverOptions,
groupDataAfterNthValue,
getDoughnutLabels,
getBackgroundColor,
getFormatedText,
getBorderColor,
backgroundColor,
doughnutRef,
getCenteredLabelPlugin,
centeredLabel
};
}