142 lines
4.7 KiB
JavaScript
142 lines
4.7 KiB
JavaScript
"use strict";
|
|
'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 : getDefaultTicks(scale, 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 getDefaultTicks(scale, tickNumber) {
|
|
const domain = scale.domain();
|
|
if (domain[0] === domain[1]) {
|
|
return [domain[0]];
|
|
}
|
|
return scale.ticks(tickNumber);
|
|
}
|
|
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]);
|
|
} |