Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfauquette committed Nov 20, 2024
1 parent 681caa5 commit 6566e4b
Show file tree
Hide file tree
Showing 22 changed files with 507 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
import { MakeOptional } from '@mui/x-internals/types';
import { DrawingAreaProvider, DrawingAreaProviderProps } from '../DrawingAreaProvider';
import { SeriesProvider, SeriesProviderProps } from '../SeriesProvider';
import { InteractionProvider } from '../InteractionProvider';
import { CartesianProvider, CartesianProviderProps } from '../CartesianProvider';
import { PluginProvider, PluginProviderProps } from '../PluginProvider';
import { useChartDataProviderProps } from './useChartDataProviderProps';
Expand All @@ -14,6 +13,7 @@ import { ZAxisContextProvider, ZAxisContextProviderProps } from '../ZAxisContext
import { HighlightedProvider, HighlightedProviderProps } from '../HighlightedProvider';
import { SizeProvider, SizeProviderProps } from '../SizeProvider';
import { SvgRefProvider } from '../SvgRefProvider';
import { ChartProvider } from '../ChartProvider';

export type ChartDataProviderProps = Omit<
SizeProviderProps &
Expand Down Expand Up @@ -61,13 +61,13 @@ function ChartDataProvider(props: ChartDataProviderProps) {
<SeriesProvider {...seriesProviderProps}>
<CartesianProvider {...cartesianProviderProps}>
<ZAxisContextProvider {...zAxisContextProps}>
<InteractionProvider>
<ChartProvider>
<HighlightedProvider {...highlightedProviderProps}>
<AnimationProvider {...animationProviderProps}>
<SvgRefProvider>{children}</SvgRefProvider>
</AnimationProvider>
</HighlightedProvider>
</InteractionProvider>
</ChartProvider>
</ZAxisContextProvider>
</CartesianProvider>
</SeriesProvider>
Expand Down
28 changes: 28 additions & 0 deletions packages/x-charts/src/context/ChartProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use client';
import * as React from 'react';
import { useCharts } from '../internals/store/useCharts';
import { ChartContextValue, ChartProviderProps } from './ChartProvider.types';
import { ALL_PLUGINS } from '../internals/plugins/allPlugins';
import { ConvertPluginsIntoSignatures } from '../internals/plugins/models/helpers';

/**
* @ignore - internal component.
*/
export const ChartContext = React.createContext<ChartContextValue<any> | null>(null);

if (process.env.NODE_ENV !== 'production') {
ChartContext.displayName = 'ChartContext';
}

function ChartProvider(props: ChartProviderProps) {
const { children } = props;

const { contextValue } = useCharts<ConvertPluginsIntoSignatures<typeof ALL_PLUGINS>, {}>(
ALL_PLUGINS,
{},
);

return <ChartContext.Provider value={contextValue}>{children}</ChartContext.Provider>;
}

export { ChartProvider };
15 changes: 15 additions & 0 deletions packages/x-charts/src/context/ChartProvider.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ChartInstance, ChartPublicAPI } from '../internals/plugins/models';
import { ChartAnyPluginSignature } from '../internals/plugins/models/plugin';
import { ChartStore } from '../internals/plugins/utils/ChartStore';

export type ChartContextValue<
TSignatures extends readonly ChartAnyPluginSignature[],
TOptionalSignatures extends readonly ChartAnyPluginSignature[] = [],
> = {
instance: ChartInstance<TSignatures, TOptionalSignatures>;
publicAPI: ChartPublicAPI<TSignatures, TOptionalSignatures>;
store: ChartStore<TSignatures>;
svgRef: React.RefObject<SVGSVGElement>;
};

export interface ChartProviderProps extends React.PropsWithChildren {}
19 changes: 0 additions & 19 deletions packages/x-charts/src/context/InteractionProvider.tsx

This file was deleted.

4 changes: 4 additions & 0 deletions packages/x-charts/src/internals/plugins/allPlugins.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// This file should be removed after creating all plugins in favor of a file per chart type.
import { useChartInteraction } from './featurePlugins/useChartInteraction';

export const ALL_PLUGINS = [useChartInteraction] as const;
13 changes: 13 additions & 0 deletions packages/x-charts/src/internals/plugins/corePlugins/corePlugins.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ConvertPluginsIntoSignatures } from '../models/helpers';


/**
* Internal plugins that create the tools used by the other plugins.
* These plugins are used by the Tree View components.
*/
export const CHART_CORE_PLUGINS = [] as const;

export type ChartCorePluginSignatures = ConvertPluginsIntoSignatures<typeof CHART_CORE_PLUGINS>;

export interface ChartCorePluginParameters {}
// extends UseChartIdParameters {}
2 changes: 2 additions & 0 deletions packages/x-charts/src/internals/plugins/corePlugins/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { CHART_CORE_PLUGINS } from './corePlugins';
export type { ChartCorePluginSignatures, ChartCorePluginParameters } from './corePlugins';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { useChartInteraction } from './useChartInteraction';
export type { UseChartInteractionSignature } from './useChartInteraction.types';
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { ChartState } from '../internals/plugins/models';
import { createSelector } from '../internals/plugins/utils/selectors';
import { ChartRootSelector, createSelector } from '../../utils/selectors';
import { UseChartInteractionSignature } from './useChartInteraction.types';

function selectInteraction(state: ChartState) {
return state.interaction;
}
const selectInteraction: ChartRootSelector<UseChartInteractionSignature> = (state) =>
state.interaction;

export const selectorChartsInteractionItem = createSelector(
selectInteraction,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import useEventCallback from '@mui/utils/useEventCallback';
import { ChartPlugin } from '../../models';
import { AxisInteractionData, UseChartInteractionSignature } from './useChartInteraction.types';
import { ChartItemIdentifier, ChartSeriesType } from '../../../../models/seriesType/config';

export const useChartInteraction: ChartPlugin<UseChartInteractionSignature> = ({ store }) => {
const cleanInteraction = useEventCallback(() => {
store.update((prev) => ({
...prev,
interaction: { ...prev.interaction, axis: { x: null, y: null }, item: null },
}));
});

const setItemInteraction = useEventCallback((newItem: ChartItemIdentifier<ChartSeriesType>) => {
store.update((prev) => ({
...prev,
interaction: {
...prev.interaction,
item: newItem,
},
}));
});

const setAxisInteraction = useEventCallback(
({ x: newStateX, y: newStateY }: Partial<AxisInteractionData>) => {
store.update((prev) => ({
...prev,
interaction: {
...prev.interaction,
axis: {
// A bit verbose, but prevent losing the x value if only y got modified.
...prev.interaction.axis,
...(prev.interaction.axis.x?.index !== newStateX?.index ||
prev.interaction.axis.x?.value !== newStateX?.value
? { x: newStateX }
: {}),
...(prev.interaction.axis.y?.index !== newStateY?.index ||
prev.interaction.axis.y?.value !== newStateY?.value
? { y: newStateY }
: {}),
},
},
}));
},
);

const enableVoronoid = useEventCallback(() => {
store.update((prev) => ({
...prev,
interaction: {
...prev.interaction,
isVoronoiEnabled: true,
},
}));
});

const disableVoronoid = useEventCallback(() => {
store.update((prev) => ({
...prev,
interaction: {
...prev.interaction,
isVoronoiEnabled: false,
},
}));
});

return {
params: {},
instance: {
cleanInteraction,
setItemInteraction,
setAxisInteraction,
enableVoronoid,
disableVoronoid,
},
};
};

useChartInteraction.getInitialState = () => ({
interaction: { item: null, axis: { x: null, y: null }, isVoronoiEnabled: false },
});

useChartInteraction.params = {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { ChartPluginSignature } from '../../models';
import { ChartItemIdentifier, ChartSeriesType } from '../../../../models/seriesType/config';

export interface UseChartInteractionInstance {
/**
* Remove all interaction.
*/
cleanInteraction: () => void;
/**
* Setter for the item the user is interacting with.
* @param {ChartItemIdentifier} newItem The identifier of the item.
*/
setItemInteraction: (newItem: ChartItemIdentifier<ChartSeriesType>) => void;
/**
* Set the new axis the user is interacting with.
* @param {Partial<AxisInteractionData>} newAxis The new axis identifier.
*/
setAxisInteraction: (newAxis: Partial<AxisInteractionData>) => void;
/**
* Enable the voronoi computation.
*/
enableVoronoid: () => void;
/**
* Disable the voronoi computation.
*/
disableVoronoid: () => void;
}

export type AxisInteractionData = {
x: null | {
value: number | Date | string;
// Set to -1 if no index.
index: number;
};
y: null | {
value: number | Date | string;
// Set to -1 if no index.
index: number;
};
};

export interface UseChartInteractionState {
interaction: {
/**
* The item currently interacting.
*/
item: null | ChartItemIdentifier<ChartSeriesType>;
/**
* The x- and y-axes currently interacting.
*/
axis: AxisInteractionData;
/**
* Set to `true` when `VoronoiHandler` is active.
* Used to prevent collision with mouseEnter events.
*/
isVoronoiEnabled?: boolean;
};
}

export type UseChartInteractionSignature = ChartPluginSignature<{
instance: UseChartInteractionInstance;
state: UseChartInteractionState;
}>;
25 changes: 25 additions & 0 deletions packages/x-charts/src/internals/plugins/models/chart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { ChartAnyPluginSignature } from './plugin';
import type { MergeSignaturesProperty } from './helpers';
import type { ChartCorePluginSignatures } from '../corePlugins';

export type ChartInstance<
TSignatures extends readonly ChartAnyPluginSignature[],
TOptionalSignatures extends readonly ChartAnyPluginSignature[] = [],
> = MergeSignaturesProperty<[...ChartCorePluginSignatures, ...TSignatures], 'instance'> &
Partial<MergeSignaturesProperty<TOptionalSignatures, 'instance'>>;

export type ChartPublicAPI<
TSignatures extends readonly ChartAnyPluginSignature[],
TOptionalSignatures extends readonly ChartAnyPluginSignature[] = [],
> = MergeSignaturesProperty<[...ChartCorePluginSignatures, ...TSignatures], 'publicAPI'> &
Partial<MergeSignaturesProperty<TOptionalSignatures, 'instance'>>;

export type ChartStateCacheKey = { id: number };

export type ChartState<
TSignatures extends readonly ChartAnyPluginSignature[],
TOptionalSignatures extends readonly ChartAnyPluginSignature[] = [],
> = MergeSignaturesProperty<[...ChartCorePluginSignatures, ...TSignatures], 'state'> &
Partial<MergeSignaturesProperty<TOptionalSignatures, 'state'>> & {
cacheKey: ChartStateCacheKey;
};
38 changes: 38 additions & 0 deletions packages/x-charts/src/internals/plugins/models/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { ChartAnyPluginSignature, ChartPlugin } from './plugin';

type IsAny<T> = 0 extends 1 & T ? true : false;

export type OptionalIfEmpty<A extends string, B> = keyof B extends never
? Partial<Record<A, B>>
: IsAny<B> extends true
? Partial<Record<A, B>>
: Record<A, B>;

export type MergeSignaturesProperty<
TSignatures extends readonly any[],
TProperty extends keyof ChartAnyPluginSignature,
> = TSignatures extends readonly [plugin: infer P, ...otherPlugin: infer R]
? P extends ChartAnyPluginSignature
? P[TProperty] & MergeSignaturesProperty<R, TProperty>
: {}
: {};

export type ConvertPluginsIntoSignatures<
TPlugins extends readonly ChartPlugin<ChartAnyPluginSignature>[],
> = TPlugins extends readonly [plugin: infer TPlugin, ...otherPlugin: infer R]
? R extends readonly ChartPlugin<any>[]
? TPlugin extends ChartPlugin<infer TSignature>
? readonly [TSignature, ...ConvertPluginsIntoSignatures<R>]
: never
: never
: [];

export type ConvertSignaturesIntoPlugins<
TSignatures extends readonly ChartAnyPluginSignature[],
> = TSignatures extends readonly [signature: infer TSignature, ...otherSignatures: infer R]
? R extends readonly ChartAnyPluginSignature[]
? TSignature extends ChartAnyPluginSignature
? readonly [ChartPlugin<TSignature>, ...ConvertSignaturesIntoPlugins<R>]
: never
: never
: [];
Loading

0 comments on commit 6566e4b

Please sign in to comment.