@mui/x-charts
Version:
The community edition of MUI X Charts components.
230 lines (225 loc) • 9.97 kB
JavaScript
'use client';
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useChartCartesianAxis = void 0;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var React = _interopRequireWildcard(require("react"));
var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
var _useAssertModelConsistency = require("@mui/x-internals/useAssertModelConsistency");
var _warning = require("@mui/x-internals/warning");
var _colorPalettes = require("../../../../colorPalettes");
var _useSelector = require("../../../store/useSelector");
var _useChartDimensions = require("../../corePlugins/useChartDimensions/useChartDimensions.selectors");
var _useChartSeries = require("../../corePlugins/useChartSeries/useChartSeries.selectors");
var _defaultizeAxis = require("./defaultizeAxis");
var _useChartCartesianAxisRendering = require("./useChartCartesianAxisRendering.selectors");
var _getAxisValue = require("./getAxisValue");
var _getSVGPoint = require("../../../getSVGPoint");
var _useChartInteraction = require("../useChartInteraction");
var _useChartCartesianInteraction = require("./useChartCartesianInteraction.selectors");
var _useLazySelectorEffect = require("../../utils/useLazySelectorEffect");
const useChartCartesianAxis = ({
params,
store,
seriesConfig,
svgRef,
instance
}) => {
const {
xAxis,
yAxis,
dataset,
onHighlightedAxisChange
} = params;
if (process.env.NODE_ENV !== 'production') {
const ids = [...(xAxis ?? []), ...(yAxis ?? [])].filter(axis => axis.id).map(axis => axis.id);
const duplicates = new Set(ids.filter((id, index) => ids.indexOf(id) !== index));
if (duplicates.size > 0) {
(0, _warning.warnOnce)([`MUI X Charts: The following axis ids are duplicated: ${Array.from(duplicates).join(', ')}.`, `Please make sure that each axis has a unique id.`].join('\n'), 'error');
}
}
const drawingArea = (0, _useSelector.useSelector)(store, _useChartDimensions.selectorChartDrawingArea);
const processedSeries = (0, _useSelector.useSelector)(store, _useChartSeries.selectorChartSeriesProcessed);
const isInteractionEnabled = (0, _useSelector.useSelector)(store, _useChartInteraction.selectorChartsInteractionIsInitialized);
const {
axis: xAxisWithScale,
axisIds: xAxisIds
} = (0, _useSelector.useSelector)(store, _useChartCartesianAxisRendering.selectorChartXAxis);
const {
axis: yAxisWithScale,
axisIds: yAxisIds
} = (0, _useSelector.useSelector)(store, _useChartCartesianAxisRendering.selectorChartYAxis);
(0, _useAssertModelConsistency.useAssertModelConsistency)({
warningPrefix: 'MUI X Charts',
componentName: 'Chart',
propName: 'highlightedAxis',
controlled: params.highlightedAxis,
defaultValue: undefined
});
(0, _useEnhancedEffect.default)(() => {
if (params.highlightedAxis !== undefined) {
store.update(prevState => {
if (prevState.controlledCartesianAxisHighlight === params.highlightedAxis) {
return prevState;
}
return (0, _extends2.default)({}, prevState, {
controlledCartesianAxisHighlight: params.highlightedAxis
});
});
}
}, [store, params.highlightedAxis]);
// The effect do not track any value defined synchronously during the 1st render by hooks called after `useChartCartesianAxis`
// As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one
const isFirstRender = React.useRef(true);
React.useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
}
store.update(prev => (0, _extends2.default)({}, prev, {
cartesianAxis: (0, _extends2.default)({}, prev.cartesianAxis, {
x: (0, _defaultizeAxis.defaultizeXAxis)(xAxis, dataset),
y: (0, _defaultizeAxis.defaultizeYAxis)(yAxis, dataset)
})
}));
}, [seriesConfig, drawingArea, xAxis, yAxis, dataset, store]);
const usedXAxis = xAxisIds[0];
const usedYAxis = yAxisIds[0];
(0, _useLazySelectorEffect.useLazySelectorEffect)(store, _useChartCartesianInteraction.selectorChartAxisInteraction, (prevAxisInteraction, nextAxisInteraction) => {
if (Object.is(prevAxisInteraction, nextAxisInteraction)) {
return;
}
if (prevAxisInteraction.length !== nextAxisInteraction.length) {
onHighlightedAxisChange(nextAxisInteraction);
return;
}
if (prevAxisInteraction?.some(({
axisId,
dataIndex
}, itemIndex) => nextAxisInteraction[itemIndex].axisId !== axisId || nextAxisInteraction[itemIndex].dataIndex !== dataIndex)) {
onHighlightedAxisChange(nextAxisInteraction);
}
}, !onHighlightedAxisChange);
React.useEffect(() => {
const element = svgRef.current;
if (!isInteractionEnabled || !element || params.disableAxisListener) {
return () => {};
}
// Clean the interaction when the mouse leaves the chart.
const moveEndHandler = instance.addInteractionListener('moveEnd', event => {
if (!event.detail.activeGestures.pan) {
instance.cleanInteraction?.();
}
});
const panEndHandler = instance.addInteractionListener('panEnd', event => {
if (!event.detail.activeGestures.move) {
instance.cleanInteraction?.();
}
});
const pressEndHandler = instance.addInteractionListener('quickPressEnd', event => {
if (!event.detail.activeGestures.move && !event.detail.activeGestures.pan) {
instance.cleanInteraction?.();
}
});
const gestureHandler = event => {
const srvEvent = event.detail.srcEvent;
const target = event.detail.target;
const svgPoint = (0, _getSVGPoint.getSVGPoint)(element, srvEvent);
// Release the pointer capture if we are panning, as this would cause the tooltip to
// be locked to the first "section" it touches.
if (event.detail.srcEvent.buttons >= 1 && target?.hasPointerCapture(event.detail.srcEvent.pointerId) && !target?.closest('[data-charts-zoom-slider]')) {
target?.releasePointerCapture(event.detail.srcEvent.pointerId);
}
if (!instance.isPointInside(svgPoint.x, svgPoint.y, target)) {
instance.cleanInteraction?.();
return;
}
instance.setPointerCoordinate?.(svgPoint);
};
const moveHandler = instance.addInteractionListener('move', gestureHandler);
const panHandler = instance.addInteractionListener('pan', gestureHandler);
const pressHandler = instance.addInteractionListener('quickPress', gestureHandler);
return () => {
moveHandler.cleanup();
moveEndHandler.cleanup();
panHandler.cleanup();
panEndHandler.cleanup();
pressHandler.cleanup();
pressEndHandler.cleanup();
};
}, [svgRef, store, xAxisWithScale, usedXAxis, yAxisWithScale, usedYAxis, instance, params.disableAxisListener, isInteractionEnabled]);
React.useEffect(() => {
const element = svgRef.current;
const onAxisClick = params.onAxisClick;
if (element === null || !onAxisClick) {
return () => {};
}
const axisClickHandler = instance.addInteractionListener('tap', event => {
let dataIndex = null;
let isXAxis = false;
const svgPoint = (0, _getSVGPoint.getSVGPoint)(element, event.detail.srcEvent);
const xIndex = (0, _getAxisValue.getAxisIndex)(xAxisWithScale[usedXAxis], svgPoint.x);
isXAxis = xIndex !== -1;
dataIndex = isXAxis ? xIndex : (0, _getAxisValue.getAxisIndex)(yAxisWithScale[usedYAxis], svgPoint.y);
const USED_AXIS_ID = isXAxis ? xAxisIds[0] : yAxisIds[0];
if (dataIndex == null || dataIndex === -1) {
return;
}
// The .data exist because otherwise the dataIndex would be null or -1.
const axisValue = (isXAxis ? xAxisWithScale : yAxisWithScale)[USED_AXIS_ID].data[dataIndex];
const seriesValues = {};
Object.keys(processedSeries).filter(seriesType => ['bar', 'line'].includes(seriesType)).forEach(seriesType => {
processedSeries[seriesType]?.seriesOrder.forEach(seriesId => {
const seriesItem = processedSeries[seriesType].series[seriesId];
const providedXAxisId = seriesItem.xAxisId;
const providedYAxisId = seriesItem.yAxisId;
const axisKey = isXAxis ? providedXAxisId : providedYAxisId;
if (axisKey === undefined || axisKey === USED_AXIS_ID) {
seriesValues[seriesId] = seriesItem.data[dataIndex];
}
});
});
onAxisClick(event.detail.srcEvent, {
dataIndex,
axisValue,
seriesValues
});
});
return () => {
axisClickHandler.cleanup();
};
}, [params.onAxisClick, processedSeries, svgRef, xAxisWithScale, xAxisIds, yAxisWithScale, yAxisIds, usedXAxis, usedYAxis, instance]);
return {};
};
exports.useChartCartesianAxis = useChartCartesianAxis;
useChartCartesianAxis.params = {
xAxis: true,
yAxis: true,
dataset: true,
onAxisClick: true,
disableAxisListener: true,
onHighlightedAxisChange: true,
highlightedAxis: true
};
useChartCartesianAxis.getDefaultizedParams = ({
params
}) => {
return (0, _extends2.default)({}, params, {
colors: params.colors ?? _colorPalettes.rainbowSurgePalette,
theme: params.theme ?? 'light',
defaultizedXAxis: (0, _defaultizeAxis.defaultizeXAxis)(params.xAxis, params.dataset),
defaultizedYAxis: (0, _defaultizeAxis.defaultizeYAxis)(params.yAxis, params.dataset)
});
};
useChartCartesianAxis.getInitialState = params => (0, _extends2.default)({
cartesianAxis: {
x: params.defaultizedXAxis,
y: params.defaultizedYAxis
}
}, params.highlightedAxis === undefined ? {} : {
controlledCartesianAxisHighlight: params.highlightedAxis
});
;