Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2bd47da
Use the internal store
alexfauquette Oct 21, 2025
1b12e9b
Fix store.update()
alexfauquette Oct 21, 2025
1b7fba0
move selectors
alexfauquette Oct 22, 2025
1baa85c
Merge remote-tracking branch 'upstream/master' into no-renamining
alexfauquette Oct 22, 2025
96c3da0
fix series selectors
alexfauquette Oct 22, 2025
0a235cb
fix tooltip
alexfauquette Oct 22, 2025
593575f
prettier
alexfauquette Oct 22, 2025
65b8785
Try using variable as recomanded by Romain
alexfauquette Oct 22, 2025
df2ddc0
Merge remote-tracking branch 'upstream/master' into no-renamining
alexfauquette Oct 24, 2025
17ebe58
fix visual regressions
alexfauquette Oct 24, 2025
067bdc0
fix-ts
alexfauquette Oct 24, 2025
4ba0463
prettier
alexfauquette Oct 24, 2025
31813bc
memoize axis computation
alexfauquette Oct 24, 2025
c26f696
Avoid SVG rerendering
alexfauquette Oct 24, 2025
2dcd2db
Memoize bar element rendering
alexfauquette Oct 24, 2025
7285902
fix-sizing
alexfauquette Oct 27, 2025
e5ea1eb
memoize flatbrush
alexfauquette Oct 27, 2025
fabf213
mmeoize funnel axis
alexfauquette Oct 27, 2025
074b1f7
memoize highlighted item
alexfauquette Oct 27, 2025
617f9c5
fix
alexfauquette Oct 27, 2025
1ff3dc1
memoize zoom filters
alexfauquette Oct 27, 2025
d749818
fix empty array ref
alexfauquette Oct 27, 2025
09dff85
script and renaming
alexfauquette Oct 27, 2025
67d92e5
forgotten lines
alexfauquette Oct 27, 2025
5f46ae4
Merge remote-tracking branch 'upstream/master' into no-renamining
alexfauquette Oct 29, 2025
d334f72
Merge remote-tracking branch 'upstream/master' into no-renamining
alexfauquette Oct 30, 2025
22afbb3
fixes
alexfauquette Oct 30, 2025
3b92ce2
add memoization
alexfauquette Oct 30, 2025
c8c61e5
rename
alexfauquette Oct 30, 2025
1270430
Merge remote-tracking branch 'upstream/master' into no-renamining
alexfauquette Oct 30, 2025
e4e17d0
use selector
JCQuintas Oct 31, 2025
815b6cf
Merge branch 'master' into no-renamining
JCQuintas Oct 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ interface ChartZoomSliderProps {
export function ChartAxisZoomSlider({ axisDirection, axisId }: ChartZoomSliderProps) {
const store = useStore();
const drawingArea = useDrawingArea();
const zoomData = useSelector(store, selectorChartAxisZoomData, [axisId]);
const zoomOptions = useSelector(store, selectorChartAxisZoomOptionsLookup, [axisId]);
const zoomData = useSelector(store, selectorChartAxisZoomData, axisId);
const zoomOptions = useSelector(store, selectorChartAxisZoomOptionsLookup, axisId);
const [showTooltip, setShowTooltip] = React.useState(false);
const { xAxis } = useXAxes();
const { yAxis } = useYAxes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function ChartAxisZoomSliderActiveTrack({
}: ChartAxisZoomSliderActiveTrackProps) {
const { instance, svgRef } = useChartContext<[UseChartProZoomSignature]>();
const store = useStore<[UseChartProZoomSignature]>();
const axis = useSelector(store, selectorChartAxis, [axisId]);
const axis = useSelector(store, selectorChartAxis, axisId);
const drawingArea = useDrawingArea();
const activePreviewRectRef = React.useRef<SVGRectElement>(null);
const [startThumbEl, setStartThumbEl] = React.useState<SVGRectElement | null>(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ function PreviewRectangles(props: {
const { axisId, axisDirection } = props;
const store = useStore();

const zoomData = useSelector(store, selectorChartAxisZoomData, [axisId]);
const zoomOptions = useSelector(store, selectorChartAxisZoomOptionsLookup, [axisId]);
const zoomData = useSelector(store, selectorChartAxisZoomData, axisId);
const zoomOptions = useSelector(store, selectorChartAxisZoomOptionsLookup, axisId);
const id = useId();

if (!zoomData) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ function PreviewAreaElement({ id, color, gradientId, onClick, ...other }: Previe
function useAreaPreviewData(axisId: AxisId) {
const store = useStore();

const xAxes = useSelector(store, selectorChartPreviewComputedXAxis, [axisId]);
const yAxes = useSelector(store, selectorChartPreviewComputedYAxis, [axisId]);
const xAxes = useSelector(store, selectorChartPreviewComputedXAxis, axisId);
const yAxes = useSelector(store, selectorChartPreviewComputedYAxis, axisId);

return useAreaPlotData(xAxes, yAxes);
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ export function BarPreviewPlot(props: BarPreviewPlotProps) {
function useBarPreviewData(axisId: AxisId, drawingArea: ChartDrawingArea) {
const store = useStore();

const xAxes = useSelector(store, selectorChartPreviewComputedXAxis, [axisId]);
const yAxes = useSelector(store, selectorChartPreviewComputedYAxis, [axisId]);
const xAxes = useSelector(store, selectorChartPreviewComputedXAxis, axisId);
const yAxes = useSelector(store, selectorChartPreviewComputedYAxis, axisId);

return useBarPlotData(drawingArea, xAxes, yAxes);
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ function PreviewLineElement({ id, color, gradientId, onClick, ...other }: Previe
function useLinePreviewData(axisId: AxisId) {
const store = useStore();

const xAxes = useSelector(store, selectorChartPreviewComputedXAxis, [axisId]);
const yAxes = useSelector(store, selectorChartPreviewComputedYAxis, [axisId]);
const xAxes = useSelector(store, selectorChartPreviewComputedXAxis, axisId);
const yAxes = useSelector(store, selectorChartPreviewComputedYAxis, axisId);

return useLinePlotData(xAxes, yAxes);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ interface ScatterPreviewPlotProps extends PreviewPlotProps {
export function ScatterPreviewPlot({ axisId, x, y, height, width }: ScatterPreviewPlotProps) {
const store = useStore();
const seriesData = useScatterSeriesContext();
const xAxes = useSelector(store, selectorChartPreviewComputedXAxis, [axisId]);
const yAxes = useSelector(store, selectorChartPreviewComputedYAxis, [axisId]);
const xAxes = useSelector(store, selectorChartPreviewComputedXAxis, axisId);
const yAxes = useSelector(store, selectorChartPreviewComputedYAxis, axisId);
const defaultXAxisId = useXAxes().xAxisIds[0];
const defaultYAxisId = useYAxes().yAxisIds[0];
const { zAxis: zAxes, zAxisIds } = useZAxes();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createSelectorMemoized } from '@mui/x-internals/store';
import {
createSelector,
selectorChartSeriesConfig,
Expand All @@ -15,14 +16,13 @@ export const selectorFunnel = (state: ChartState<[], [UseChartFunnelAxisSignatur

export const selectorFunnelGap = createSelector([selectorFunnel], (funnel) => funnel?.gap ?? 0);

export const selectorChartXAxis = createSelector(
[
selectorChartRawXAxis,
selectorChartDrawingArea,
selectorChartSeriesProcessed,
selectorChartSeriesConfig,
selectorFunnelGap,
],
export const selectorChartXAxis = createSelectorMemoized(
selectorChartRawXAxis,
selectorChartDrawingArea,
selectorChartSeriesProcessed,
selectorChartSeriesConfig,
selectorFunnelGap,

(axis, drawingArea, formattedSeries, seriesConfig, gap) =>
computeAxisValue({
drawingArea,
Expand All @@ -34,14 +34,13 @@ export const selectorChartXAxis = createSelector(
}),
);

export const selectorChartYAxis = createSelector(
[
selectorChartRawYAxis,
selectorChartDrawingArea,
selectorChartSeriesProcessed,
selectorChartSeriesConfig,
selectorFunnelGap,
],
export const selectorChartYAxis = createSelectorMemoized(
selectorChartRawYAxis,
selectorChartDrawingArea,
selectorChartSeriesProcessed,
selectorChartSeriesConfig,
selectorFunnelGap,

(axis, drawingArea, formattedSeries, seriesConfig, gap) =>
computeAxisValue({
drawingArea,
Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts-pro/src/SankeyChart/SankeyLinkElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export const SankeyLinkElement = React.forwardRef<SVGPathElement, SankeyLinkElem
link,
};

const isHighlighted = useSelector(store, selectorIsLinkHighlighted, [link]);
const isFaded = useSelector(store, selectorIsSankeyItemFaded, [isHighlighted]);
const isHighlighted = useSelector(store, selectorIsLinkHighlighted, link);
const isFaded = useSelector(store, selectorIsSankeyItemFaded, isHighlighted);

// Add interaction props for tooltips
const interactionProps = useInteractionItemProps(identifier);
Expand Down
4 changes: 2 additions & 2 deletions packages/x-charts-pro/src/SankeyChart/SankeyNodeElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ export const SankeyNodeElement = React.forwardRef<SVGGElement, SankeyNodeElement
node,
};

const isHighlighted = useSelector(store, selectorIsNodeHighlighted, [node]);
const isFaded = useSelector(store, selectorIsSankeyItemFaded, [isHighlighted]);
const isHighlighted = useSelector(store, selectorIsNodeHighlighted, node.id);
const isFaded = useSelector(store, selectorIsSankeyItemFaded, isHighlighted);

// Add interaction props for tooltips
const interactionProps = useInteractionItemProps(identifier);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
type UseChartSeriesSignature,
} from '@mui/x-charts/internals';
import type { UseSankeyHighlightSignature } from './useSankeyHighlight.types';
import type { SankeyLayoutLink, SankeyLayoutNode } from '../sankey.types';
import type { SankeyLayoutLink, SankeyNodeId } from '../sankey.types';
import type {
SankeyLinkFade,
SankeyLinkHighlight,
Expand Down Expand Up @@ -79,13 +79,8 @@ export const selectorSankeyHighlightedItem = createSelector(
* - It's connected to a highlighted link (based on linkOptions.highlight)
*/
export const selectorIsNodeHighlighted = createSelector(
[
selectorSankeyHighlightedItem,
selectorNodeHighlightConfig,
selectorLinkHighlightConfig,
(_, node: SankeyLayoutNode) => node.id,
],
(highlightedItem, nodeHighlight, linkHighlight, nodeId): boolean => {
[selectorSankeyHighlightedItem, selectorNodeHighlightConfig, selectorLinkHighlightConfig],
(highlightedItem, nodeHighlight, linkHighlight, nodeId: SankeyNodeId): boolean => {
if (!highlightedItem) {
return false;
}
Expand Down Expand Up @@ -124,13 +119,8 @@ export const selectorIsNodeHighlighted = createSelector(
* - It's connected to a highlighted node (based on nodeOptions.highlight)
*/
export const selectorIsLinkHighlighted = createSelector(
[
selectorSankeyHighlightedItem,
selectorNodeHighlightConfig,
selectorLinkHighlightConfig,
(_, link: SankeyLayoutLink) => link,
],
(highlightedItem, nodeHighlight, linkHighlight, link): boolean => {
[selectorSankeyHighlightedItem, selectorNodeHighlightConfig, selectorLinkHighlightConfig],
(highlightedItem, nodeHighlight, linkHighlight, link: SankeyLayoutLink): boolean => {
if (!highlightedItem) {
return false;
}
Expand Down Expand Up @@ -174,13 +164,8 @@ export const selectorIsLinkHighlighted = createSelector(
* - The fade mode is 'global' for the highlighted element type
*/
export const selectorIsSankeyItemFaded = createSelector(
[
selectorSankeyHighlightedItem,
selectorNodeFadeConfig,
selectorLinkFadeConfig,
(_, isHighlighted) => isHighlighted,
],
(highlightedItem, nodeFade, linkFade, isHighlighted): boolean => {
[selectorSankeyHighlightedItem, selectorNodeFadeConfig, selectorLinkFadeConfig],
(highlightedItem, nodeFade, linkFade, isHighlighted: boolean): boolean => {
if (!highlightedItem || isHighlighted) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { selectorChartZoomState } from './useChartProZoom.selectors';
import type { ZoomInteractionName, PanInteractionName } from './ZoomInteractionConfig.types';

export const selectorZoomInteractionConfig = createSelector(
[selectorChartZoomState, (_state, interactionName: ZoomInteractionName) => interactionName],
(zoomState, interactionName) => zoomState.zoomInteractionConfig.zoom[interactionName] ?? null,
[selectorChartZoomState],
(zoomState, interactionName: ZoomInteractionName) =>
zoomState.zoomInteractionConfig.zoom[interactionName] ?? null,
);

export const selectorPanInteractionConfig = createSelector(
[selectorChartZoomState, (_state, interactionName: PanInteractionName) => interactionName],
(zoomState, interactionName) => zoomState.zoomInteractionConfig.pan[interactionName] ?? null,
[selectorChartZoomState],
(zoomState, interactionName: PanInteractionName) =>
zoomState.zoomInteractionConfig.pan[interactionName] ?? null,
);

export const selectorIsZoomBrushEnabled = createSelector(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const usePanOnDrag = (
const drawingArea = useSelector(store, selectorChartDrawingArea);
const optionsLookup = useSelector(store, selectorChartZoomOptionsLookup);
const startRef = React.useRef<readonly ZoomData[]>(null);
const config = useSelector(store, selectorPanInteractionConfig, ['drag' as const]);
const config = useSelector(store, selectorPanInteractionConfig, 'drag' as const);

const isPanOnDragEnabled: boolean =
Object.values(optionsLookup).some((v) => v.panning) && Boolean(config);
Expand Down Expand Up @@ -77,6 +77,7 @@ export const usePanOnDrag = (

const handlePan = (event: PanEvent) => {
const zoomData = startRef.current;

if (!zoomData) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const usePanOnPressAndDrag = (
const drawingArea = useSelector(store, selectorChartDrawingArea);
const optionsLookup = useSelector(store, selectorChartZoomOptionsLookup);
const startRef = React.useRef<readonly ZoomData[]>(null);
const config = useSelector(store, selectorPanInteractionConfig, ['pressAndDrag' as const]);
const config = useSelector(store, selectorPanInteractionConfig, 'pressAndDrag' as const);

const isPanOnPressAndDragEnabled: boolean =
Object.values(optionsLookup).some((v) => v.panning) && Boolean(config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const useZoomOnBrush = (
) => {
const drawingArea = useSelector(store, selectorChartDrawingArea);
const optionsLookup = useSelector(store, selectorChartZoomOptionsLookup);
const config = useSelector(store, selectorZoomInteractionConfig, ['brush' as const]);
const config = useSelector(store, selectorZoomInteractionConfig, 'brush' as const);

const isZoomOnBrushEnabled: boolean = Object.keys(optionsLookup).length > 0 && Boolean(config);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const useZoomOnDoubleTapReset = (
setZoomDataCallback: React.Dispatch<ZoomData[] | ((prev: ZoomData[]) => ZoomData[])>,
) => {
const optionsLookup = useSelector(store, selectorChartZoomOptionsLookup);
const config = useSelector(store, selectorZoomInteractionConfig, ['doubleTapReset' as const]);
const config = useSelector(store, selectorZoomInteractionConfig, 'doubleTapReset' as const);

const isZoomOnDoubleTapResetEnabled: boolean =
Object.keys(optionsLookup).length > 0 && Boolean(config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const useZoomOnPinch = (
) => {
const drawingArea = useSelector(store, selectorChartDrawingArea);
const optionsLookup = useSelector(store, selectorChartZoomOptionsLookup);
const config = useSelector(store, selectorZoomInteractionConfig, ['pinch' as const]);
const config = useSelector(store, selectorZoomInteractionConfig, 'pinch' as const);

const isZoomOnPinchEnabled: boolean = Object.keys(optionsLookup).length > 0 && Boolean(config);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const useZoomOnTapAndDrag = (
) => {
const drawingArea = useSelector(store, selectorChartDrawingArea);
const optionsLookup = useSelector(store, selectorChartZoomOptionsLookup);
const config = useSelector(store, selectorZoomInteractionConfig, ['tapAndDrag' as const]);
const config = useSelector(store, selectorZoomInteractionConfig, 'tapAndDrag' as const);

const isZoomOnTapAndDragEnabled: boolean =
Object.keys(optionsLookup).length > 0 && Boolean(config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const useZoomOnWheel = (
const optionsLookup = useSelector(store, selectorChartZoomOptionsLookup);
const startedOutsideRef = React.useRef(false);
const startedOutsideTimeoutRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
const config = useSelector(store, selectorZoomInteractionConfig, ['wheel' as const]);
const config = useSelector(store, selectorZoomInteractionConfig, 'wheel' as const);

const isZoomOnWheelEnabled: boolean = Object.keys(optionsLookup).length > 0 && Boolean(config);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export const selectorChartZoomIsEnabled = createSelector(
);

export const selectorChartAxisZoomData = createSelector(
[selectorChartZoomMap, (state, axisId: AxisId) => axisId],
(zoomMap, axisId) => zoomMap?.get(axisId),
[selectorChartZoomMap],
(zoomMap, axisId: AxisId) => zoomMap?.get(axisId),
);

export const selectorChartCanZoomOut = createSelector(
Expand Down
26 changes: 16 additions & 10 deletions packages/x-charts/src/BarChart/BarElement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,22 @@ function BarElement(props: BarElementProps) {
height,
...other
} = props;
const interactionProps = useInteractionItemProps({ type: 'bar', seriesId: id, dataIndex });
const { isFaded, isHighlighted } = useItemHighlighted({
seriesId: id,
dataIndex,
});
const isFocused = useIsItemFocused({
seriesType: 'bar',
seriesId: id,
dataIndex,
});
const itemIdentifier = React.useMemo(
() => ({ type: 'bar' as const, seriesId: id, dataIndex }),
[id, dataIndex],
);
const interactionProps = useInteractionItemProps(itemIdentifier);
const { isFaded, isHighlighted } = useItemHighlighted(itemIdentifier);
const isFocused = useIsItemFocused(
React.useMemo(
() => ({
seriesType: 'bar',
seriesId: id,
dataIndex,
}),
[id, dataIndex],
),
);

const ownerState = {
id,
Expand Down
14 changes: 10 additions & 4 deletions packages/x-charts/src/ChartsSurface/ChartsSurface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import { useSvgRef } from '../hooks/useSvgRef';
import { useSelector } from '../internals/store/useSelector';
import { useStore } from '../internals/store/useStore';
import {
selectorChartContainerSize,
selectorChartPropsSize,
selectorChartPropsHeight,
selectorChartPropsWidth,
selectorChartSvgWidth,
selectorChartSvgHeight,
} from '../internals/plugins/corePlugins/useChartDimensions/useChartDimensions.selectors';
import {
selectorChartsHasFocusedItem,
Expand Down Expand Up @@ -80,8 +82,12 @@ const ChartsSurface = React.forwardRef<SVGSVGElement, ChartsSurfaceProps>(functi
ref: React.Ref<SVGSVGElement>,
) {
const store = useStore();
const { width: svgWidth, height: svgHeight } = useSelector(store, selectorChartContainerSize);
const { width: propsWidth, height: propsHeight } = useSelector(store, selectorChartPropsSize);

const svgWidth = useSelector(store, selectorChartSvgWidth);
const svgHeight = useSelector(store, selectorChartSvgHeight);

const propsWidth = useSelector(store, selectorChartPropsWidth);
const propsHeight = useSelector(store, selectorChartPropsHeight);
const isKeyboardNavigationEnabled = useSelector(store, selectorChartsIsKeyboardNavigationEnabled);
const hasFocusedItem = useSelector(store, selectorChartsHasFocusedItem);
const svgRef = useSvgRef();
Expand Down
Loading
Loading