UNPKG

@mui/x-charts

Version:

The community edition of MUI X Charts components.

98 lines (92 loc) 3.53 kB
'use client'; import * as React from 'react'; import { isBandScale } from "../internals/isBandScale.js"; const offsetRatio = { start: 0, extremities: 0, end: 1, middle: 0.5, tick: 0 }; export function useTicksGrouped(options) { const { scale, tickInterval, tickLabelPlacement = 'middle', tickPlacement = 'extremities', groups } = options; return React.useMemo(() => { const domain = scale.domain(); const filteredDomain = typeof tickInterval === 'function' && domain.filter(tickInterval) || typeof tickInterval === 'object' && tickInterval || domain; if (scale.bandwidth() > 0) { // scale type = 'band' const entries = mapToGrouping(filteredDomain, groups, tickPlacement, tickLabelPlacement, scale); if (entries[0]) { entries[0].ignoreTick = true; } return [{ formattedValue: undefined, offset: scale.range()[0], labelOffset: 0, groupIndex: groups.length - 1 }, ...entries, // Last tick { formattedValue: undefined, offset: scale.range()[1], labelOffset: 0, groupIndex: groups.length - 1 }]; } // scale type = 'point' return mapToGrouping(filteredDomain, groups, tickPlacement, tickLabelPlacement, scale); }, [scale, tickInterval, groups, tickPlacement, tickLabelPlacement]); } function mapToGrouping(tickValues, groups, tickPlacement, tickLabelPlacement, scale) { const allTickItems = []; // Map to keep track of offsets and their corresponding tick indexes // Used to remove redundant ticks when they are in the same position const dataIndexToTickIndex = new Map(); let currentValueCount = 0; for (let groupIndex = 0; groupIndex < groups.length; groupIndex += 1) { for (let dataIndex = 0; dataIndex < tickValues.length; dataIndex += 1) { const tickValue = tickValues[dataIndex]; const groupValue = groups[groupIndex].getValue(tickValue, dataIndex); const lastItem = allTickItems[allTickItems.length - 1]; // Check if this is a new unique value for this group const isNew = lastItem?.value !== groupValue || lastItem?.groupIndex !== groupIndex; if (isNew) { currentValueCount = 1; // Calculate tick offset const tickOffset = isBandScale(scale) ? scale(tickValue) - (scale.step() - scale.bandwidth()) / 2 + offsetRatio[tickPlacement] * scale.step() : scale(tickValue); // Calculate the label offset const labelOffset = scale.step() * currentValueCount * (offsetRatio[tickLabelPlacement] - offsetRatio[tickPlacement]); // Add a new item allTickItems.push({ value: groupValue, formattedValue: `${groupValue}`, offset: tickOffset, groupIndex, dataIndex, ignoreTick: false, labelOffset }); if (!dataIndexToTickIndex.has(dataIndex)) { dataIndexToTickIndex.set(dataIndex, new Set()); } const tickIndexes = dataIndexToTickIndex.get(dataIndex); for (const previousIndex of tickIndexes.values()) { allTickItems[previousIndex].ignoreTick = true; } tickIndexes.add(allTickItems.length - 1); } else { currentValueCount += 1; // Calculate the label offset const labelOffset = scale.step() * currentValueCount * (offsetRatio[tickLabelPlacement] - offsetRatio[tickPlacement]); lastItem.labelOffset = labelOffset; } } } return allTickItems; }