UNPKG

@mui/x-charts

Version:

The community edition of MUI X Charts components.

191 lines (189 loc) 7.76 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.computeAxisValue = computeAxisValue; exports.resolveAxisSize = resolveAxisSize; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _defaultValueFormatters = require("../../../defaultValueFormatters"); var _axis = require("../../../../models/axis"); var _colorScale = require("../../../colorScale"); var _ticks = require("../../../ticks"); var _getScale = require("../../../getScale"); var _dateHelpers = require("../../../dateHelpers"); var _getAxisTriggerTooltip = require("./getAxisTriggerTooltip"); var _scaleGuards = require("../../../scaleGuards"); var _constants = require("../../../../constants"); function getRange(drawingArea, axisDirection, // | 'rotation' | 'radius', reverse) { const range = axisDirection === 'x' ? [drawingArea.left, drawingArea.left + drawingArea.width] : [drawingArea.top + drawingArea.height, drawingArea.top]; return reverse ? [range[1], range[0]] : range; } function shouldIgnoreGapRatios(scale, categoryGapRatio) { const step = scale.step(); const paddingPx = step * categoryGapRatio; /* If the padding is less than 0.1px, we consider it negligible and ignore it. * This prevents issues where very small gaps cause rendering artifacts or unexpected layouts. * A threshold of 0.1px is chosen as it's generally below the perceptible limit for most displays. */ return paddingPx < 0.1; } function resolveAxisSize(axis, autoSizes, direction) { const size = direction === 'x' ? axis.height : axis.width; if (size === 'auto') { const autoSize = autoSizes?.[axis.id]; if (autoSize !== undefined) { return autoSize; } const defaultSize = direction === 'x' ? _constants.DEFAULT_AXIS_SIZE_HEIGHT : _constants.DEFAULT_AXIS_SIZE_WIDTH; return defaultSize + (axis.label ? _constants.AXIS_LABEL_DEFAULT_HEIGHT : 0); } return size ?? 0; } const DEFAULT_CATEGORY_GAP_RATIO = 0.2; const DEFAULT_BAR_GAP_RATIO = 0.1; /** * Recalculates axis offsets using actual resolved sizes (including auto-sizes). * This is needed because offsets from defaultizeAxis use placeholder values for auto-sized axes. */ function recalculateOffsets(allAxis, autoSizes, axisDirection, axesGap) { const offsets = {}; const result = {}; for (const axis of allAxis) { const position = axis.position; if (!position) { continue; } offsets[position] ?? (offsets[position] = 0); result[axis.id] = offsets[position]; if (position !== 'none') { const size = resolveAxisSize(axis, autoSizes, axisDirection); offsets[position] += size + axesGap; const zoom = axis.zoom; if (zoom?.slider.enabled) { offsets[position] += zoom.slider.size; } } } return result; } function computeAxisValue({ scales, drawingArea, formattedSeries, axis: allAxis, seriesConfig, axisDirection, zoomMap, domains, autoSizes, axesGap = 0 }) { if (allAxis === undefined) { return { axis: {}, axisIds: [] }; } const axisIdsTriggeringTooltip = (0, _getAxisTriggerTooltip.getAxisTriggerTooltip)(axisDirection, seriesConfig, formattedSeries, allAxis[0].id); const resolvedOffsets = recalculateOffsets(allAxis, autoSizes, axisDirection, axesGap); const completeAxis = {}; allAxis.forEach(eachAxis => { const axis = eachAxis; const scale = scales[axis.id]; const zoom = zoomMap?.get(axis.id); const zoomRange = zoom ? [zoom.start, zoom.end] : [0, 100]; const range = getRange(drawingArea, axisDirection, axis.reverse ?? false); const rawTickNumber = domains[axis.id].tickNumber; const triggerTooltip = !axis.ignoreTooltip && axisIdsTriggeringTooltip.has(axis.id); const tickNumber = (0, _ticks.scaleTickNumberByRange)(rawTickNumber, zoomRange); const resolvedSize = resolveAxisSize(axis, autoSizes, axisDirection); const data = axis.data ?? []; const resolvedOffset = resolvedOffsets[axis.id] ?? axis.offset ?? 0; if ((0, _scaleGuards.isOrdinalScale)(scale)) { const scaleRange = axisDirection === 'y' ? [range[1], range[0]] : range; if ((0, _scaleGuards.isBandScale)(scale) && (0, _axis.isBandScaleConfig)(axis)) { const desiredCategoryGapRatio = axis.categoryGapRatio ?? DEFAULT_CATEGORY_GAP_RATIO; const ignoreGapRatios = shouldIgnoreGapRatios(scale, desiredCategoryGapRatio); const categoryGapRatio = ignoreGapRatios ? 0 : desiredCategoryGapRatio; const barGapRatio = ignoreGapRatios ? 0 : axis.barGapRatio ?? DEFAULT_BAR_GAP_RATIO; completeAxis[axis.id] = (0, _extends2.default)({ categoryGapRatio, barGapRatio, triggerTooltip }, axis, { offset: resolvedOffset }, axisDirection === 'x' ? { height: resolvedSize } : { width: resolvedSize }, { data, /* Doing this here is technically wrong, but acceptable in practice. * In theory, this should be done in the normalized scale selector, but then we'd need that selector to depend * on the zoom range, which would void its goal (which is to be independent of zoom). * Since we only ignore gap ratios when they're practically invisible, the small errors caused by this * discrepancy will hopefully not be noticeable. */ scale: ignoreGapRatios ? scale.copy().padding(0) : scale, tickNumber, colorScale: axis.colorMap && (axis.colorMap.type === 'ordinal' ? (0, _colorScale.getOrdinalColorScale)((0, _extends2.default)({ values: axis.data }, axis.colorMap)) : (0, _colorScale.getColorScale)(axis.colorMap)) }); } if ((0, _axis.isPointScaleConfig)(axis)) { completeAxis[axis.id] = (0, _extends2.default)({ triggerTooltip }, axis, { offset: resolvedOffset }, axisDirection === 'x' ? { height: resolvedSize } : { width: resolvedSize }, { data, scale, tickNumber, colorScale: axis.colorMap && (axis.colorMap.type === 'ordinal' ? (0, _colorScale.getOrdinalColorScale)((0, _extends2.default)({ values: axis.data }, axis.colorMap)) : (0, _colorScale.getColorScale)(axis.colorMap)) }); } if ((0, _dateHelpers.isDateData)(axis.data)) { const dateFormatter = (0, _dateHelpers.createDateFormatter)(axis.data, scaleRange, axis.tickNumber); completeAxis[axis.id].valueFormatter = axis.valueFormatter ?? dateFormatter; } return; } if (axis.scaleType === 'band' || axis.scaleType === 'point') { // Could be merged with the two previous "if conditions" but then TS does not get that `axis.scaleType` can't be `band` or `point`. return; } const continuousAxis = axis; const scaleType = continuousAxis.scaleType ?? 'linear'; completeAxis[axis.id] = (0, _extends2.default)({ triggerTooltip }, continuousAxis, { offset: resolvedOffset }, axisDirection === 'x' ? { height: resolvedSize } : { width: resolvedSize }, { data, scaleType, scale, tickNumber, colorScale: continuousAxis.colorMap && (0, _colorScale.getSequentialColorScale)(continuousAxis.colorMap), valueFormatter: axis.valueFormatter ?? (0, _defaultValueFormatters.createScalarFormatter)(tickNumber, (0, _getScale.getScale)(scaleType, range.map(v => scale.invert(v)), range)) }); }); return { axis: completeAxis, axisIds: allAxis.map(({ id }) => id) }; }