Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[charts] Allow Zoom to be controllable #13858

Merged
merged 31 commits into from
Jul 23, 2024
Merged

Conversation

JCQuintas
Copy link
Member

  • Had to change the internal usage of setZoomData([]) to setZoomData(() => []) to work with controllable state
  • Small adjustments to zoom and pan logic to work with the setZoomData usage change

Basic usage

const Component = () => {
  const [zoom, setZoom] = React.useState<ZoomData[]>([
    {
      axisId: 'my-x-axis',
      start: 20,
      end: 40,
    },
  ]);

  return (
    <div>
      <Button onClick={() => setZoom([{ axisId: 'my-x-axis', start: 0, end: 100 }])}>
        Reset zoom
      </Button>
      <Chart
        {...chartProps}
        zoom={zoom}
        onZoomChange={setZoom}
        xAxis={[
          {
            zoom: true,
            id: 'my-x-axis',
          },
        ]}
      />
    </div>
  );
}

@JCQuintas JCQuintas added new feature New feature or request component: charts This is the name of the generic UI component, not the React module! labels Jul 16, 2024
@JCQuintas JCQuintas self-assigned this Jul 16, 2024
export default function ZoomControlled() {
const [zoom, setZoom] = React.useState<ZoomData[]>([
{
axisId: 'my-x-axis',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently axisId is required. Should we allow {start,end} to be passed when there is only one zoom enabled?


// This function is used to initialize the zoom data when it is not provided by the user.
// It is helpful to avoid the need to provide the possibly auto-generated id for each axis.
export const initializeZoomData = (
Copy link
Member Author

@JCQuintas JCQuintas Jul 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the user can use an empty array in the controlled zoom. We then fill it up correctly on the first user interaction. Though I'm not sure we should enforce the correct usage from the start?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we should enforce the correct usage from the start?

I don't see issue asking users to start with the correct behavior.

I assume most of the use-cases will be useState([ { axisId: 'my-x-axis', start: 0, end: 100 } ])

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We got to intialize the data regardless for uncontrolled charts 😅

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From its usage it does not really look like an initializer.

I would expect that initializeZoomData is used to initialize the state. For example in the default value of the useControlledProps. But you use it at the beginning of every zoom interaction.

Either you consider it more as a cleaner function that ensure the axis are relevant with the options.
Then I would move the usage of this function in the value = React.useMemo(... of the provider to call it only once.

Or it's an initializer and it should be called once in the useControlledProps.

Notice that this solution does not support the case of a user adding/removing the zoom option of an axis. It's an edge case so no need for it to be fixed. Maybe other a highlight in the docs such as

You can not switch an axis from zoom: false to zoom: true.
The current workaround is to control the zoomData and add this new zoomable axis to it.

@mui-bot
Copy link

mui-bot commented Jul 16, 2024

docs/data/charts/zoom-and-pan/zoom-and-pan.md Outdated Show resolved Hide resolved
docs/data/charts/zoom-and-pan/zoom-and-pan.md Outdated Show resolved Hide resolved
docs/data/charts/zoom-and-pan/zoom-and-pan.md Outdated Show resolved Hide resolved
packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx Outdated Show resolved Hide resolved

// This function is used to initialize the zoom data when it is not provided by the user.
// It is helpful to avoid the need to provide the possibly auto-generated id for each axis.
export const initializeZoomData = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we should enforce the correct usage from the start?

I don't see issue asking users to start with the correct behavior.

I assume most of the use-cases will be useState([ { axisId: 'my-x-axis', start: 0, end: 100 } ])

Comment on lines 325 to 330
{ "name": "ZAxisContextProviderProps", "kind": "TypeAlias" },
{ "name": "ZoomContext", "kind": "Variable" },
{ "name": "ZoomData", "kind": "TypeAlias" },
{ "name": "ZoomOptions", "kind": "TypeAlias" },
{ "name": "ZoomProps", "kind": "TypeAlias" },
{ "name": "ZoomProvider", "kind": "Function" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about moving them in a .types.ts files such that we only export types

Suggested change
{ "name": "ZAxisContextProviderProps", "kind": "TypeAlias" },
{ "name": "ZoomContext", "kind": "Variable" },
{ "name": "ZoomData", "kind": "TypeAlias" },
{ "name": "ZoomOptions", "kind": "TypeAlias" },
{ "name": "ZoomProps", "kind": "TypeAlias" },
{ "name": "ZoomProvider", "kind": "Function" }
{ "name": "ZoomData", "kind": "TypeAlias" },
{ "name": "ZoomOptions", "kind": "TypeAlias" },
{ "name": "ZoomProps", "kind": "TypeAlias" },

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed it to only export things that are actually useful for the user. Also documented useZoom and <ZoomSetup/> a bit

JCQuintas and others added 4 commits July 17, 2024 16:56
Co-authored-by: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com>
Signed-off-by: Jose C Quintas Jr <juniorquintas@gmail.com>
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Jul 18, 2024
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Jul 18, 2024
@JCQuintas
Copy link
Member Author

@alexfauquette this is ready for review


// This function is used to initialize the zoom data when it is not provided by the user.
// It is helpful to avoid the need to provide the possibly auto-generated id for each axis.
export const initializeZoomData = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From its usage it does not really look like an initializer.

I would expect that initializeZoomData is used to initialize the state. For example in the default value of the useControlledProps. But you use it at the beginning of every zoom interaction.

Either you consider it more as a cleaner function that ensure the axis are relevant with the options.
Then I would move the usage of this function in the value = React.useMemo(... of the provider to call it only once.

Or it's an initializer and it should be called once in the useControlledProps.

Notice that this solution does not support the case of a user adding/removing the zoom option of an axis. It's an edge case so no need for it to be fixed. Maybe other a highlight in the docs such as

You can not switch an axis from zoom: false to zoom: true.
The current workaround is to control the zoomData and add this new zoomable axis to it.

Copy link
Member

@alexfauquette alexfauquette left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@JCQuintas JCQuintas merged commit 88b9a96 into mui:master Jul 23, 2024
17 checks passed
@JCQuintas JCQuintas deleted the zoom-controllable branch July 23, 2024 11:14
DungTiger pushed a commit to DungTiger/mui-x that referenced this pull request Jul 23, 2024
Signed-off-by: Jose C Quintas Jr <juniorquintas@gmail.com>
Co-authored-by: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com>
thomasmoon pushed a commit to thomasmoon/mui-x that referenced this pull request Sep 9, 2024
Signed-off-by: Jose C Quintas Jr <juniorquintas@gmail.com>
Co-authored-by: Alexandre Fauquette <45398769+alexfauquette@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: charts This is the name of the generic UI component, not the React module! new feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants