UNPKG

@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.

263 lines (249 loc) 7.28 kB
import { reactive, ref, type Ref } from 'vue'; import PatternFunctions from './PatternFunctions'; import { addAlpha } from './ColorFunctions'; import type { HTMLLegendPlugin } from '../types/Chart'; import { getOrCreateLegendList, createHtmlLegendListElement, createLegendElementWithPatterns, createLegendElementWithCheckbox, createHtmlLegendItemText, createLegendElementWithSquareArea, type ChartItem } from './ChartsCommonLegend'; const { getPatternIndexWithShift } = PatternFunctions(); export default function () { const borderWidth = ref(2); const onHoverIndex: { dataSetIndex: number; columnIndex: number } = reactive({ dataSetIndex: -1, columnIndex: -1 }); interface Dataset { data: any; label: string; type: any; fill?: boolean; } function getHtmlLegendPlugin( legendContainer: Ref, selectMode: Ref<boolean>, onHoverIndex: any, disableAccessibility: Ref<boolean>, patternsColors: Ref<string[]>, patternsList: Ref< (( hover: boolean, color: string, disableAccessibility: boolean ) => CanvasPattern)[] > ): HTMLLegendPlugin[] { return [ { id: 'htmlLegend', afterUpdate(chart: any) { const ul: HTMLLIElement = getOrCreateLegendList( legendContainer, 'column' ); ul.style.display = 'flex'; ul.style.margin = '1.375rem 1.0625rem'; ul.style.flexDirection = 'row-reverse'; ul.style.flexWrap = 'wrap'; ul.style.justifyContent = 'flex-end'; while (ul.firstChild) { ul.firstChild.remove(); } const items: ChartItem[] = chart.options.plugins.legend.labels.generateLabels(chart); items .sort((a, b) => b.datasetIndex - a.datasetIndex) .forEach((item: ChartItem): void => { const li: HTMLElement = createHtmlLegendListElement( chart, selectMode, item.datasetIndex ); let liContent: HTMLElement; if (!selectMode.value) { if (item?.lineCap) { liContent = createLegendElementWithSquareArea(item); } else { liContent = createLegendElementWithPatterns( item, chart, { datasetIndex: -1 }, disableAccessibility.value, patternsColors.value, patternsList.value, false ); } } else { liContent = createLegendElementWithCheckbox( chart, item, selectMode, { datasetIndex: -1 }, patternsColors.value, false ); } liContent.style.boxSizing = 'border-box'; li.style.marginRight = '10px'; li.style.marginBottom = '2px'; li.appendChild(liContent); li.appendChild(createHtmlLegendItemText(item)); ul.appendChild(li); }); } } ]; } function privateGetHtmlLegendPlugin( legendContainer: Ref, selectMode: Ref<boolean>, disableAccessibility: Ref<boolean>, patternsColors: Ref<string[]>, patternsList: Ref< (( hover: boolean, color: string, disableAccessibility: boolean ) => CanvasPattern)[] > ) { return getHtmlLegendPlugin( legendContainer, selectMode, onHoverIndex, disableAccessibility, patternsColors, patternsList ); } function getMixedDatasets( datasets: Dataset[], disableAccessibility: boolean, patternsColors: string[], patternsList: (( hover: boolean, color: string, disableAccessibility: boolean ) => CanvasPattern)[], patternShifting?: number ) { // Hack to force refresh const borderWithValue = borderWidth.value; return datasets.map((dataset, index) => { const isBarChart = dataset.type === 'bar'; return { type: dataset.type, fill: isBarChart ? null : false, borderWidth: function () { return disableAccessibility && isBarChart ? 1 : borderWithValue; }, borderColor: function (context: any) { return disableAccessibility && isBarChart ? '#00000000' : isBarChart ? getBorderColor( index, context.index, patternsColors, patternShifting ) : patternsColors[index % patternsColors.length]; }, backgroundColor: function (context: any) { return getPattern( index, context.index, disableAccessibility, patternsColors, patternsList, patternShifting ); }, yAxisID: isBarChart ? 'A' : 'B', pointStyle: index % 2 === 0 ? 'rectRot' : 'circle', data: dataset.data, label: dataset.label, pointBackgroundColor: '#FFFFFF', pointRadius: 5, order: dataset.type === 'line' ? 0 : 1 }; }); } function getBorderColor( dataSetIndex: number, contextIndex: number, patternsColors: string[], patternShifting?: number ) { const index = getPatternIndexWithShift(dataSetIndex, patternShifting); if (displayFullOpacity(dataSetIndex, contextIndex)) { return patternsColors[index]; } else { return addAlpha(patternsColors[index], 0.2); } } function getPattern( dataSetIndex: number, contextIndex: number, disableAccessibility: boolean, patternsColors: string[], patternsList: (( hover: boolean, color: string, disableAccessibility: boolean ) => CanvasPattern)[], patternShifting?: number ) { const index = getPatternIndexWithShift(dataSetIndex, patternShifting); if (displayFullOpacity(dataSetIndex, contextIndex)) { return patternsList[index]( false, patternsColors[index], disableAccessibility ); } else { return patternsList[index]( true, patternsColors[index], disableAccessibility ); } } function displayFullOpacity( dataSetIndex: number, contextIndex: number ): boolean { return ( nothingHovered() || columnHovered(dataSetIndex, contextIndex) || legendHovered(dataSetIndex) ); } function nothingHovered(): boolean { return onHoverIndex.dataSetIndex < 0; } function columnHovered(dataSetIndex: number, contextIndex: number): boolean { return ( onHoverIndex.dataSetIndex === dataSetIndex && onHoverIndex.columnIndex === contextIndex ); } function legendHovered(dataSetIndex: number): boolean { return ( onHoverIndex.dataSetIndex === dataSetIndex && onHoverIndex.columnIndex < 0 ); } return { privateGetHtmlLegendPlugin, getMixedDatasets, getBorderColor, getPattern, onHoverIndex }; }