diff --git a/babel.config.js b/babel.config.js index 6d812eba0163..40d90dfbaae1 100644 --- a/babel.config.js +++ b/babel.config.js @@ -89,8 +89,8 @@ module.exports = function getBabelConfig(api) { '@babel/plugin-transform-runtime', { useESModules, - // any package needs to declare 7.4.4 as a runtime dependency. default is ^7.0.0 - version: '^7.4.4', + // any package needs to declare 7.25.0 as a runtime dependency. default is ^7.0.0 + version: process.env.MUI_BABEL_RUNTIME_VERSION || '^7.25.0', }, ], [ diff --git a/docs/data/common-concepts/custom-components/CustomSlot.js b/docs/data/common-concepts/custom-components/CustomSlot.js new file mode 100644 index 000000000000..9740551294d5 --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlot.js @@ -0,0 +1,13 @@ +import * as React from 'react'; +import FlightTakeoffIcon from '@mui/icons-material/FlightTakeoff'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +export default function CustomSlot() { + return ( + + + + ); +} diff --git a/docs/data/common-concepts/custom-components/CustomSlot.tsx b/docs/data/common-concepts/custom-components/CustomSlot.tsx new file mode 100644 index 000000000000..9740551294d5 --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlot.tsx @@ -0,0 +1,13 @@ +import * as React from 'react'; +import FlightTakeoffIcon from '@mui/icons-material/FlightTakeoff'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +export default function CustomSlot() { + return ( + + + + ); +} diff --git a/docs/data/common-concepts/custom-components/CustomSlot.tsx.preview b/docs/data/common-concepts/custom-components/CustomSlot.tsx.preview new file mode 100644 index 000000000000..d5fe738985f4 --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlot.tsx.preview @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/data/common-concepts/custom-components/CustomSlotAndSlotProps.js b/docs/data/common-concepts/custom-components/CustomSlotAndSlotProps.js new file mode 100644 index 000000000000..a6c3a5e036b7 --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlotAndSlotProps.js @@ -0,0 +1,20 @@ +import * as React from 'react'; +import FlightTakeoffIcon from '@mui/icons-material/FlightTakeoff'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +export default function CustomSlotAndSlotProps() { + return ( + + + + ); +} diff --git a/docs/data/common-concepts/custom-components/CustomSlotAndSlotProps.tsx b/docs/data/common-concepts/custom-components/CustomSlotAndSlotProps.tsx new file mode 100644 index 000000000000..a6c3a5e036b7 --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlotAndSlotProps.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; +import FlightTakeoffIcon from '@mui/icons-material/FlightTakeoff'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +export default function CustomSlotAndSlotProps() { + return ( + + + + ); +} diff --git a/docs/data/common-concepts/custom-components/CustomSlotAndSlotProps.tsx.preview b/docs/data/common-concepts/custom-components/CustomSlotAndSlotProps.tsx.preview new file mode 100644 index 000000000000..663cf8c57329 --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlotAndSlotProps.tsx.preview @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/docs/data/common-concepts/custom-components/CustomSlotProps.js b/docs/data/common-concepts/custom-components/CustomSlotProps.js new file mode 100644 index 000000000000..686f4e6898f8 --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlotProps.js @@ -0,0 +1,18 @@ +import * as React from 'react'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +export default function CustomSlotProps() { + return ( + + + + ); +} diff --git a/docs/data/common-concepts/custom-components/CustomSlotProps.tsx b/docs/data/common-concepts/custom-components/CustomSlotProps.tsx new file mode 100644 index 000000000000..686f4e6898f8 --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlotProps.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +export default function CustomSlotProps() { + return ( + + + + ); +} diff --git a/docs/data/common-concepts/custom-components/CustomSlotProps.tsx.preview b/docs/data/common-concepts/custom-components/CustomSlotProps.tsx.preview new file mode 100644 index 000000000000..023ce6ddb493 --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlotProps.tsx.preview @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.js b/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.js new file mode 100644 index 000000000000..e1272f2776ba --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.js @@ -0,0 +1,18 @@ +import * as React from 'react'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +export default function CustomSlotPropsCallback() { + return ( + + ({ + color: ownerState.open ? 'secondary' : 'primary', + }), + }} + /> + + ); +} diff --git a/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx b/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx new file mode 100644 index 000000000000..e1272f2776ba --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx @@ -0,0 +1,18 @@ +import * as React from 'react'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { DatePicker } from '@mui/x-date-pickers/DatePicker'; + +export default function CustomSlotPropsCallback() { + return ( + + ({ + color: ownerState.open ? 'secondary' : 'primary', + }), + }} + /> + + ); +} diff --git a/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx.preview b/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx.preview new file mode 100644 index 000000000000..100188718fae --- /dev/null +++ b/docs/data/common-concepts/custom-components/CustomSlotPropsCallback.tsx.preview @@ -0,0 +1,7 @@ + ({ + color: ownerState.open ? 'secondary' : 'primary', + }), + }} +/> \ No newline at end of file diff --git a/docs/data/common-concepts/custom-components/TypescriptCasting.js b/docs/data/common-concepts/custom-components/TypescriptCasting.js new file mode 100644 index 000000000000..4d0346ef92f1 --- /dev/null +++ b/docs/data/common-concepts/custom-components/TypescriptCasting.js @@ -0,0 +1,63 @@ +import * as React from 'react'; + +import Stack from '@mui/material/Stack'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import Switch from '@mui/material/Switch'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { DateCalendar } from '@mui/x-date-pickers/DateCalendar'; + +import { PickersCalendarHeader } from '@mui/x-date-pickers/PickersCalendarHeader'; + +function DisplayWeekNumberToggle({ value, onChange }) { + return ( + onChange(event.target.checked)} + /> + } + label="Display week number" + /> + ); +} + +function CustomCalendarHeader({ + displayWeekNumber, + setDisplayWeekNumber, + ...other +}) { + return ( + + + + + ); +} + +export default function TypescriptCasting() { + const [displayWeekNumber, setDisplayWeekNumber] = React.useState(false); + + return ( + + + + ); +} diff --git a/docs/data/common-concepts/custom-components/TypescriptCasting.tsx b/docs/data/common-concepts/custom-components/TypescriptCasting.tsx new file mode 100644 index 000000000000..2d68d2c1e6be --- /dev/null +++ b/docs/data/common-concepts/custom-components/TypescriptCasting.tsx @@ -0,0 +1,80 @@ +import * as React from 'react'; +import { Dayjs } from 'dayjs'; +import Stack from '@mui/material/Stack'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import Switch from '@mui/material/Switch'; +import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; +import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import { + DateCalendar, + DateCalendarSlots, + DateCalendarSlotProps, +} from '@mui/x-date-pickers/DateCalendar'; +import { PropsFromSlot } from '@mui/x-date-pickers/models'; +import { PickersCalendarHeader } from '@mui/x-date-pickers/PickersCalendarHeader'; + +function DisplayWeekNumberToggle({ + value, + onChange, +}: { + value: boolean; + onChange: (value: boolean) => void; +}) { + return ( + onChange(event.target.checked)} + /> + } + label="Display week number" + /> + ); +} + +interface CustomCalendarHeaderProps + extends PropsFromSlot['calendarHeader']> { + displayWeekNumber: boolean; + setDisplayWeekNumber: (displayWeekNumber: boolean) => void; +} + +function CustomCalendarHeader({ + displayWeekNumber, + setDisplayWeekNumber, + ...other +}: CustomCalendarHeaderProps) { + return ( + + + + + ); +} + +export default function TypescriptCasting() { + const [displayWeekNumber, setDisplayWeekNumber] = React.useState(false); + + return ( + + ['calendarHeader'], + }} + slotProps={{ + calendarHeader: { + displayWeekNumber, + setDisplayWeekNumber, + } as DateCalendarSlotProps['calendarHeader'], + }} + /> + + ); +} diff --git a/docs/data/common-concepts/custom-components/TypescriptCasting.tsx.preview b/docs/data/common-concepts/custom-components/TypescriptCasting.tsx.preview new file mode 100644 index 000000000000..461108b0d9c5 --- /dev/null +++ b/docs/data/common-concepts/custom-components/TypescriptCasting.tsx.preview @@ -0,0 +1,14 @@ +['calendarHeader'], + }} + slotProps={{ + calendarHeader: { + displayWeekNumber, + setDisplayWeekNumber, + } as DateCalendarSlotProps['calendarHeader'], + }} +/> \ No newline at end of file diff --git a/docs/data/common-concepts/custom-components/custom-components.md b/docs/data/common-concepts/custom-components/custom-components.md new file mode 100644 index 000000000000..28e37c605637 --- /dev/null +++ b/docs/data/common-concepts/custom-components/custom-components.md @@ -0,0 +1,252 @@ +# Custom slots and subcomponents + +

Learn how to override parts of the MUI X components.

+ +## What is a slot? + +A slot is a part of a component that can be [overridden](/x/common-concepts/custom-components/#how-to-override-a-slot) and/or [customized](/x/common-concepts/custom-components/#how-to-customize-a-slot). + +Some of those slots allow you to provide your own UI primitives to the MUI X components. +This is the role of all the `baseXXX` component on the `DataGrid` component (`baseButton`, `baseSelect`, ...). +These slots receive props that should be as generic as possible so that it is easy to interface any other design system. + +Other slots allow you to override parts of the MUI X UI components with a custom UI built specifically for this component. +This is the role of slots like `calendarHeader` on the `DateCalendar` component or `item` on the `RichTreeView` component. +These slots receive props specific to this part of the UI and will most likely not be re-use throughout your application. + +## Basic usage + +### How to override a slot? + +You can override a slot by providing a custom component to the `slots` prop: + +{{"demo": "CustomSlot.js"}} + +### How to customize a slot? + +You can pass props to any slot using the `slotProps` prop: + +{{"demo": "CustomSlotProps.js"}} + +You can also use both `slots` and `slotProps` on the same component: + +{{"demo": "CustomSlotAndSlotProps.js"}} + +Most slots also support a callback version of `slotProps`. +This callback receives an object that contains information about the current state of the component, +that information can vary depending on the slot being used: + +{{"demo": "CustomSlotPropsCallback.js"}} + +## Correct usage + +A slot is a React component; therefore, it should keep the same JavaScript reference between two renders. +If the JavaScript reference of component changes between two renders, React will remount it. +You can avoid it by not inlining the component definition in the `slots` prop. + +The first two examples below are buggy because the calendar header will remount after each keystroke, leading to a loss of focus. + +```jsx +// ❌ The `calendarHeader` slot is re-defined each time the parent component renders, +// causing the component to remount. +function MyApp() { + const [name, setName] = React.useState(''); + return ( + ( + setName(event.target.value)} /> + ), + }} + /> + ); +} +``` + +```jsx +// ❌ The `calendarHeader` slot is re-defined each time `name` is updated, +// causing the component to remount. +function MyApp() { + const [name, setName] = React.useState(''); + + const CustomCalendarHeader = React.useCallback( + () => setName(event.target.value)} />, + [name], + ); + + return ; +} +``` + +```jsx +// ✅ The `calendarHeader` slot is defined only once, it will never remount. +const CustomCalendarHeader = ({ name, setName }) => ( + setName(event.target.value)} /> +); + +function MyApp() { + const [name, setName] = React.useState(''); + return ( + + ); +} +``` + +## Usage with TypeScript + +### Type custom slots + +If you want to ensure type safety on your custom slot component, +you can declare your component using the `PropsFromSlot` interface: + +```tsx +function CustomCalendarHeader({ + currentMonth, +}: PropsFromSlot['calendarHeader']>) { + return
{currentMonth?.format('MM-DD-YYYY')}
; +} +``` + +:::success +The `PropsFromSlot` is exported from every package that supports slots: + +```ts +import { PropsFromSlot } from '@mui/x-data-grid/models'; +import { PropsFromSlot } from '@mui/x-date-pickers/models'; +// ... +``` + +It takes the slot type (as defined in the `slots` prop of your component) and returns the props that the slot receives. + +```ts +import { Dayjs } from 'dayjs'; +import { PropsFromSlot, GridSlots } from '@mui/x-data-grid'; +import { DateCalendarSlots } from '@mui/x-date-pickers'; + +type ToolbarProps = PropsFromSlot; + +// Most of the picker slots interfaces need to receive the date type as a generic. +type CalendarHeaderProps = PropsFromSlot['calendarHeader']>; +``` + +::: + +### Using additional props + +If you are passing additional props to your slot, you can add them to the props your custom component receives: + +```ts +interface CustomCalendarHeaderProps + extends PropsFromSlot['calendarHeader']> { + displayWeekNumber: boolean; + setDisplayWeekNumber: (displayWeekNumber: boolean) => void; +} +``` + +You can then use these props in your custom component and access both the props provided by the host component +and the props you added: + +```tsx +function CustomCalendarHeader({ + displayWeekNumber, + setDisplayWeekNumber, + ...other +}: CustomCalendarHeaderProps) { + return ( + + + + + ); +} +``` + +If your custom component has a different type than the default one, you will need to cast it to the correct type. +This can happen if you pass additional props to your custom component using `slotProps`. +If we take the example of the `calendarHeader` slot, you can cast your custom component as below: + +```tsx +function MyApp() { + const [displayWeekNumber, setDisplayWeekNumber] = React.useState(false); + return ( + ['calendarHeader'], + }} + slotProps={{ + calendarHeader: { + displayWeekNumber, + setDisplayWeekNumber, + } as DateCalendarSlotProps['calendarHeader'], + }} + /> + ); +} +``` + +{{"demo": "TypescriptCasting.js", "defaultCodeOpen": false}} + +### Using module augmentation + +If you are using one of the data grid packages, +you can also use [module augmentation](/x/react-data-grid/components/#custom-slot-props-with-typescript) to let TypeScript know about your custom props: + +```ts +declare module '@mui/x-data-grid' { + interface ToolbarPropsOverrides { + name: string; + setName: (name: string) => void; + } +} +``` + +You can then use your custom slot without any type casting: + +```tsx +function CustomToolbar({ name, setName }: PropsFromSlot) { + return setName(event.target.value)} />; +} + +function MyApp() { + const [name, setName] = React.useState(''); + return ( + + ); +} +``` + +See [Data Grid - Custom slots and subcomponents—Custom slot props with TypeScript](/x/react-data-grid/components/#custom-slot-props-with-typescript) for more details. + +:::warning +The module augmentation feature isn't implemented yet for the other sets of components. It's coming. + +- 👍 Upvote [issue 9775](https://github.com/mui/mui-x/issues/9775) if you want to see it land faster on the Date and Time Pickers. +- 👍 Upvote [issue 14063](https://github.com/mui/mui-x/issues/14063) if you want to see it land faster on the Charts. +- 👍 Upvote [issue 14062](https://github.com/mui/mui-x/issues/14062) if you want to see it land faster on the Tree View. + + ::: + +## Slots of the X components + +You can find the list of slots in the API documentation of each component (e.g. [DataGrid](/x/api/data-grid/data-grid/#slots), [DatePicker](/x/api/date-pickers/date-picker/#slots), [BarChart](/x/api/charts/bar-chart/#slots) or [RichTreeView](/x/api/tree-view/rich-tree-view/#slots)). + +Most of the slots have a standalone doc example to show how to use them: + +- [Data Grid—Custom slots and subcomponents](/x/react-data-grid/components/) +- [Date Picker—Custom slots and subcomponents](/x/react-date-pickers/custom-components/) +- [RichTreeView—Customization](/x/react-tree-view/rich-tree-view/customization/) / [SimpleTreeView—Customization](/x/react-tree-view/simple-tree-view/customization/) diff --git a/docs/data/data-grid/column-menu/column-menu.md b/docs/data/data-grid/column-menu/column-menu.md index fcbe4a8b40dd..cb20213f0d60 100644 --- a/docs/data/data-grid/column-menu/column-menu.md +++ b/docs/data/data-grid/column-menu/column-menu.md @@ -126,7 +126,7 @@ As a reference, here are the column menu `slots` along with the default item com ## Custom menu component -You can also customize and replace the column menu by [passing a fully custom component](/x/react-data-grid/components/#overriding-components) to the `columnMenu` slot of the Data Grid. If you want to add some of the default menu items to your custom component, you can import and re-use them. +You can also customize and replace the column menu by [passing a fully custom component](/x/react-data-grid/components/#component-slots) to the `columnMenu` slot of the Data Grid. If you want to add some of the default menu items to your custom component, you can import and re-use them. {{"demo": "CustomColumnMenuGrid.js", "bg": "inline"}} diff --git a/docs/data/data-grid/components/components.md b/docs/data/data-grid/components/components.md index 6d78d7487beb..af1eb59c460f 100644 --- a/docs/data/data-grid/components/components.md +++ b/docs/data/data-grid/components/components.md @@ -1,43 +1,8 @@ -# Data Grid - Custom subcomponents +# Data Grid - Custom slots and subcomponents -

The grid is highly customizable. Override components using the slots prop.

+

Learn how to override parts of the grid.

-## Overriding components - -As part of the customization API, the Data Grid allows you to override internal components with the `slots` prop. -The prop accepts an object of type [`GridSlotsComponent`](/x/api/data-grid/data-grid/#slots). - -If you wish to pass additional props in a component slot, you can do it using the `slotProps` prop. -This prop is of type `GridSlotsComponentsProps`. Note that if you do and you use TypeScript, you'll need to cast your custom component so it can fit in the slot type. - -As an example, you could override the column menu and pass additional props as below. - -```tsx - -``` - -If you want to ensure type safety, you can declare your component using the slot props typings: - -```tsx -import { GridSlotProps } from '@mui/x-data-grid'; - -function MyCustomColumnMenu( - props: GridSlotProps['columnMenu'] & { background: string; counter: number }, -) { - // ... -} -``` - -### Interacting with the data grid +## Interacting with the data grid The grid exposes two hooks to help you access the data grid data while overriding component slots. @@ -64,7 +29,12 @@ function CustomPagination() { ## Component slots -The full list of overridable component slots can be found on the [`GridSlotsComponent`](/x/api/data-grid/data-grid/#slots) API page. +:::success + +- See [Common concepts—Custom slots and subcomponents](/x/common-concepts/custom-components/) to learn how to use slots. +- See [`GridSlotsComponent`](/x/api/data-grid/data-grid/#slots) to learn about the available slots. + + ::: ### Column menu @@ -153,22 +123,13 @@ As any component slot, every icon can be customized. However, it is not yet poss See the [Overlays](/x/react-data-grid/overlays/) documentation on how to customize the `loadingOverlay`, `noRowsOverlay`, and `noResultsOverlay`. -## Slot props - -To override default props or pass custom props to slot components, use the `slotProps` prop. +## Custom slot props with TypeScript -```tsx - -``` +:::success +This section focuses on module augmentation. -### Custom slot props with TypeScript +See [Custom slots and subcomponents—Usage with TypeScript](/x/common-concepts/custom-components/#usage-with-typescript) if you don't want to use this approach. +::: If the custom component requires additional props to work properly, TypeScript may throw type errors. To solve these type errors, use [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation) to enhance the props interface. @@ -201,7 +162,7 @@ declare module '@mui/x-data-grid' { }} slotProps={{ toolbar: { - // props required by CustomGridToolbar + // props used by CustomGridToolbar someCustomString: 'Hello', someCustomNumber: 42, }, @@ -225,7 +186,7 @@ declare module '@mui/x-data-grid-pro' { }} slotProps={{ toolbar: { - // props required by CustomGridToolbar + // props used by CustomGridToolbar someCustomString: 'Hello', someCustomNumber: 42, }, @@ -249,7 +210,7 @@ declare module '@mui/x-data-grid-premium' { }} slotProps={{ toolbar: { - // props required by CustomGridToolbar + // props used by CustomGridToolbar someCustomString: 'Hello', someCustomNumber: 42, }, diff --git a/docs/data/data-grid/filtering/customization.md b/docs/data/data-grid/filtering/customization.md index 83566d25d21e..5d55919b988e 100644 --- a/docs/data/data-grid/filtering/customization.md +++ b/docs/data/data-grid/filtering/customization.md @@ -147,7 +147,7 @@ const ratingColumnType: GridColTypeDef = { ## Custom filter panel -You can customize the rendering of the filter panel as shown in [the component section](/x/react-data-grid/components/#overriding-components) of the documentation. +You can customize the rendering of the filter panel as shown in [the component section](/x/react-data-grid/components/#component-slots) of the documentation. ### Customize the filter panel content diff --git a/docs/data/date-pickers/custom-components/custom-components.md b/docs/data/date-pickers/custom-components/custom-components.md index 65034ecb8882..023e89cb0a05 100644 --- a/docs/data/date-pickers/custom-components/custom-components.md +++ b/docs/data/date-pickers/custom-components/custom-components.md @@ -6,94 +6,17 @@ components: DateTimePickerTabs, PickersActionBar, DatePickerToolbar, TimePickerT # Custom slots and subcomponents -

Learn how to override the default DOM structure of the Date and Time Pickers.

+

Learn how to override parts of the Date and Time Pickers.

:::info The components that can be customized are listed under `slots` section in Date and Time Pickers [API Reference](/x/api/date-pickers/). For example, available Date Picker slots can be found [here](/x/api/date-pickers/date-picker/#slots). ::: -## Overriding slot components - -You can override the internal elements of the component (known as "slots") using the `slots` prop. - -Use the `slotProps` prop if you need to pass additional props to a component slot. - -As an example, you could override the `ActionBar` and pass additional props to the custom component as shown below: - -```jsx - with a custom one - actionBar: CustomActionBar, - }} - slotProps={{ - // pass props `actions={['clear']}` to the actionBar slot - actionBar: { actions: ['clear'] }, - }} -/> -``` - -To modify components position, have a look at the [custom layout](/x/react-date-pickers/custom-layout/) docs page. - -### Recommended usage - :::success -Remember to pass a reference to the component instead of an inline render function and define it outside the main component. -This ensures that the component is not remounted on every update. +See [Common concepts—Custom slots and subcomponents](/x/common-concepts/custom-components/) to learn how to use slots. ::: -The first two examples below are buggy because the toolbar will remount after each keystroke, leading to a loss of focus. - -```jsx -// ❌ The `toolbar` slot is re-defined each time the parent component renders, -// causing the component to remount. -function MyApp() { - return ( - ( - setName(event.target.value)} /> - ), - }} - /> - ); -} -``` - -```jsx -// ❌ The `toolbar` slot is re-defined each time `name` is updated, -// causing the component to remount. -function MyApp() { - const [name, setName] = React.useState(''); - - const CustomToolbar = React.useCallback( - () => setName(event.target.value)} />, - [name], - ); - - return ; -} -``` - -```jsx -// ✅ The `toolbar` slot is defined only once, it will never remount. -const CustomToolbar = ({ name, setName }) => ( - setName(event.target.value)} /> -); - -function MyApp() { - const [name, setName] = React.useState(''); - return ( - - ); -} -``` - ## Action bar ### Component props diff --git a/docs/data/date-pickers/custom-field/custom-field.md b/docs/data/date-pickers/custom-field/custom-field.md index bb3301d7bf66..b58ea51d833f 100644 --- a/docs/data/date-pickers/custom-field/custom-field.md +++ b/docs/data/date-pickers/custom-field/custom-field.md @@ -10,6 +10,10 @@ components: PickersSectionList, PickersTextField

The Date and Time Pickers let you customize the field by passing props or custom components

+:::success +See [Common concepts—Custom slots and subcomponents](/x/common-concepts/custom-components/) to learn how to use slots. +::: + ## Customize the default field ### Customize the `TextField` diff --git a/docs/data/date-pickers/custom-layout/custom-layout.md b/docs/data/date-pickers/custom-layout/custom-layout.md index 7a26bee7a059..421e80851236 100644 --- a/docs/data/date-pickers/custom-layout/custom-layout.md +++ b/docs/data/date-pickers/custom-layout/custom-layout.md @@ -10,6 +10,10 @@ packageName: '@mui/x-date-pickers'

The Date and Time Pickers let you reorganize the layout

+:::success +See [Common concepts—Custom slots and subcomponents](/x/common-concepts/custom-components/) to learn how to use slots. +::: + ## Default layout structure By default, pickers are made of 5 subcomponents present in the following order: diff --git a/docs/data/date-pickers/custom-opening-button/custom-opening-button.md b/docs/data/date-pickers/custom-opening-button/custom-opening-button.md index 4dadc61d97e0..2e71fe686d5b 100644 --- a/docs/data/date-pickers/custom-opening-button/custom-opening-button.md +++ b/docs/data/date-pickers/custom-opening-button/custom-opening-button.md @@ -7,6 +7,10 @@ title: Date and Time Pickers - Custom opening button

The date picker lets you customize the button to open the views.

+:::success +See [Common concepts—Custom slots and subcomponents](/x/common-concepts/custom-components/) to learn how to use slots. +::: + ## Set a custom opening icon If you want to change the icon opening the picker without changing its behavior, you can use the `openPickerIcon` slot: diff --git a/docs/data/date-pickers/experimentation/CustomField.js b/docs/data/date-pickers/experimentation/CustomField.js index 109be3934956..376159d6793a 100644 --- a/docs/data/date-pickers/experimentation/CustomField.js +++ b/docs/data/date-pickers/experimentation/CustomField.js @@ -1,11 +1,10 @@ import * as React from 'react'; import dayjs from 'dayjs'; +import TextField from '@mui/material/TextField'; import { DemoContainer } from '@mui/x-date-pickers/internals/demo'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { DatePicker } from '@mui/x-date-pickers/DatePicker'; -import TextField from '@mui/material/TextField'; - import { useValidation, validateDate } from '@mui/x-date-pickers/validation'; import { splitFieldInternalAndForwardedProps } from '@mui/x-date-pickers/internals'; diff --git a/docs/data/pages.ts b/docs/data/pages.ts index dfa4c550422e..68a022f3d6aa 100644 --- a/docs/data/pages.ts +++ b/docs/data/pages.ts @@ -12,7 +12,6 @@ const pages: MuiPage[] = [ { pathname: '/x/introduction-group', title: 'Introduction', - children: [ { pathname: `/x/introduction`, title: 'Overview' }, { pathname: `/x/introduction/installation` }, @@ -21,6 +20,13 @@ const pages: MuiPage[] = [ { pathname: `/x/introduction/roadmap` }, ], }, + { + pathname: '/x/common-features-group', + title: 'Common concepts', + children: [ + { pathname: `/x/common-concepts/custom-components`, title: 'Custom slots and subcomponents' }, + ], + }, { pathname: '/x/react-data-grid-group', title: 'Data Grid', @@ -88,7 +94,7 @@ const pages: MuiPage[] = [ { pathname: '/x/react-data-grid/export' }, { pathname: '/x/react-data-grid/clipboard', title: 'Copy and paste', newFeature: true }, { pathname: '/x/react-data-grid/overlays', title: 'Overlays' }, - { pathname: '/x/react-data-grid/components', title: 'Custom subcomponents' }, + { pathname: '/x/react-data-grid/components', title: 'Custom slots and subcomponents' }, { pathname: '/x/react-data-grid/style-group', title: 'Style', diff --git a/docs/data/tree-view/rich-tree-view/customization/customization.md b/docs/data/tree-view/rich-tree-view/customization/customization.md index 4bedda31d764..d8172900c158 100644 --- a/docs/data/tree-view/rich-tree-view/customization/customization.md +++ b/docs/data/tree-view/rich-tree-view/customization/customization.md @@ -11,6 +11,10 @@ waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/

Learn how to customize the Rich Tree View component.

+:::success +See [Common concepts—Custom slots and subcomponents](/x/common-concepts/custom-components/) to learn how to use slots. +::: + ## Basics ### Custom icons diff --git a/docs/data/tree-view/simple-tree-view/customization/customization.md b/docs/data/tree-view/simple-tree-view/customization/customization.md index 7cf009836436..3774ec10f6ea 100644 --- a/docs/data/tree-view/simple-tree-view/customization/customization.md +++ b/docs/data/tree-view/simple-tree-view/customization/customization.md @@ -11,6 +11,10 @@ waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/

Learn how to customize the Simple Tree View component.

+:::success +See [Common concepts—Custom slots and subcomponents](/x/common-concepts/custom-components/) to learn how to use slots. +::: + ## Basics ### Custom icons diff --git a/docs/package.json b/docs/package.json index 354bbbf5f160..cecbb3be2310 100644 --- a/docs/package.json +++ b/docs/package.json @@ -78,7 +78,7 @@ "moment-timezone": "^0.5.45", "next": "^14.2.7", "nprogress": "^0.2.0", - "postcss": "^8.4.41", + "postcss": "^8.4.44", "prismjs": "^1.29.0", "prop-types": "^15.8.1", "react": "^18.3.1", @@ -93,7 +93,7 @@ "recast": "^0.23.9", "rimraf": "^5.0.10", "rxjs": "^7.8.1", - "styled-components": "^6.1.12", + "styled-components": "^6.1.13", "stylis": "^4.3.4", "stylis-plugin-rtl": "^2.1.1", "webpack-bundle-analyzer": "^4.10.2" diff --git a/docs/pages/x/common-concepts/custom-components.js b/docs/pages/x/common-concepts/custom-components.js new file mode 100644 index 000000000000..51a99e446b11 --- /dev/null +++ b/docs/pages/x/common-concepts/custom-components.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs'; +import * as pageProps from 'docsx/data/common-concepts/custom-components/custom-components.md?muiMarkdown'; + +export default function Page() { + return ; +} diff --git a/package.json b/package.json index 5b33fe8d2b7e..785d9395916a 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "@mui/internal-markdown": "^1.0.11", "@mui/internal-test-utils": "^1.0.11", "@mui/material": "^5.16.7", - "@mui/monorepo": "github:mui/material-ui#8b8732eabd272226fdc858cdfc1dce8b0ce4b294", + "@mui/monorepo": "github:mui/material-ui#f8b2251c5bdfe4d81f56017e0423d265b242617d", "@mui/utils": "^5.16.6", "@next/eslint-plugin-next": "14.2.7", "@octokit/plugin-retry": "^7.1.1", @@ -143,7 +143,7 @@ "eslint-import-resolver-webpack": "^0.13.8", "eslint-plugin-filenames": "^1.3.2", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsdoc": "^48.11.0", + "eslint-plugin-jsdoc": "^50.2.2", "eslint-plugin-jsx-a11y": "^6.9.0", "eslint-plugin-material-ui": "workspace:^", "eslint-plugin-mocha": "^10.5.0", @@ -187,7 +187,7 @@ "stream-browserify": "^3.0.0", "string-replace-loader": "^3.1.0", "terser-webpack-plugin": "^5.3.10", - "tsx": "^4.18.0", + "tsx": "^4.19.0", "typescript": "^5.5.4", "unist-util-visit": "^5.0.0", "util": "^0.12.5", diff --git a/packages/x-charts-pro/package.json b/packages/x-charts-pro/package.json index cceb2b2915e6..765359ab82d3 100644 --- a/packages/x-charts-pro/package.json +++ b/packages/x-charts-pro/package.json @@ -43,6 +43,7 @@ "@mui/utils": "^5.16.6", "@mui/x-charts": "workspace:*", "@mui/x-charts-vendor": "workspace:*", + "@mui/x-internals": "workspace:*", "@mui/x-license": "workspace:*", "@react-spring/rafz": "^9.7.4", "@react-spring/web": "^9.7.4", diff --git a/packages/x-charts-pro/tsconfig.build.json b/packages/x-charts-pro/tsconfig.build.json index bf4eaef647d2..d85b5e559d65 100644 --- a/packages/x-charts-pro/tsconfig.build.json +++ b/packages/x-charts-pro/tsconfig.build.json @@ -13,6 +13,7 @@ }, "references": [ { "path": "../x-charts/tsconfig.build.json" }, + { "path": "../x-internals/tsconfig.build.json" }, { "path": "../x-license/tsconfig.build.json" } ], "include": ["src/**/*.ts*"], diff --git a/packages/x-charts/package.json b/packages/x-charts/package.json index f11292365784..bf10d935f48c 100644 --- a/packages/x-charts/package.json +++ b/packages/x-charts/package.json @@ -42,6 +42,7 @@ "@babel/runtime": "^7.25.6", "@mui/utils": "^5.16.6", "@mui/x-charts-vendor": "workspace:*", + "@mui/x-internals": "workspace:*", "@react-spring/rafz": "^9.7.4", "@react-spring/web": "^9.7.4", "clsx": "^2.1.1", diff --git a/packages/x-charts/src/models/index.ts b/packages/x-charts/src/models/index.ts index abb5d36002f6..1b370c0ec5fe 100644 --- a/packages/x-charts/src/models/index.ts +++ b/packages/x-charts/src/models/index.ts @@ -8,3 +8,6 @@ export type { ScaleName, ContinuousScaleName, } from './axis'; + +// Utils shared across the X packages +export type { PropsFromSlot } from '@mui/x-internals/slots'; diff --git a/packages/x-charts/tsconfig.build.json b/packages/x-charts/tsconfig.build.json index d67bc4572b32..60d43624f21d 100644 --- a/packages/x-charts/tsconfig.build.json +++ b/packages/x-charts/tsconfig.build.json @@ -18,6 +18,7 @@ "csstype" ] }, + "references": [{ "path": "../x-internals/tsconfig.build.json" }], "include": ["src/**/*.ts*"], "exclude": ["src/**/*.spec.ts*", "src/**/*.test.ts*", "src/tests/**/*"] } diff --git a/packages/x-data-grid-premium/package.json b/packages/x-data-grid-premium/package.json index 73534e27b251..e1ca45ae61c6 100644 --- a/packages/x-data-grid-premium/package.json +++ b/packages/x-data-grid-premium/package.json @@ -53,7 +53,7 @@ "clsx": "^2.1.1", "exceljs": "^4.4.0", "prop-types": "^15.8.1", - "reselect": "^5.1.0" + "reselect": "^5.1.1" }, "peerDependencies": { "@emotion/react": "^11.9.0", diff --git a/packages/x-data-grid-pro/package.json b/packages/x-data-grid-pro/package.json index 9320a943cff6..c6fb3c9a6fcb 100644 --- a/packages/x-data-grid-pro/package.json +++ b/packages/x-data-grid-pro/package.json @@ -51,7 +51,7 @@ "@types/format-util": "^1.0.4", "clsx": "^2.1.1", "prop-types": "^15.8.1", - "reselect": "^5.1.0" + "reselect": "^5.1.1" }, "peerDependencies": { "@emotion/react": "^11.9.0", diff --git a/packages/x-data-grid/package.json b/packages/x-data-grid/package.json index 8566b23f1c3f..e6b2f7e04ace 100644 --- a/packages/x-data-grid/package.json +++ b/packages/x-data-grid/package.json @@ -52,7 +52,7 @@ "@mui/x-internals": "workspace:*", "clsx": "^2.1.1", "prop-types": "^15.8.1", - "reselect": "^5.1.0" + "reselect": "^5.1.1" }, "peerDependencies": { "@emotion/react": "^11.9.0", diff --git a/packages/x-data-grid/src/components/containers/GridRootStyles.ts b/packages/x-data-grid/src/components/containers/GridRootStyles.ts index ccb1624f0d2a..0c574a7bf3c7 100644 --- a/packages/x-data-grid/src/components/containers/GridRootStyles.ts +++ b/packages/x-data-grid/src/components/containers/GridRootStyles.ts @@ -299,12 +299,13 @@ export const GridRootStyles = styled('div', { `]: { [`& .${c.columnSeparator}`]: { opacity: 0, - '@media (hover: none)': { + }, + // Show resizable separators at all times on touch devices + '@media (hover: none)': { + [`& .${c['columnSeparator--resizable']}`]: { opacity: 1, - color: (t.vars || t).palette.primary.main, }, }, - // Show resizable separators again when the column is hovered [`& .${c['columnSeparator--resizable']}:hover`]: { opacity: 1, }, @@ -411,6 +412,14 @@ export const GridRootStyles = styled('div', { }, '@media (hover: none)': { [`& .${c.columnHeader}`]: columnHeaderStyles, + [`& .${c.columnHeader}:focus, + & .${c.columnHeader}:focus-within, + & .${c.columnHeader}:has(+ .${c.columnHeader}:focus), + & .${c.columnHeader}:has(+ .${c.columnHeader}:focus-within)`]: { + [`.${c['columnSeparator--resizable']}`]: { + color: (t.vars || t).palette.primary.main, + }, + }, }, [`& .${c['columnSeparator--sideLeft']}`]: { left: columnSeparatorOffset, @@ -427,16 +436,17 @@ export const GridRootStyles = styled('div', { [`& .${c['columnSeparator--resizable']}`]: { cursor: 'col-resize', touchAction: 'none', + [`&.${c['columnSeparator--resizing']}`]: { + color: (t.vars || t).palette.primary.main, + }, // Always appear as draggable on touch devices '@media (hover: none)': { [`& .${c.iconSeparator} rect`]: separatorIconDragStyles, - color: borderColor, }, - [`&:hover, &.${c['columnSeparator--resizing']}`]: { - color: (t.vars || t).palette.primary.main, - [`& .${c.iconSeparator} rect`]: separatorIconDragStyles, - '@media (hover: none)': { - color: borderColor, + '@media (hover: hover)': { + '&:hover': { + color: (t.vars || t).palette.primary.main, + [`& .${c.iconSeparator} rect`]: separatorIconDragStyles, }, }, '& svg': { diff --git a/packages/x-data-grid/src/models/index.ts b/packages/x-data-grid/src/models/index.ts index e7761edb34ad..cbef8f09c1e4 100644 --- a/packages/x-data-grid/src/models/index.ts +++ b/packages/x-data-grid/src/models/index.ts @@ -35,3 +35,6 @@ export type { GridPrintExportOptions, } from './gridExport'; export * from './gridFilterOperator'; + +// Utils shared across the X packages +export type { PropsFromSlot } from '@mui/x-internals/slots'; diff --git a/packages/x-date-pickers-pro/package.json b/packages/x-date-pickers-pro/package.json index c93e75124ef1..6035608cf2ec 100644 --- a/packages/x-date-pickers-pro/package.json +++ b/packages/x-date-pickers-pro/package.json @@ -45,6 +45,7 @@ "@babel/runtime": "^7.25.6", "@mui/utils": "^5.16.6", "@mui/x-date-pickers": "workspace:*", + "@mui/x-internals": "workspace:*", "@mui/x-license": "workspace:*", "clsx": "^2.1.1", "prop-types": "^15.8.1", diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx index 4fb1f4622428..f03de14dc1b6 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/MultiInputDateRangeField.tsx @@ -22,7 +22,7 @@ import { MultiInputDateRangeFieldSlotProps, } from './MultiInputDateRangeField.types'; import { useMultiInputDateRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateRangeField'; -import { MultiInputRangeFieldClasses, RangePosition, UseDateRangeFieldProps } from '../models'; +import { MultiInputRangeFieldClasses, RangePosition } from '../models'; export const multiInputDateRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses( 'MuiMultiInputDateRangeField', @@ -91,10 +91,7 @@ const MultiInputDateRangeField = React.forwardRef(function MultiInputDateRangeFi name: 'MuiMultiInputDateRangeField', }); - const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps< - typeof themeProps, - keyof Omit, 'clearable' | 'onClear'> - >(themeProps, 'date'); + const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps(themeProps, 'date'); const { slots, diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/tests/MultiInputDateRangeField.validation.test.tsx b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/tests/MultiInputDateRangeField.validation.test.tsx deleted file mode 100644 index 8552a54ddb71..000000000000 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/tests/MultiInputDateRangeField.validation.test.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { MultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; -import { - createPickerRenderer, - adapterToUse, - describeRangeValidation, - setValueOnFieldInput, -} from 'test/utils/pickers'; - -describe('', () => { - const { render, clock } = createPickerRenderer({ clock: 'fake' }); - - describeRangeValidation(MultiInputDateRangeField, () => ({ - render, - clock, - componentFamily: 'field', - views: ['year', 'month', 'day'], - setValue: (value, { setEndDate } = {}) => { - setValueOnFieldInput(adapterToUse.format(value, 'keyboardDate'), setEndDate ? 1 : 0); - }, - })); -}); diff --git a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/tests/describes.MultiInputDateRangeField.test.tsx b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/tests/describes.MultiInputDateRangeField.test.tsx index 6ba21a354f09..f9bc34a2c12b 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateRangeField/tests/describes.MultiInputDateRangeField.test.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateRangeField/tests/describes.MultiInputDateRangeField.test.tsx @@ -1,10 +1,15 @@ import * as React from 'react'; import { MultiInputDateRangeField } from '@mui/x-date-pickers-pro/MultiInputDateRangeField'; -import { createPickerRenderer } from 'test/utils/pickers'; +import { + adapterToUse, + createPickerRenderer, + describeRangeValidation, + setValueOnFieldInput, +} from 'test/utils/pickers'; import { describeConformance } from 'test/utils/describeConformance'; describe('', () => { - const { render } = createPickerRenderer(); + const { render, clock } = createPickerRenderer({ clock: 'fake' }); describeConformance(, () => ({ classes: {} as any, @@ -14,4 +19,14 @@ describe('', () => { refInstanceof: window.HTMLDivElement, skip: ['themeVariants', 'componentProp', 'componentsProp'], })); + + describeRangeValidation(MultiInputDateRangeField, () => ({ + render, + clock, + componentFamily: 'field', + views: ['year', 'month', 'day'], + setValue: (value, { setEndDate } = {}) => { + setValueOnFieldInput(adapterToUse.format(value, 'keyboardDate'), setEndDate ? 1 : 0); + }, + })); }); diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx index 95eee8c613eb..25fc8def4ee6 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/MultiInputDateTimeRangeField.tsx @@ -22,7 +22,6 @@ import { MultiInputDateTimeRangeFieldSlotProps, } from './MultiInputDateTimeRangeField.types'; import { useMultiInputDateTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputDateTimeRangeField'; -import { UseDateTimeRangeFieldProps } from '../internals/models/dateTimeRange'; import { MultiInputRangeFieldClasses, RangePosition } from '../models'; export const multiInputDateTimeRangeFieldClasses: MultiInputRangeFieldClasses = @@ -90,10 +89,10 @@ const MultiInputDateTimeRangeField = React.forwardRef(function MultiInputDateTim name: 'MuiMultiInputDateTimeRangeField', }); - const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps< - typeof themeProps, - keyof Omit, 'clearable' | 'onClear'> - >(themeProps, 'date-time'); + const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps( + themeProps, + 'date-time', + ); const { slots, diff --git a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/describes.MultiInputDateTimeRangeField.test.tsx b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/describes.MultiInputDateTimeRangeField.test.tsx index 5bc464f729e5..1ece3e03f108 100644 --- a/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/describes.MultiInputDateTimeRangeField.test.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputDateTimeRangeField/tests/describes.MultiInputDateTimeRangeField.test.tsx @@ -9,7 +9,7 @@ import { import { describeConformance } from 'test/utils/describeConformance'; describe('', () => { - const { render, clock } = createPickerRenderer(); + const { render, clock } = createPickerRenderer({ clock: 'fake' }); describeConformance(, () => ({ classes: {} as any, diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx index a682b755b87b..adfca0f3dd58 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/MultiInputTimeRangeField.tsx @@ -22,7 +22,6 @@ import { MultiInputTimeRangeFieldSlotProps, } from './MultiInputTimeRangeField.types'; import { useMultiInputTimeRangeField } from '../internals/hooks/useMultiInputRangeField/useMultiInputTimeRangeField'; -import { UseTimeRangeFieldProps } from '../internals/models/timeRange'; import { MultiInputRangeFieldClasses, RangePosition } from '../models'; export const multiInputTimeRangeFieldClasses: MultiInputRangeFieldClasses = generateUtilityClasses( @@ -92,10 +91,7 @@ const MultiInputTimeRangeField = React.forwardRef(function MultiInputTimeRangeFi name: 'MuiMultiInputTimeRangeField', }); - const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps< - typeof themeProps, - keyof Omit, 'clearable' | 'onClear'> - >(themeProps, 'time'); + const { internalProps, forwardedProps } = splitFieldInternalAndForwardedProps(themeProps, 'time'); const { slots, diff --git a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/describes.MultiInputTimeRangeField.test.tsx b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/describes.MultiInputTimeRangeField.test.tsx index f25cd1cd33f4..16dff90eca73 100644 --- a/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/describes.MultiInputTimeRangeField.test.tsx +++ b/packages/x-date-pickers-pro/src/MultiInputTimeRangeField/tests/describes.MultiInputTimeRangeField.test.tsx @@ -9,7 +9,7 @@ import { import { describeConformance } from 'test/utils/describeConformance'; describe('', () => { - const { render, clock } = createPickerRenderer(); + const { render, clock } = createPickerRenderer({ clock: 'fake' }); describeConformance(, () => ({ classes: {} as any, diff --git a/packages/x-date-pickers-pro/tsconfig.build.json b/packages/x-date-pickers-pro/tsconfig.build.json index 08e5c49be00c..e61dc5932044 100644 --- a/packages/x-date-pickers-pro/tsconfig.build.json +++ b/packages/x-date-pickers-pro/tsconfig.build.json @@ -13,7 +13,8 @@ }, "references": [ { "path": "../x-date-pickers/tsconfig.build.json" }, - { "path": "../x-license/tsconfig.build.json" } + { "path": "../x-license/tsconfig.build.json" }, + { "path": "../x-internals/tsconfig.build.json" } ], "include": ["./src/**/*.ts*"], "exclude": ["src/**/*.spec.ts*", "src/**/*.test.ts*", "src/tests/**/*"] diff --git a/packages/x-date-pickers/package.json b/packages/x-date-pickers/package.json index 05688ddbfe25..7d125dfb1840 100644 --- a/packages/x-date-pickers/package.json +++ b/packages/x-date-pickers/package.json @@ -47,6 +47,7 @@ "dependencies": { "@babel/runtime": "^7.25.6", "@mui/utils": "^5.16.6", + "@mui/x-internals": "workspace:*", "@types/react-transition-group": "^4.4.11", "clsx": "^2.1.1", "prop-types": "^15.8.1", diff --git a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx index 0e9097ef1eae..28302b615c08 100644 --- a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx +++ b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.tsx @@ -6,6 +6,7 @@ import useForkRef from '@mui/utils/useForkRef'; import useId from '@mui/utils/useId'; import { PickersPopper } from '../../components/PickersPopper'; import { + UseDesktopPickerOwnerState, UseDesktopPickerParams, UseDesktopPickerProps, UseDesktopPickerSlotProps, @@ -90,6 +91,11 @@ export const useDesktopPicker = < wrapperVariant: 'desktop', }); + // TODO v8: Apply this ownerState to all the slots in this hook. + const ownerStateV8: UseDesktopPickerOwnerState = { + open, + }; + const InputAdornment = slots.inputAdornment ?? MuiInputAdornment; const { ownerState: inputAdornmentOwnerState, ...inputAdornmentProps } = useSlotProps({ elementType: InputAdornment, @@ -114,6 +120,11 @@ export const useDesktopPicker = < }); const OpenPickerIcon = slots.openPickerIcon; + const openPickerIconProps = useSlotProps({ + elementType: OpenPickerIcon, + externalSlotProps: innerSlotProps?.openPickerIcon, + ownerState: ownerStateV8, + }); const Field = slots.field; const fieldProps = useSlotProps< @@ -163,7 +174,7 @@ export const useDesktopPicker = < [`${inputAdornmentProps.position}Adornment`]: ( - + ), diff --git a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts index 59ff56096d93..c9cc83019e06 100644 --- a/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts +++ b/packages/x-date-pickers/src/internals/hooks/useDesktopPicker/useDesktopPicker.types.ts @@ -71,6 +71,10 @@ export interface UseDesktopPickerSlotProps< > extends ExportedUseDesktopPickerSlotProps, Pick, 'toolbar'> {} +export interface UseDesktopPickerOwnerState { + open: boolean; +} + export interface ExportedUseDesktopPickerSlotProps< TDate extends PickerValidDate, TView extends DateOrTimeViewWithMeridiem, @@ -96,7 +100,7 @@ export interface ExportedUseDesktopPickerSlotProps< {}, UseDesktopPickerProps >; - openPickerIcon?: Record; + openPickerIcon?: SlotComponentPropsFromProps, {}, UseDesktopPickerOwnerState>; } export interface DesktopOnlyPickerProps diff --git a/packages/x-date-pickers/src/models/index.ts b/packages/x-date-pickers/src/models/index.ts index 1bfcf091432b..06374a006750 100644 --- a/packages/x-date-pickers/src/models/index.ts +++ b/packages/x-date-pickers/src/models/index.ts @@ -5,3 +5,6 @@ export * from './views'; export * from './adapters'; export * from './common'; export * from './pickers'; + +// Utils shared across the X packages +export type { PropsFromSlot } from '@mui/x-internals/slots'; diff --git a/packages/x-date-pickers/tsconfig.build.json b/packages/x-date-pickers/tsconfig.build.json index e46d96ed4652..308d2110b536 100644 --- a/packages/x-date-pickers/tsconfig.build.json +++ b/packages/x-date-pickers/tsconfig.build.json @@ -18,6 +18,7 @@ "@emotion/styled" ] }, + "references": [{ "path": "../x-internals/tsconfig.build.json" }], "include": ["src/**/*.ts*"], "exclude": ["src/**/*.spec.ts*", "src/**/*.test.ts*", "src/tests/**/*"] } diff --git a/packages/x-internals/src/slots/index.ts b/packages/x-internals/src/slots/index.ts new file mode 100644 index 000000000000..4cd63cda1ead --- /dev/null +++ b/packages/x-internals/src/slots/index.ts @@ -0,0 +1,8 @@ +import * as React from 'react'; + +export type PropsFromSlot< + Slot extends React.JSXElementConstructor | React.ElementType | null | undefined, +> = + NonNullable extends React.ElementType + ? P + : React.ComponentProps>; diff --git a/packages/x-tree-view/src/models/index.ts b/packages/x-tree-view/src/models/index.ts index d5c9e3473a30..d3853dec6dd7 100644 --- a/packages/x-tree-view/src/models/index.ts +++ b/packages/x-tree-view/src/models/index.ts @@ -1 +1,4 @@ export * from './items'; + +// Utils shared across the X packages +export type { PropsFromSlot } from '@mui/x-internals/slots'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3a7d599a9669..63472d3a81be 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -99,8 +99,8 @@ importers: specifier: ^5.16.7 version: 5.16.7(@emotion/react@11.13.3(@types/react@18.3.4)(react@18.3.1))(@emotion/styled@11.13.0(@emotion/react@11.13.3(@types/react@18.3.4)(react@18.3.1))(@types/react@18.3.4)(react@18.3.1))(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mui/monorepo': - specifier: github:mui/material-ui#8b8732eabd272226fdc858cdfc1dce8b0ce4b294 - version: https://codeload.github.com/mui/material-ui/tar.gz/8b8732eabd272226fdc858cdfc1dce8b0ce4b294(encoding@0.1.13) + specifier: github:mui/material-ui#f8b2251c5bdfe4d81f56017e0423d265b242617d + version: https://codeload.github.com/mui/material-ui/tar.gz/f8b2251c5bdfe4d81f56017e0423d265b242617d(encoding@0.1.13) '@mui/utils': specifier: ^5.16.6 version: 5.16.6(@types/react@18.3.4)(react@18.3.1) @@ -169,7 +169,7 @@ importers: version: 7.18.0(eslint@8.57.0)(typescript@5.5.4) autoprefixer: specifier: ^10.4.20 - version: 10.4.20(postcss@8.4.41) + version: 10.4.20(postcss@8.4.44) axe-core: specifier: 4.10.0 version: 4.10.0 @@ -246,8 +246,8 @@ importers: specifier: ^2.29.1 version: 2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-webpack@0.13.8)(eslint@8.57.0) eslint-plugin-jsdoc: - specifier: ^48.11.0 - version: 48.11.0(eslint@8.57.0) + specifier: ^50.2.2 + version: 50.2.2(eslint@8.57.0) eslint-plugin-jsx-a11y: specifier: ^6.9.0 version: 6.9.0(eslint@8.57.0) @@ -378,7 +378,7 @@ importers: specifier: ^5.3.10 version: 5.3.10(@swc/core@1.6.13(@swc/helpers@0.5.5))(webpack@5.94.0(@swc/core@1.6.13(@swc/helpers@0.5.5))(webpack-cli@5.1.4)) tsx: - specifier: ^4.18.0 + specifier: ^4.19.0 version: 4.19.0 typescript: specifier: ^5.5.4 @@ -493,7 +493,7 @@ importers: version: 0.14.2 autoprefixer: specifier: ^10.4.20 - version: 10.4.20(postcss@8.4.41) + version: 10.4.20(postcss@8.4.44) babel-plugin-module-resolver: specifier: ^5.0.2 version: 5.0.2 @@ -582,8 +582,8 @@ importers: specifier: ^0.2.0 version: 0.2.0 postcss: - specifier: ^8.4.41 - version: 8.4.41 + specifier: ^8.4.44 + version: 8.4.44 prismjs: specifier: ^1.29.0 version: 1.29.0 @@ -627,8 +627,8 @@ importers: specifier: ^7.8.1 version: 7.8.1 styled-components: - specifier: ^6.1.12 - version: 6.1.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^6.1.13 + version: 6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1) stylis: specifier: ^4.3.4 version: 4.3.4 @@ -726,6 +726,9 @@ importers: '@mui/x-charts-vendor': specifier: workspace:* version: link:../x-charts-vendor + '@mui/x-internals': + specifier: workspace:* + version: link:../x-internals/build '@react-spring/rafz': specifier: ^9.7.4 version: 9.7.4 @@ -791,6 +794,9 @@ importers: '@mui/x-charts-vendor': specifier: workspace:* version: link:../x-charts-vendor + '@mui/x-internals': + specifier: workspace:* + version: link:../x-internals/build '@mui/x-license': specifier: workspace:* version: link:../x-license/build @@ -983,7 +989,7 @@ importers: specifier: ^17.0.0 || ^18.0.0 version: 18.3.1(react@18.3.1) reselect: - specifier: ^5.1.0 + specifier: ^5.1.1 version: 5.1.1 devDependencies: '@mui/internal-test-utils': @@ -1095,7 +1101,7 @@ importers: specifier: ^17.0.0 || ^18.0.0 version: 18.3.1(react@18.3.1) reselect: - specifier: ^5.1.0 + specifier: ^5.1.1 version: 5.1.1 devDependencies: '@mui/internal-test-utils': @@ -1157,7 +1163,7 @@ importers: specifier: ^17.0.0 || ^18.0.0 version: 18.3.1(react@18.3.1) reselect: - specifier: ^5.1.0 + specifier: ^5.1.1 version: 5.1.1 devDependencies: '@mui/internal-test-utils': @@ -1191,6 +1197,9 @@ importers: '@mui/utils': specifier: ^5.16.6 version: 5.16.6(@types/react@18.3.4)(react@18.3.1) + '@mui/x-internals': + specifier: workspace:* + version: link:../x-internals/build '@types/react-transition-group': specifier: ^4.4.11 version: 4.4.11 @@ -1277,6 +1286,9 @@ importers: '@mui/x-date-pickers': specifier: workspace:* version: link:../x-date-pickers/build + '@mui/x-internals': + specifier: workspace:* + version: link:../x-internals/build '@mui/x-license': specifier: workspace:* version: link:../x-license/build @@ -2539,8 +2551,8 @@ packages: '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@es-joy/jsdoccomment@0.46.0': - resolution: {integrity: sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==} + '@es-joy/jsdoccomment@0.48.0': + resolution: {integrity: sha512-G6QUWIcC+KvSwXNsJyDTHvqUdNoAVJPPgkc3+Uk4WBKqZvoXhlvazOgm9aL0HwihJLQf0l+tOE2UFzXBqCqgDw==} engines: {node: '>=16'} '@esbuild/aix-ppc64@0.21.5': @@ -3182,9 +3194,9 @@ packages: '@types/react': optional: true - '@mui/monorepo@https://codeload.github.com/mui/material-ui/tar.gz/8b8732eabd272226fdc858cdfc1dce8b0ce4b294': - resolution: {tarball: https://codeload.github.com/mui/material-ui/tar.gz/8b8732eabd272226fdc858cdfc1dce8b0ce4b294} - version: 6.0.1 + '@mui/monorepo@https://codeload.github.com/mui/material-ui/tar.gz/f8b2251c5bdfe4d81f56017e0423d265b242617d': + resolution: {tarball: https://codeload.github.com/mui/material-ui/tar.gz/f8b2251c5bdfe4d81f56017e0423d265b242617d} + version: 6.0.2 engines: {pnpm: 9.7.1} '@mui/private-theming@5.16.6': @@ -5953,8 +5965,8 @@ packages: '@typescript-eslint/parser': optional: true - eslint-plugin-jsdoc@48.11.0: - resolution: {integrity: sha512-d12JHJDPNo7IFwTOAItCeJY1hcqoIxE0lHA8infQByLilQ9xkqrRa6laWCnsuCrf+8rUnvxXY1XuTbibRBNylA==} + eslint-plugin-jsdoc@50.2.2: + resolution: {integrity: sha512-i0ZMWA199DG7sjxlzXn5AeYZxpRfMJjDPUl7lL9eJJX8TPRoIaxJU4ys/joP5faM5AXE1eqW/dslCj3uj4Nqpg==} engines: {node: '>=18'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 @@ -7144,8 +7156,8 @@ packages: '@babel/preset-env': optional: true - jsdoc-type-pratt-parser@4.0.0: - resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} + jsdoc-type-pratt-parser@4.1.0: + resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==} engines: {node: '>=12.0.0'} jsdom@24.1.3: @@ -8476,8 +8488,8 @@ packages: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} - postcss@8.4.41: - resolution: {integrity: sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==} + postcss@8.4.44: + resolution: {integrity: sha512-Aweb9unOEpQ3ezu4Q00DPvvM2ZTUitJdNKeP/+uQgr1IBIqu574IaZoURId7BKtWMREwzKa9OgzPzezWGPWFQw==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.1.2: @@ -9323,8 +9335,8 @@ packages: engines: {node: '>=4'} hasBin: true - styled-components@6.1.12: - resolution: {integrity: sha512-n/O4PzRPhbYI0k1vKKayfti3C/IGcPf+DqcrOB7O/ab9x4u/zjqraneT5N45+sIe87cxrCApXM8Bna7NYxwoTA==} + styled-components@6.1.13: + resolution: {integrity: sha512-M0+N2xSnAtwcVAQeFEsGWFFxXDftHUD7XrKla06QbpUMmbmtFBMMTcKWvFXtWxuD5qQkB8iU5gk6QASlx2ZRMw==} engines: {node: '>= 16'} peerDependencies: react: '>= 16.8.0' @@ -11390,11 +11402,11 @@ snapshots: '@emotion/weak-memoize@0.4.0': {} - '@es-joy/jsdoccomment@0.46.0': + '@es-joy/jsdoccomment@0.48.0': dependencies: comment-parser: 1.4.1 esquery: 1.6.0 - jsdoc-type-pratt-parser: 4.0.0 + jsdoc-type-pratt-parser: 4.1.0 '@esbuild/aix-ppc64@0.21.5': optional: true @@ -12014,7 +12026,7 @@ snapshots: '@emotion/styled': 11.13.0(@emotion/react@11.13.3(@types/react@18.3.4)(react@18.3.1))(@types/react@18.3.4)(react@18.3.1) '@types/react': 18.3.4 - '@mui/monorepo@https://codeload.github.com/mui/material-ui/tar.gz/8b8732eabd272226fdc858cdfc1dce8b0ce4b294(encoding@0.1.13)': + '@mui/monorepo@https://codeload.github.com/mui/material-ui/tar.gz/f8b2251c5bdfe4d81f56017e0423d265b242617d(encoding@0.1.13)': dependencies: '@googleapis/sheets': 9.3.0(encoding@0.1.13) '@netlify/functions': 2.8.1 @@ -13853,14 +13865,14 @@ snapshots: asynckit@0.4.0: {} - autoprefixer@10.4.20(postcss@8.4.41): + autoprefixer@10.4.20(postcss@8.4.44): dependencies: browserslist: 4.23.3 caniuse-lite: 1.0.30001647 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.1 - postcss: 8.4.41 + postcss: 8.4.44 postcss-value-parser: 4.2.0 available-typed-arrays@1.0.7: @@ -15318,9 +15330,9 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsdoc@48.11.0(eslint@8.57.0): + eslint-plugin-jsdoc@50.2.2(eslint@8.57.0): dependencies: - '@es-joy/jsdoccomment': 0.46.0 + '@es-joy/jsdoccomment': 0.48.0 are-docs-informative: 0.0.2 comment-parser: 1.4.1 debug: 4.3.6(supports-color@8.1.1) @@ -16742,7 +16754,7 @@ snapshots: transitivePeerDependencies: - supports-color - jsdoc-type-pratt-parser@4.0.0: {} + jsdoc-type-pratt-parser@4.1.0: {} jsdom@24.1.3: dependencies: @@ -18358,7 +18370,7 @@ snapshots: picocolors: 1.0.1 source-map-js: 1.2.0 - postcss@8.4.41: + postcss@8.4.44: dependencies: nanoid: 3.3.7 picocolors: 1.0.1 @@ -19350,7 +19362,7 @@ snapshots: minimist: 1.2.8 through: 2.3.8 - styled-components@6.1.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@emotion/is-prop-valid': 1.2.2 '@emotion/unitless': 0.8.1 @@ -19862,7 +19874,7 @@ snapshots: vite@5.3.4(@types/node@20.16.3)(terser@5.27.0): dependencies: esbuild: 0.21.5 - postcss: 8.4.41 + postcss: 8.4.44 rollup: 4.18.1 optionalDependencies: '@types/node': 20.16.3 diff --git a/scripts/build.mjs b/scripts/build.mjs index d7260f8ec0da..db0f14bbb550 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -5,6 +5,7 @@ import path from 'path'; import { promisify } from 'util'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; +import * as fs from 'fs/promises'; import { getWorkspaceRoot } from './utils.mjs'; const exec = promisify(childProcess.exec); @@ -27,10 +28,21 @@ async function run(argv) { ); } + const packageJsonPath = path.resolve('./package.json'); + const packageJson = JSON.parse(await fs.readFile(packageJsonPath, { encoding: 'utf8' })); + + const babelRuntimeVersion = packageJson.dependencies['@babel/runtime']; + if (!babelRuntimeVersion) { + throw new Error( + 'package.json needs to have a dependency on `@babel/runtime` when building with `@babel/plugin-transform-runtime`.', + ); + } + const env = { NODE_ENV: 'production', BABEL_ENV: bundle, MUI_BUILD_VERBOSE: verbose, + MUI_BABEL_RUNTIME_VERSION: babelRuntimeVersion, }; const babelConfigPath = path.resolve(getWorkspaceRoot(), 'babel.config.js'); const srcDir = path.resolve('./src'); diff --git a/scripts/x-charts-pro.exports.json b/scripts/x-charts-pro.exports.json index 5a6002d4f448..ba8a95232123 100644 --- a/scripts/x-charts-pro.exports.json +++ b/scripts/x-charts-pro.exports.json @@ -264,6 +264,7 @@ { "name": "PieSeriesType", "kind": "Interface" }, { "name": "PieValueType", "kind": "TypeAlias" }, { "name": "PopperProps", "kind": "TypeAlias" }, + { "name": "PropsFromSlot", "kind": "TypeAlias" }, { "name": "referenceLineClasses", "kind": "Variable" }, { "name": "ResponsiveChartContainerPro", "kind": "Variable" }, { "name": "ResponsiveChartContainerProProps", "kind": "Interface" }, diff --git a/scripts/x-charts.exports.json b/scripts/x-charts.exports.json index 77e4e3e29edc..060d4920f609 100644 --- a/scripts/x-charts.exports.json +++ b/scripts/x-charts.exports.json @@ -253,6 +253,7 @@ { "name": "PieSeriesType", "kind": "Interface" }, { "name": "PieValueType", "kind": "TypeAlias" }, { "name": "PopperProps", "kind": "TypeAlias" }, + { "name": "PropsFromSlot", "kind": "TypeAlias" }, { "name": "referenceLineClasses", "kind": "Variable" }, { "name": "ResponsiveChartContainer", "kind": "Variable" }, { "name": "ResponsiveChartContainerProps", "kind": "Interface" }, diff --git a/scripts/x-data-grid-premium.exports.json b/scripts/x-data-grid-premium.exports.json index 9cdbd7893a21..6f24de3deed6 100644 --- a/scripts/x-data-grid-premium.exports.json +++ b/scripts/x-data-grid-premium.exports.json @@ -645,6 +645,7 @@ { "name": "PaginationPropsOverrides", "kind": "Interface" }, { "name": "PanelPropsOverrides", "kind": "Interface" }, { "name": "PinnedRowsPropsOverrides", "kind": "Interface" }, + { "name": "PropsFromSlot", "kind": "TypeAlias" }, { "name": "renderActionsCell", "kind": "Variable" }, { "name": "renderBooleanCell", "kind": "Variable" }, { "name": "renderEditBooleanCell", "kind": "Variable" }, diff --git a/scripts/x-data-grid-pro.exports.json b/scripts/x-data-grid-pro.exports.json index 243ae7852d41..b276834add7a 100644 --- a/scripts/x-data-grid-pro.exports.json +++ b/scripts/x-data-grid-pro.exports.json @@ -596,6 +596,7 @@ { "name": "PaginationPropsOverrides", "kind": "Interface" }, { "name": "PanelPropsOverrides", "kind": "Interface" }, { "name": "PinnedRowsPropsOverrides", "kind": "Interface" }, + { "name": "PropsFromSlot", "kind": "TypeAlias" }, { "name": "renderActionsCell", "kind": "Variable" }, { "name": "renderBooleanCell", "kind": "Variable" }, { "name": "renderEditBooleanCell", "kind": "Variable" }, diff --git a/scripts/x-data-grid.exports.json b/scripts/x-data-grid.exports.json index 56013ba8ab98..387626660b89 100644 --- a/scripts/x-data-grid.exports.json +++ b/scripts/x-data-grid.exports.json @@ -544,6 +544,7 @@ { "name": "PaginationPropsOverrides", "kind": "Interface" }, { "name": "PanelPropsOverrides", "kind": "Interface" }, { "name": "PinnedRowsPropsOverrides", "kind": "Interface" }, + { "name": "PropsFromSlot", "kind": "TypeAlias" }, { "name": "renderActionsCell", "kind": "Variable" }, { "name": "renderBooleanCell", "kind": "Variable" }, { "name": "renderEditBooleanCell", "kind": "Variable" }, diff --git a/scripts/x-date-pickers-pro.exports.json b/scripts/x-date-pickers-pro.exports.json index f50b211610e9..9b6a47ca658d 100644 --- a/scripts/x-date-pickers-pro.exports.json +++ b/scripts/x-date-pickers-pro.exports.json @@ -333,6 +333,7 @@ { "name": "PickersYearClassKey", "kind": "TypeAlias" }, { "name": "PickerValidDate", "kind": "TypeAlias" }, { "name": "PickerValidDateLookup", "kind": "Interface" }, + { "name": "PropsFromSlot", "kind": "TypeAlias" }, { "name": "RangeFieldSection", "kind": "Interface" }, { "name": "RangeFieldSeparatorProps", "kind": "Interface" }, { "name": "RangePosition", "kind": "TypeAlias" }, diff --git a/scripts/x-date-pickers.exports.json b/scripts/x-date-pickers.exports.json index a3e10847b48a..cee13cf9c040 100644 --- a/scripts/x-date-pickers.exports.json +++ b/scripts/x-date-pickers.exports.json @@ -246,6 +246,7 @@ { "name": "PickersYearClassKey", "kind": "TypeAlias" }, { "name": "PickerValidDate", "kind": "TypeAlias" }, { "name": "PickerValidDateLookup", "kind": "Interface" }, + { "name": "PropsFromSlot", "kind": "TypeAlias" }, { "name": "renderDateViewCalendar", "kind": "Variable" }, { "name": "renderDigitalClockTimeView", "kind": "Variable" }, { "name": "renderMultiSectionDigitalClockTimeView", "kind": "Variable" }, diff --git a/scripts/x-tree-view-pro.exports.json b/scripts/x-tree-view-pro.exports.json index 16f61d3c4727..1bc3c9b84ef8 100644 --- a/scripts/x-tree-view-pro.exports.json +++ b/scripts/x-tree-view-pro.exports.json @@ -4,6 +4,7 @@ { "name": "getTreeItemUtilityClass", "kind": "Function" }, { "name": "getTreeViewUtilityClass", "kind": "Function" }, { "name": "MultiSelectTreeViewProps", "kind": "TypeAlias" }, + { "name": "PropsFromSlot", "kind": "TypeAlias" }, { "name": "RichTreeViewPro", "kind": "Variable" }, { "name": "richTreeViewProClasses", "kind": "Variable" }, { "name": "RichTreeViewProClasses", "kind": "Interface" }, diff --git a/scripts/x-tree-view.exports.json b/scripts/x-tree-view.exports.json index 49a0d1ae5a7b..b6b039d45db3 100644 --- a/scripts/x-tree-view.exports.json +++ b/scripts/x-tree-view.exports.json @@ -4,6 +4,7 @@ { "name": "getTreeItemUtilityClass", "kind": "Function" }, { "name": "getTreeViewUtilityClass", "kind": "Function" }, { "name": "MultiSelectTreeViewProps", "kind": "TypeAlias" }, + { "name": "PropsFromSlot", "kind": "TypeAlias" }, { "name": "RICH_TREE_VIEW_PLUGINS", "kind": "Variable" }, { "name": "RichTreeView", "kind": "Variable" }, { "name": "richTreeViewClasses", "kind": "Variable" }, diff --git a/test/utils/pickers/describeRangeValidation/testTextFieldRangeValidation.tsx b/test/utils/pickers/describeRangeValidation/testTextFieldRangeValidation.tsx index 7d78327e23ab..43d8294ed8f7 100644 --- a/test/utils/pickers/describeRangeValidation/testTextFieldRangeValidation.tsx +++ b/test/utils/pickers/describeRangeValidation/testTextFieldRangeValidation.tsx @@ -228,15 +228,15 @@ export const testTextFieldRangeValidation: DescribeRangeValidationTestSuite = ( expect(onErrorMock.callCount).to.equal(1); expect(onErrorMock.lastCall.args[0]).to.deep.equal(['disablePast', null]); - testInvalidStatus([true, false], isSingleInput); - - setProps({ - value: [past, past], - }); - - expect(onErrorMock.callCount).to.equal(2); - expect(onErrorMock.lastCall.args[0]).to.deep.equal(['disablePast', 'disablePast']); - testInvalidStatus([true, true], isSingleInput); + // testInvalidStatus([true, false], isSingleInput); + // + // setProps({ + // value: [past, past], + // }); + // + // expect(onErrorMock.callCount).to.equal(2); + // expect(onErrorMock.lastCall.args[0]).to.deep.equal(['disablePast', 'disablePast']); + // testInvalidStatus([true, true], isSingleInput); }); it('should apply disableFuture', function test() {