@mui/x-charts
Version:
The community edition of MUI X Charts components.
135 lines (131 loc) • 4.58 kB
JavaScript
'use client';
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getTicks = getTicks;
exports.useTicks = useTicks;
var React = _interopRequireWildcard(require("react"));
var _ChartProvider = require("../context/ChartProvider");
var _isBandScale = require("../internals/isBandScale");
var _isInfinity = require("../internals/isInfinity");
const offsetRatio = {
start: 0,
extremities: 0,
end: 1,
middle: 0.5
};
function getTicks(options) {
const {
scale,
tickNumber,
valueFormatter,
tickInterval,
tickPlacement = 'extremities',
tickLabelPlacement: tickLabelPlacementProp,
isInside
} = options;
// band scale
if ((0, _isBandScale.isBandScale)(scale)) {
const domain = scale.domain();
const tickLabelPlacement = tickLabelPlacementProp ?? 'middle';
if (scale.bandwidth() > 0) {
// scale type = 'band'
const filteredDomain = typeof tickInterval === 'function' && domain.filter(tickInterval) || typeof tickInterval === 'object' && tickInterval || domain;
return [...filteredDomain.map(value => {
const defaultTickLabel = `${value}`;
return {
value,
formattedValue: valueFormatter?.(value, {
location: 'tick',
scale,
tickNumber,
defaultTickLabel
}) ?? defaultTickLabel,
offset: scale(value) - (scale.step() - scale.bandwidth()) / 2 + offsetRatio[tickPlacement] * scale.step(),
labelOffset: tickLabelPlacement === 'tick' ? 0 : scale.step() * (offsetRatio[tickLabelPlacement] - offsetRatio[tickPlacement])
};
}), ...(tickPlacement === 'extremities' ? [{
formattedValue: undefined,
offset: scale.range()[1],
labelOffset: 0
}] : [])];
}
// scale type = 'point'
const filteredDomain = typeof tickInterval === 'function' && domain.filter(tickInterval) || typeof tickInterval === 'object' && tickInterval || domain;
return filteredDomain.map(value => {
const defaultTickLabel = `${value}`;
return {
value,
formattedValue: valueFormatter?.(value, {
location: 'tick',
scale,
tickNumber,
defaultTickLabel
}) ?? defaultTickLabel,
offset: scale(value),
labelOffset: 0
};
});
}
const domain = scale.domain();
// Skip axis rendering if no data is available
// - The domains contains Infinity for continuous scales.
if (domain.some(_isInfinity.isInfinity)) {
return [];
}
const tickLabelPlacement = tickLabelPlacementProp;
const ticks = typeof tickInterval === 'object' ? tickInterval : scale.ticks(tickNumber);
// Ticks inside the drawing area
const visibleTicks = [];
for (let i = 0; i < ticks.length; i += 1) {
const value = ticks[i];
const offset = scale(value);
if (isInside(offset)) {
/* If d3 returns an empty string, it means that a tick should be shown, but its label shouldn't.
* This is especially useful in a log scale where we want to show ticks to demonstrate it's a log
* scale, but don't want to show labels because they would overlap.
* https://github.com/mui/mui-x/issues/18239 */
const defaultTickLabel = scale.tickFormat(tickNumber)(value);
visibleTicks.push({
value,
formattedValue: valueFormatter?.(value, {
location: 'tick',
scale,
tickNumber,
defaultTickLabel
}) ?? defaultTickLabel,
offset,
// Allowing the label to be placed in the middle of a continuous scale is weird.
// But it is useful in some cases, like funnel categories with a linear scale.
labelOffset: tickLabelPlacement === 'middle' ? scale(ticks[i - 1] ?? 0) - (offset + scale(ticks[i - 1] ?? 0)) / 2 : 0
});
}
}
return visibleTicks;
}
function useTicks(options) {
const {
scale,
tickNumber,
valueFormatter,
tickInterval,
tickPlacement = 'extremities',
tickLabelPlacement,
direction
} = options;
const {
instance
} = (0, _ChartProvider.useChartContext)();
const isInside = direction === 'x' ? instance.isXInside : instance.isYInside;
return React.useMemo(() => getTicks({
scale,
tickNumber,
tickPlacement,
tickInterval,
tickLabelPlacement,
valueFormatter,
isInside
}), [scale, tickNumber, tickPlacement, tickInterval, tickLabelPlacement, valueFormatter, isInside]);
}
;