From 55249f5d5f792db89fff02bd53ee7ac2c925cf08 Mon Sep 17 00:00:00 2001 From: Diego Andai <diego@mui.com> Date: Wed, 27 Nov 2024 12:50:30 -0300 Subject: [PATCH] [typescript] Cherry pick React 19 type PRs to v5.x (#44577) --- docs/data/base/components/select/select.md | 2 +- .../joy/components/input/DebouncedInput.js | 2 +- .../joy/components/input/DebouncedInput.tsx | 4 +++- .../snackbar/SnackbarHideDuration.js | 4 ++-- .../snackbar/SnackbarHideDuration.tsx | 4 ++-- .../material/components/app-bar/BackToTop.tsx | 2 +- .../components/app-bar/ElevateAppBar.tsx | 2 +- .../components/app-bar/HideAppBar.tsx | 2 +- .../components/autocomplete/Virtualize.tsx | 12 +++++++---- .../components/dialogs/FullScreenDialog.tsx | 2 +- .../components/lists/InteractiveList.tsx | 2 +- .../components/popper/SpringPopper.tsx | 2 +- .../progress/CircularIntegration.js | 2 +- .../progress/CircularIntegration.tsx | 2 +- .../components/progress/DelayingAppearance.js | 2 +- .../progress/DelayingAppearance.tsx | 4 +++- .../components/rating/RadioGroupRating.tsx | 2 +- .../steppers/CustomizedSteppers.tsx | 2 +- .../integrations/routing/ListRouter.tsx | 2 +- docs/pages/base-ui/api/use-autocomplete.json | 4 ++-- docs/src/components/about/HowToSupport.tsx | 2 +- docs/src/components/header/HeaderNavBar.tsx | 2 +- .../home/MaterialDesignComponents.tsx | 2 +- docs/src/components/home/UserFeedbacks.tsx | 2 +- docs/src/components/pricing/PricingTable.tsx | 2 +- docs/src/components/productX/XRoadmap.tsx | 2 +- .../components/showcase/ViewToggleButton.tsx | 2 +- .../components/typography/SectionHeadline.tsx | 2 +- docs/src/layouts/HeroContainer.tsx | 4 ++-- .../modules/components/JoyThemeBuilder.tsx | 21 ++++++++++++------- docs/src/modules/components/JoyUsageDemo.tsx | 2 +- .../modules/components/JoyVariablesDemo.tsx | 4 ++-- docs/types/docs.d.ts | 2 +- packages/mui-base/src/Button/Button.tsx | 2 +- packages/mui-base/src/Tab/Tab.tsx | 2 +- .../src/useAutocomplete/useAutocomplete.d.ts | 2 +- packages/mui-base/src/useButton/useButton.ts | 2 +- .../src/useCompound/useCompound.test.tsx | 8 +++---- .../src/useCompound/useCompoundParent.ts | 9 +++++--- packages/mui-base/src/useMenu/menuReducer.ts | 2 +- .../src/useMenuItem/useMenuItem.types.ts | 2 +- .../mui-base/src/useOption/useOption.types.ts | 2 +- packages/mui-base/src/useSlider/useSlider.ts | 6 +++--- .../mui-base/src/useTabs/TabsProvider.tsx | 2 +- packages/mui-base/src/useTabs/useTabs.ts | 2 +- packages/mui-base/src/utils/useMessageBus.ts | 2 +- .../test/describeConformanceUnstyled.tsx | 2 +- .../mui-joy/src/Autocomplete/Autocomplete.tsx | 2 +- .../mui-joy/src/ButtonGroup/ButtonGroup.tsx | 7 ++++--- packages/mui-joy/src/Card/Card.tsx | 7 ++++--- packages/mui-joy/src/ListItem/ListItem.tsx | 4 ++-- .../mui-joy/src/ModalDialog/ModalDialog.tsx | 7 ++++--- packages/mui-joy/src/Tab/Tab.tsx | 2 +- .../ToggleButtonGroup/ToggleButtonGroup.tsx | 7 ++++--- packages/mui-joy/src/Tooltip/Tooltip.tsx | 2 +- packages/mui-lab/src/Timeline/Timeline.tsx | 5 ++--- .../mui-lab/src/Timeline/Timeline.types.ts | 2 +- packages/mui-lab/test/describeConformance.ts | 2 +- .../pagesRouterV13Document.tsx | 2 +- .../mui-material/src/Popper/Popper.spec.tsx | 2 +- packages/mui-material/src/Slider/useSlider.ts | 6 +++--- .../mui-material/src/styles/styled.spec.tsx | 4 ++-- .../src/useAutocomplete/useAutocomplete.d.ts | 2 +- .../mui-material/test/describeConformance.ts | 2 +- .../src/GlobalStyles/GlobalStyles.d.ts | 2 +- .../src/GlobalStyles/GlobalStyles.spec.tsx | 2 +- .../src/GlobalStyles/GlobalStyles.d.ts | 2 +- .../src/GlobalStyles/GlobalStyles.spec.tsx | 2 +- packages/mui-system/src/Stack/createStack.tsx | 4 ++-- .../src/Unstable_Grid/createGrid.tsx | 7 +++++-- .../src/cssVars/createCssVarsProvider.d.ts | 2 +- .../mui-system/test/describeConformance.ts | 2 +- .../getValidReactChildren.ts | 2 +- packages/mui-utils/src/setRef/setRef.spec.tsx | 2 +- packages/test-utils/src/createRenderer.tsx | 16 ++++++++------ 75 files changed, 144 insertions(+), 118 deletions(-) diff --git a/docs/data/base/components/select/select.md b/docs/data/base/components/select/select.md index 7b66ecc94cc074..d3c996083bff70 100644 --- a/docs/data/base/components/select/select.md +++ b/docs/data/base/components/select/select.md @@ -60,7 +60,7 @@ const CustomSelect = React.forwardRef(function CustomSelect<TValue>( return <Select {...props} ref={ref} />; }) as <TValue>( props: SelectProps<TValue> & React.RefAttributes<HTMLUListElement>, -) => JSX.Element; +) => React.JSX.Element; ``` For the sake of brevity, the rest of the demos throughout this doc will not use `forwardRef`. diff --git a/docs/data/joy/components/input/DebouncedInput.js b/docs/data/joy/components/input/DebouncedInput.js index 7955a340238075..e3be327ae80114 100644 --- a/docs/data/joy/components/input/DebouncedInput.js +++ b/docs/data/joy/components/input/DebouncedInput.js @@ -7,7 +7,7 @@ import Box from '@mui/joy/Box'; function DebounceInput(props) { const { handleDebounce, debounceTimeout, ...rest } = props; - const timerRef = React.useRef(); + const timerRef = React.useRef(undefined); const handleChange = (event) => { clearTimeout(timerRef.current); diff --git a/docs/data/joy/components/input/DebouncedInput.tsx b/docs/data/joy/components/input/DebouncedInput.tsx index 927d37954daedf..5bf72ffbe9f213 100644 --- a/docs/data/joy/components/input/DebouncedInput.tsx +++ b/docs/data/joy/components/input/DebouncedInput.tsx @@ -11,7 +11,9 @@ type DebounceProps = { function DebounceInput(props: InputProps & DebounceProps) { const { handleDebounce, debounceTimeout, ...rest } = props; - const timerRef = React.useRef<ReturnType<typeof setTimeout>>(); + const timerRef = React.useRef<ReturnType<typeof setTimeout> | undefined>( + undefined, + ); const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { clearTimeout(timerRef.current); diff --git a/docs/data/joy/components/snackbar/SnackbarHideDuration.js b/docs/data/joy/components/snackbar/SnackbarHideDuration.js index 8c3968bd9bd7e3..6d21d8b8ec9667 100644 --- a/docs/data/joy/components/snackbar/SnackbarHideDuration.js +++ b/docs/data/joy/components/snackbar/SnackbarHideDuration.js @@ -10,9 +10,9 @@ export default function SnackbarHideDuration() { const [open, setOpen] = React.useState(false); const [duration, setDuration] = React.useState(); const [left, setLeft] = React.useState(); - const timer = React.useRef(); + const timer = React.useRef(undefined); const countdown = () => { - timer.current = window.setInterval(() => { + timer.current = setInterval(() => { setLeft((prev) => (prev === undefined ? prev : Math.max(0, prev - 100))); }, 100); }; diff --git a/docs/data/joy/components/snackbar/SnackbarHideDuration.tsx b/docs/data/joy/components/snackbar/SnackbarHideDuration.tsx index c98174c2cf33c5..dc56b4dfd2aed7 100644 --- a/docs/data/joy/components/snackbar/SnackbarHideDuration.tsx +++ b/docs/data/joy/components/snackbar/SnackbarHideDuration.tsx @@ -10,9 +10,9 @@ export default function SnackbarHideDuration() { const [open, setOpen] = React.useState(false); const [duration, setDuration] = React.useState<undefined | number>(); const [left, setLeft] = React.useState<undefined | number>(); - const timer = React.useRef<undefined | number>(); + const timer = React.useRef<ReturnType<typeof setInterval> | undefined>(undefined); const countdown = () => { - timer.current = window.setInterval(() => { + timer.current = setInterval(() => { setLeft((prev) => (prev === undefined ? prev : Math.max(0, prev - 100))); }, 100); }; diff --git a/docs/data/material/components/app-bar/BackToTop.tsx b/docs/data/material/components/app-bar/BackToTop.tsx index bb76a90931cc19..1aec6b41614cb1 100644 --- a/docs/data/material/components/app-bar/BackToTop.tsx +++ b/docs/data/material/components/app-bar/BackToTop.tsx @@ -16,7 +16,7 @@ interface Props { * You won't need it on your project. */ window?: () => Window; - children: React.ReactElement<any>; + children: React.ReactElement<unknown>; } function ScrollTop(props: Props) { diff --git a/docs/data/material/components/app-bar/ElevateAppBar.tsx b/docs/data/material/components/app-bar/ElevateAppBar.tsx index cf47ff2b5cc745..aa40a9daa48303 100644 --- a/docs/data/material/components/app-bar/ElevateAppBar.tsx +++ b/docs/data/material/components/app-bar/ElevateAppBar.tsx @@ -13,7 +13,7 @@ interface Props { * You won't need it on your project. */ window?: () => Window; - children: React.ReactElement<any>; + children: React.ReactElement<{ elevation?: number }>; } function ElevationScroll(props: Props) { diff --git a/docs/data/material/components/app-bar/HideAppBar.tsx b/docs/data/material/components/app-bar/HideAppBar.tsx index ee71918b61e843..cf4b6523284a2a 100644 --- a/docs/data/material/components/app-bar/HideAppBar.tsx +++ b/docs/data/material/components/app-bar/HideAppBar.tsx @@ -14,7 +14,7 @@ interface Props { * You won't need it on your project. */ window?: () => Window; - children: React.ReactElement<any>; + children: React.ReactElement<unknown>; } function HideOnScroll(props: Props) { diff --git a/docs/data/material/components/autocomplete/Virtualize.tsx b/docs/data/material/components/autocomplete/Virtualize.tsx index 9e062e1ef1cec9..7a54aa5420ba91 100644 --- a/docs/data/material/components/autocomplete/Virtualize.tsx +++ b/docs/data/material/components/autocomplete/Virtualize.tsx @@ -58,9 +58,13 @@ const ListboxComponent = React.forwardRef< React.HTMLAttributes<HTMLElement> >(function ListboxComponent(props, ref) { const { children, ...other } = props; - const itemData: React.ReactElement<any>[] = []; - (children as React.ReactElement<any>[]).forEach( - (item: React.ReactElement<any> & { children?: React.ReactElement<any>[] }) => { + const itemData: React.ReactElement<unknown>[] = []; + (children as React.ReactElement<unknown>[]).forEach( + ( + item: React.ReactElement<unknown> & { + children?: React.ReactElement<unknown>[]; + }, + ) => { itemData.push(item); itemData.push(...(item.children || [])); }, @@ -73,7 +77,7 @@ const ListboxComponent = React.forwardRef< const itemCount = itemData.length; const itemSize = smUp ? 36 : 48; - const getChildSize = (child: React.ReactElement<any>) => { + const getChildSize = (child: React.ReactElement<unknown>) => { if (child.hasOwnProperty('group')) { return 48; } diff --git a/docs/data/material/components/dialogs/FullScreenDialog.tsx b/docs/data/material/components/dialogs/FullScreenDialog.tsx index 5b0dc07b9cd042..2215e96f891b12 100644 --- a/docs/data/material/components/dialogs/FullScreenDialog.tsx +++ b/docs/data/material/components/dialogs/FullScreenDialog.tsx @@ -15,7 +15,7 @@ import { TransitionProps } from '@mui/material/transitions'; const Transition = React.forwardRef(function Transition( props: TransitionProps & { - children: React.ReactElement<any>; + children: React.ReactElement<unknown>; }, ref: React.Ref<unknown>, ) { diff --git a/docs/data/material/components/lists/InteractiveList.tsx b/docs/data/material/components/lists/InteractiveList.tsx index 661995d60917d4..e667a977cda23a 100644 --- a/docs/data/material/components/lists/InteractiveList.tsx +++ b/docs/data/material/components/lists/InteractiveList.tsx @@ -16,7 +16,7 @@ import Typography from '@mui/material/Typography'; import FolderIcon from '@mui/icons-material/Folder'; import DeleteIcon from '@mui/icons-material/Delete'; -function generate(element: React.ReactElement<any>) { +function generate(element: React.ReactElement<unknown>) { return [0, 1, 2].map((value) => React.cloneElement(element, { key: value, diff --git a/docs/data/material/components/popper/SpringPopper.tsx b/docs/data/material/components/popper/SpringPopper.tsx index 5526317503ff16..636bedcfc229c1 100644 --- a/docs/data/material/components/popper/SpringPopper.tsx +++ b/docs/data/material/components/popper/SpringPopper.tsx @@ -4,7 +4,7 @@ import Popper from '@mui/material/Popper'; import { useSpring, animated } from '@react-spring/web'; interface FadeProps { - children?: React.ReactElement<any>; + children?: React.ReactElement<unknown>; in?: boolean; onEnter?: () => void; onExited?: () => void; diff --git a/docs/data/material/components/progress/CircularIntegration.js b/docs/data/material/components/progress/CircularIntegration.js index 1c885b355996da..adb2accfe4cd9a 100644 --- a/docs/data/material/components/progress/CircularIntegration.js +++ b/docs/data/material/components/progress/CircularIntegration.js @@ -10,7 +10,7 @@ import SaveIcon from '@mui/icons-material/Save'; export default function CircularIntegration() { const [loading, setLoading] = React.useState(false); const [success, setSuccess] = React.useState(false); - const timer = React.useRef(); + const timer = React.useRef(undefined); const buttonSx = { ...(success && { diff --git a/docs/data/material/components/progress/CircularIntegration.tsx b/docs/data/material/components/progress/CircularIntegration.tsx index c32a5957a42fb8..c0e3761c48905b 100644 --- a/docs/data/material/components/progress/CircularIntegration.tsx +++ b/docs/data/material/components/progress/CircularIntegration.tsx @@ -10,7 +10,7 @@ import SaveIcon from '@mui/icons-material/Save'; export default function CircularIntegration() { const [loading, setLoading] = React.useState(false); const [success, setSuccess] = React.useState(false); - const timer = React.useRef<ReturnType<typeof setTimeout>>(); + const timer = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined); const buttonSx = { ...(success && { diff --git a/docs/data/material/components/progress/DelayingAppearance.js b/docs/data/material/components/progress/DelayingAppearance.js index df2b050772e529..0844371d452fbf 100644 --- a/docs/data/material/components/progress/DelayingAppearance.js +++ b/docs/data/material/components/progress/DelayingAppearance.js @@ -8,7 +8,7 @@ import Typography from '@mui/material/Typography'; export default function DelayingAppearance() { const [loading, setLoading] = React.useState(false); const [query, setQuery] = React.useState('idle'); - const timerRef = React.useRef(); + const timerRef = React.useRef(undefined); React.useEffect( () => () => { diff --git a/docs/data/material/components/progress/DelayingAppearance.tsx b/docs/data/material/components/progress/DelayingAppearance.tsx index a6784fd2d359d8..024769f55ca7a0 100644 --- a/docs/data/material/components/progress/DelayingAppearance.tsx +++ b/docs/data/material/components/progress/DelayingAppearance.tsx @@ -8,7 +8,9 @@ import Typography from '@mui/material/Typography'; export default function DelayingAppearance() { const [loading, setLoading] = React.useState(false); const [query, setQuery] = React.useState('idle'); - const timerRef = React.useRef<ReturnType<typeof setTimeout>>(); + const timerRef = React.useRef<ReturnType<typeof setTimeout> | undefined>( + undefined, + ); React.useEffect( () => () => { diff --git a/docs/data/material/components/rating/RadioGroupRating.tsx b/docs/data/material/components/rating/RadioGroupRating.tsx index f42709d21c1359..89a509e2d0effe 100644 --- a/docs/data/material/components/rating/RadioGroupRating.tsx +++ b/docs/data/material/components/rating/RadioGroupRating.tsx @@ -15,7 +15,7 @@ const StyledRating = styled(Rating)(({ theme }) => ({ const customIcons: { [index: string]: { - icon: React.ReactElement<any>; + icon: React.ReactElement<unknown>; label: string; }; } = { diff --git a/docs/data/material/components/steppers/CustomizedSteppers.tsx b/docs/data/material/components/steppers/CustomizedSteppers.tsx index 3a4c2e7ddf879c..03791f59e854a9 100644 --- a/docs/data/material/components/steppers/CustomizedSteppers.tsx +++ b/docs/data/material/components/steppers/CustomizedSteppers.tsx @@ -122,7 +122,7 @@ const ColorlibStepIconRoot = styled('div')<{ function ColorlibStepIcon(props: StepIconProps) { const { active, completed, className } = props; - const icons: { [index: string]: React.ReactElement<any> } = { + const icons: { [index: string]: React.ReactElement<unknown> } = { 1: <SettingsIcon />, 2: <GroupAddIcon />, 3: <VideoLabelIcon />, diff --git a/docs/data/material/integrations/routing/ListRouter.tsx b/docs/data/material/integrations/routing/ListRouter.tsx index fc3fe2410991a3..52dac8f8461185 100644 --- a/docs/data/material/integrations/routing/ListRouter.tsx +++ b/docs/data/material/integrations/routing/ListRouter.tsx @@ -34,7 +34,7 @@ function Router(props: { children?: React.ReactNode }) { } interface ListItemLinkProps { - icon?: React.ReactElement<any>; + icon?: React.ReactElement<unknown>; primary: string; to: string; } diff --git a/docs/pages/base-ui/api/use-autocomplete.json b/docs/pages/base-ui/api/use-autocomplete.json index 994ebed0543af0..0a4ac4aaf008aa 100644 --- a/docs/pages/base-ui/api/use-autocomplete.json +++ b/docs/pages/base-ui/api/use-autocomplete.json @@ -147,8 +147,8 @@ }, "unstable_isActiveElementInListbox": { "type": { - "name": "(listbox: React.RefObject<HTMLElement>) => boolean", - "description": "(listbox: React.RefObject<HTMLElement>) => boolean" + "name": "(listbox: React.RefObject<HTMLElement | null>) => boolean", + "description": "(listbox: React.RefObject<HTMLElement | null>) => boolean" } }, "value": { diff --git a/docs/src/components/about/HowToSupport.tsx b/docs/src/components/about/HowToSupport.tsx index bf03040aab35a2..2ac0a6e22aaa24 100644 --- a/docs/src/components/about/HowToSupport.tsx +++ b/docs/src/components/about/HowToSupport.tsx @@ -21,7 +21,7 @@ function Widget({ }: { children: React.ReactNode; title: string; - icon: React.ReactElement<any>; + icon: React.ReactElement<unknown>; }) { return ( <Paper diff --git a/docs/src/components/header/HeaderNavBar.tsx b/docs/src/components/header/HeaderNavBar.tsx index f135aa52fb9138..8fe75798908401 100644 --- a/docs/src/components/header/HeaderNavBar.tsx +++ b/docs/src/components/header/HeaderNavBar.tsx @@ -75,7 +75,7 @@ const PRODUCT_IDS = [ ]; type ProductSubMenuProps = { - icon: React.ReactElement<any>; + icon: React.ReactElement<unknown>; name: React.ReactNode; description: React.ReactNode; chip?: React.ReactNode; diff --git a/docs/src/components/home/MaterialDesignComponents.tsx b/docs/src/components/home/MaterialDesignComponents.tsx index 645d2786cc7410..efacc3c318452d 100644 --- a/docs/src/components/home/MaterialDesignComponents.tsx +++ b/docs/src/components/home/MaterialDesignComponents.tsx @@ -125,7 +125,7 @@ function Demo({ }: { name: string; theme: Theme | undefined; - children: React.ReactElement<any>; + children: React.ReactElement<unknown>; control?: { prop: string; values: Array<string>; defaultValue?: string }; }) { const [propValue, setPropValue] = React.useState( diff --git a/docs/src/components/home/UserFeedbacks.tsx b/docs/src/components/home/UserFeedbacks.tsx index 5f9786f3d08b66..5a73469ffab2f7 100644 --- a/docs/src/components/home/UserFeedbacks.tsx +++ b/docs/src/components/home/UserFeedbacks.tsx @@ -95,7 +95,7 @@ function Feedback({ avatarSrcSet: string; name: string; role: string; - company?: React.ReactElement<any>; + company?: React.ReactElement<unknown>; }; }) { return ( diff --git a/docs/src/components/pricing/PricingTable.tsx b/docs/src/components/pricing/PricingTable.tsx index e25e774399bac0..d8c225ab266adc 100644 --- a/docs/src/components/pricing/PricingTable.tsx +++ b/docs/src/components/pricing/PricingTable.tsx @@ -424,7 +424,7 @@ function RowHead({ children, startIcon, ...props -}: BoxProps & { startIcon?: React.ReactElement<any> }) { +}: BoxProps & { startIcon?: React.ReactElement<unknown> }) { return ( <Box {...props} diff --git a/docs/src/components/productX/XRoadmap.tsx b/docs/src/components/productX/XRoadmap.tsx index 8eb2b64f83b924..e43b55bd5a67b3 100644 --- a/docs/src/components/productX/XRoadmap.tsx +++ b/docs/src/components/productX/XRoadmap.tsx @@ -41,7 +41,7 @@ function RoadmapStatusDot({ color }: RoadmapStatusDotProps) { } export default function XRoadmap() { - function renderList(content: React.ReactElement<any>, nested?: boolean) { + function renderList(content: React.ReactElement<unknown>, nested?: boolean) { return ( <Box sx={{ diff --git a/docs/src/components/showcase/ViewToggleButton.tsx b/docs/src/components/showcase/ViewToggleButton.tsx index e4c155cbd9c987..eec9402524ea2c 100644 --- a/docs/src/components/showcase/ViewToggleButton.tsx +++ b/docs/src/components/showcase/ViewToggleButton.tsx @@ -11,7 +11,7 @@ const views = ['quilt', 'module', 'agenda', 'week', 'sidebar'] as const; type View = (typeof views)[number]; -const viewIcons: Record<View, React.ReactElement<any>> = { +const viewIcons: Record<View, React.ReactElement<unknown>> = { quilt: <ViewQuiltRounded />, module: <ViewModuleRounded />, agenda: <ViewAgendaRounded />, diff --git a/docs/src/components/typography/SectionHeadline.tsx b/docs/src/components/typography/SectionHeadline.tsx index b1e30e3eb76611..f9d42e1659d68e 100644 --- a/docs/src/components/typography/SectionHeadline.tsx +++ b/docs/src/components/typography/SectionHeadline.tsx @@ -11,7 +11,7 @@ interface SectionHeadlineProps { */ inverted?: boolean; overline?: React.ReactNode; - title: string | React.ReactElement<any>; + title: string | React.ReactElement<React.HTMLAttributes<HTMLElement>>; } export default function SectionHeadline(props: SectionHeadlineProps) { diff --git a/docs/src/layouts/HeroContainer.tsx b/docs/src/layouts/HeroContainer.tsx index 0fcd853ab1a7b9..536dc4f17fd392 100644 --- a/docs/src/layouts/HeroContainer.tsx +++ b/docs/src/layouts/HeroContainer.tsx @@ -8,9 +8,9 @@ import { alpha } from '@mui/material/styles'; interface HeroContainerProps { disableMobileHidden?: boolean; disableTabExclusion?: boolean; - left: React.ReactElement<any>; + left: React.ReactElement<unknown>; linearGradient?: boolean; - right: React.ReactElement<any>; + right: React.ReactElement<unknown>; rightSx?: BoxProps['sx']; } diff --git a/docs/src/modules/components/JoyThemeBuilder.tsx b/docs/src/modules/components/JoyThemeBuilder.tsx index e8507ace5d0671..902745b23081ae 100644 --- a/docs/src/modules/components/JoyThemeBuilder.tsx +++ b/docs/src/modules/components/JoyThemeBuilder.tsx @@ -983,7 +983,11 @@ function filterGlobalVariantTokens(palette: Partial<PaletteVariant>, variant: Va return tokens; } -type StateReducer<T> = (state: T, action: Partial<T>) => T; +type ReducerState = { + hover: boolean; + active: boolean; + disabled: boolean; +}; function GlobalVariantForm({ color, @@ -1001,13 +1005,14 @@ function GlobalVariantForm({ onRemove: (token: string) => void; }) { const [selectedVariant, setSelectedVariant] = React.useState<VariantProp>('solid'); - const [states, setStates] = React.useReducer< - StateReducer<{ hover: boolean; active: boolean; disabled: boolean }> - >((prevState, action) => ({ ...prevState, ...action }), { - hover: false, - active: false, - disabled: false, - }); + const [states, setStates] = React.useReducer( + (prevState: ReducerState, action: Partial<ReducerState>) => ({ ...prevState, ...action }), + { + hover: false, + active: false, + disabled: false, + }, + ); const themeDefaultValue = filterGlobalVariantTokens(themeDefaultValueProp, selectedVariant); const value = filterGlobalVariantTokens(valueProp, selectedVariant); const mergedValue = { ...themeDefaultValue, ...value }; diff --git a/docs/src/modules/components/JoyUsageDemo.tsx b/docs/src/modules/components/JoyUsageDemo.tsx index ea9b394509fda9..7da2e3bb8b7197 100644 --- a/docs/src/modules/components/JoyUsageDemo.tsx +++ b/docs/src/modules/components/JoyUsageDemo.tsx @@ -165,7 +165,7 @@ interface JoyUsageDemoProps<ComponentProps> { * A function to override the code block result. */ getCodeBlock?: (code: string, props: ComponentProps) => string; - renderDemo: (props: ComponentProps) => React.ReactElement<any>; + renderDemo: (props: ComponentProps) => React.ReactElement<unknown>; } export default function JoyUsageDemo<T extends { [k: string]: any } = {}>({ diff --git a/docs/src/modules/components/JoyVariablesDemo.tsx b/docs/src/modules/components/JoyVariablesDemo.tsx index 16450717fbe363..b23e4bf952bee3 100644 --- a/docs/src/modules/components/JoyVariablesDemo.tsx +++ b/docs/src/modules/components/JoyVariablesDemo.tsx @@ -33,7 +33,7 @@ function formatSx(sx: { [k: string]: string | number }) { interface SlotVariablesProps { slot: string; data: Array<DataItem>; - renderField: (item: DataItem) => React.ReactElement<any>; + renderField: (item: DataItem) => React.ReactElement<unknown>; defaultOpen?: boolean; } @@ -88,7 +88,7 @@ export default function JoyVariablesDemo(props: { componentName: string; childrenAccepted?: boolean; data: Array<DataItem | [string, Array<DataItem>, { defaultOpen?: boolean } | undefined]>; - renderDemo: (sx: { [k: string]: string | number }) => React.ReactElement<any>; + renderDemo: (sx: { [k: string]: string | number }) => React.ReactElement<unknown>; renderCode?: (formattedSx: string) => string; }) { const { componentName, data = [], childrenAccepted = false, renderCode } = props; diff --git a/docs/types/docs.d.ts b/docs/types/docs.d.ts index fc96dea50c386a..4d77ba0ecabb66 100644 --- a/docs/types/docs.d.ts +++ b/docs/types/docs.d.ts @@ -23,7 +23,7 @@ declare module 'docs/src/modules/components/HighlightedCode' { component?: React.ElementType; sx?: object; } - export default function HighlightedCode(props: Props): React.ReactElement<any>; + export default function HighlightedCode(props: Props): React.ReactElement<unknown>; } declare module 'react-imask'; diff --git a/packages/mui-base/src/Button/Button.tsx b/packages/mui-base/src/Button/Button.tsx index 816c3e9c4f1c71..ce9dd0ce7fa9cb 100644 --- a/packages/mui-base/src/Button/Button.tsx +++ b/packages/mui-base/src/Button/Button.tsx @@ -46,7 +46,7 @@ const Button = React.forwardRef(function Button<RootComponentType extends React. ...other } = props; - const buttonRef = React.useRef<HTMLButtonElement | HTMLAnchorElement | HTMLElement>(); + const buttonRef = React.useRef<HTMLButtonElement | HTMLAnchorElement | HTMLElement | null>(null); let rootElementName = rootElementNameProp; diff --git a/packages/mui-base/src/Tab/Tab.tsx b/packages/mui-base/src/Tab/Tab.tsx index d63b03374d05bd..6147ba91e90ed3 100644 --- a/packages/mui-base/src/Tab/Tab.tsx +++ b/packages/mui-base/src/Tab/Tab.tsx @@ -45,7 +45,7 @@ const Tab = React.forwardRef(function Tab<RootComponentType extends React.Elemen ...other } = props; - const tabRef = React.useRef<HTMLButtonElement | HTMLAnchorElement | HTMLElement>(); + const tabRef = React.useRef<HTMLButtonElement | HTMLAnchorElement | HTMLElement | null>(null); const handleRef = useForkRef(tabRef, forwardedRef); const { active, highlighted, selected, getRootProps } = useTab({ diff --git a/packages/mui-base/src/useAutocomplete/useAutocomplete.d.ts b/packages/mui-base/src/useAutocomplete/useAutocomplete.d.ts index f436583759b0bf..d2825047f2c0c7 100644 --- a/packages/mui-base/src/useAutocomplete/useAutocomplete.d.ts +++ b/packages/mui-base/src/useAutocomplete/useAutocomplete.d.ts @@ -49,7 +49,7 @@ export interface UseAutocompleteProps< * Temporary for Joy UI because the parent listbox is the document object * TODO v6: Normalize the logic and remove this param. */ - unstable_isActiveElementInListbox?: (listbox: React.RefObject<HTMLElement>) => boolean; + unstable_isActiveElementInListbox?: (listbox: React.RefObject<HTMLElement | null>) => boolean; /** * If `true`, the portion of the selected suggestion that the user hasn't typed, * known as the completion string, appears inline after the input cursor in the textbox. diff --git a/packages/mui-base/src/useButton/useButton.ts b/packages/mui-base/src/useButton/useButton.ts index 0c6b5da72973aa..815a3009b2fa70 100644 --- a/packages/mui-base/src/useButton/useButton.ts +++ b/packages/mui-base/src/useButton/useButton.ts @@ -34,7 +34,7 @@ export function useButton(parameters: UseButtonParameters = {}): UseButtonReturn type, rootElementName: rootElementNameProp, } = parameters; - const buttonRef = React.useRef<HTMLButtonElement | HTMLAnchorElement | HTMLElement>(); + const buttonRef = React.useRef<HTMLButtonElement | HTMLAnchorElement | HTMLElement | null>(null); const [active, setActive] = React.useState<boolean>(false); diff --git a/packages/mui-base/src/useCompound/useCompound.test.tsx b/packages/mui-base/src/useCompound/useCompound.test.tsx index 509e851cf6456b..4e51d94ac76afe 100644 --- a/packages/mui-base/src/useCompound/useCompound.test.tsx +++ b/packages/mui-base/src/useCompound/useCompound.test.tsx @@ -4,7 +4,7 @@ import { render } from '@mui-internal/test-utils'; import { CompoundComponentContext, useCompoundParent } from './useCompoundParent'; import { useCompoundItem } from './useCompoundItem'; -type ItemValue = { value: string; ref: React.RefObject<HTMLSpanElement> }; +type ItemValue = { value: string; ref: React.RefObject<HTMLSpanElement | null> }; describe('compound components', () => { describe('useCompoundParent', () => { @@ -188,7 +188,7 @@ describe('compound components', () => { const { children } = props; const { contextValue } = useCompoundParent< string, - { ref: React.RefObject<HTMLSpanElement> } + { ref: React.RefObject<HTMLSpanElement | null> } >(); return ( @@ -240,7 +240,7 @@ describe('compound components', () => { const { children } = props; const { contextValue } = useCompoundParent< number, - { ref: React.RefObject<HTMLLIElement> } + { ref: React.RefObject<HTMLLIElement | null> } >(); return ( @@ -256,7 +256,7 @@ describe('compound components', () => { function Child() { const ref = React.useRef<HTMLLIElement>(null); - const { id } = useCompoundItem<string, { ref: React.RefObject<HTMLLIElement> }>( + const { id } = useCompoundItem<string, { ref: React.RefObject<HTMLLIElement | null> }>( idGenerator, React.useMemo(() => ({ ref }), []), ); diff --git a/packages/mui-base/src/useCompound/useCompoundParent.ts b/packages/mui-base/src/useCompound/useCompoundParent.ts index 8cc2dad24b6efe..99f0b2082704ff 100644 --- a/packages/mui-base/src/useCompound/useCompoundParent.ts +++ b/packages/mui-base/src/useCompound/useCompoundParent.ts @@ -47,7 +47,10 @@ if (process.env.NODE_ENV !== 'production') { CompoundComponentContext.displayName = 'CompoundComponentContext'; } -export interface UseCompoundParentReturnValue<Key, Subitem extends { ref: React.RefObject<Node> }> { +export interface UseCompoundParentReturnValue< + Key, + Subitem extends { ref: React.RefObject<Node | null> }, +> { /** * The value for the CompoundComponentContext provider. */ @@ -63,7 +66,7 @@ export interface UseCompoundParentReturnValue<Key, Subitem extends { ref: React. /** * Sorts the subitems by their position in the DOM. */ -function sortSubitems<Key, Subitem extends { ref: React.RefObject<Node> }>( +function sortSubitems<Key, Subitem extends { ref: React.RefObject<Node | null> }>( subitems: Map<Key, Subitem>, ) { const subitemsArray = Array.from(subitems.keys()).map((key) => { @@ -100,7 +103,7 @@ function sortSubitems<Key, Subitem extends { ref: React.RefObject<Node> }>( */ export function useCompoundParent< Key, - Subitem extends { ref: React.RefObject<Node> }, + Subitem extends { ref: React.RefObject<Node | null> }, >(): UseCompoundParentReturnValue<Key, Subitem> { const [subitems, setSubitems] = React.useState(new Map<Key, Subitem>()); const subitemKeys = React.useRef(new Set<Key>()); diff --git a/packages/mui-base/src/useMenu/menuReducer.ts b/packages/mui-base/src/useMenu/menuReducer.ts index 74ffc00361bbe0..ecdf640b4fe16f 100644 --- a/packages/mui-base/src/useMenu/menuReducer.ts +++ b/packages/mui-base/src/useMenu/menuReducer.ts @@ -3,7 +3,7 @@ import { ActionWithContext } from '../utils/useControllableReducer.types'; import { MenuInternalState } from './useMenu.types'; export type MenuActionContext = ListActionContext<string> & { - listboxRef: React.RefObject<HTMLElement>; + listboxRef: React.RefObject<HTMLElement | null>; }; export function menuReducer( diff --git a/packages/mui-base/src/useMenuItem/useMenuItem.types.ts b/packages/mui-base/src/useMenuItem/useMenuItem.types.ts index 8f5231685ec892..ed8ea501838a62 100644 --- a/packages/mui-base/src/useMenuItem/useMenuItem.types.ts +++ b/packages/mui-base/src/useMenuItem/useMenuItem.types.ts @@ -11,7 +11,7 @@ export interface MenuItemMetadata { id: string; disabled: boolean; label?: string; - ref: React.RefObject<HTMLElement>; + ref: React.RefObject<HTMLElement | null>; } export type UseMenuItemRootSlotProps<ExternalProps = {}> = ExternalProps & diff --git a/packages/mui-base/src/useOption/useOption.types.ts b/packages/mui-base/src/useOption/useOption.types.ts index 0bc3ee4cf14d23..e64f59bef52229 100644 --- a/packages/mui-base/src/useOption/useOption.types.ts +++ b/packages/mui-base/src/useOption/useOption.types.ts @@ -4,7 +4,7 @@ export interface SelectOption<Value> { value: Value; label: React.ReactNode; disabled?: boolean; - ref: React.RefObject<HTMLElement>; + ref: React.RefObject<HTMLElement | null>; id?: string; } diff --git a/packages/mui-base/src/useSlider/useSlider.ts b/packages/mui-base/src/useSlider/useSlider.ts index 7739bab422238c..564a1f3612627a 100644 --- a/packages/mui-base/src/useSlider/useSlider.ts +++ b/packages/mui-base/src/useSlider/useSlider.ts @@ -218,7 +218,7 @@ export function useSlider(parameters: UseSliderParameters): UseSliderReturnValue value: valueProp, } = parameters; - const touchId = React.useRef<number>(); + const touchId = React.useRef<number | undefined>(undefined); // We can't use the :active browser pseudo-classes. // - The active state isn't triggered when clicking on the rail. // - The active state isn't transferred when inversing a range slider. @@ -273,7 +273,7 @@ export function useSlider(parameters: UseSliderParameters): UseSliderReturnValue } = useIsFocusVisible(); const [focusedThumbIndex, setFocusedThumbIndex] = React.useState(-1); - const sliderRef = React.useRef<HTMLSpanElement>(); + const sliderRef = React.useRef<HTMLSpanElement | null>(null); const handleFocusRef = useForkRef(focusVisibleRef, sliderRef); const handleRef = useForkRef(ref, handleFocusRef); @@ -405,7 +405,7 @@ export function useSlider(parameters: UseSliderParameters): UseSliderReturnValue changeValue(event, event.target.valueAsNumber); }; - const previousIndex = React.useRef<number>(); + const previousIndex = React.useRef<number | undefined>(undefined); let axis = orientation; if (isRtl && orientation === 'horizontal') { axis += '-reverse'; diff --git a/packages/mui-base/src/useTabs/TabsProvider.tsx b/packages/mui-base/src/useTabs/TabsProvider.tsx index 31d8aebd939315..2731205d1a8511 100644 --- a/packages/mui-base/src/useTabs/TabsProvider.tsx +++ b/packages/mui-base/src/useTabs/TabsProvider.tsx @@ -5,7 +5,7 @@ import { CompoundComponentContext, CompoundComponentContextValue } from '../useC export type TabPanelMetadata = { id: string | undefined; - ref: React.RefObject<HTMLElement>; + ref: React.RefObject<HTMLElement | null>; }; export type TabsProviderValue = CompoundComponentContextValue<string | number, TabPanelMetadata> & diff --git a/packages/mui-base/src/useTabs/useTabs.ts b/packages/mui-base/src/useTabs/useTabs.ts index 75994646e1266c..bf6e1d368f8f70 100644 --- a/packages/mui-base/src/useTabs/useTabs.ts +++ b/packages/mui-base/src/useTabs/useTabs.ts @@ -8,7 +8,7 @@ import { TabPanelMetadata } from './TabsProvider'; export interface TabMetadata { disabled: boolean; id: string | undefined; - ref: React.RefObject<HTMLElement>; + ref: React.RefObject<HTMLElement | null>; } type IdLookupFunction = (id: string | number) => string | undefined; diff --git a/packages/mui-base/src/utils/useMessageBus.ts b/packages/mui-base/src/utils/useMessageBus.ts index b7246f9b0b4bce..4cfab271580c1f 100644 --- a/packages/mui-base/src/utils/useMessageBus.ts +++ b/packages/mui-base/src/utils/useMessageBus.ts @@ -40,7 +40,7 @@ export function createMessageBus(): MessageBus { * @ignore - internal hook. */ export function useMessageBus() { - const bus = React.useRef<MessageBus>(); + const bus = React.useRef<MessageBus | undefined>(undefined); if (!bus.current) { bus.current = createMessageBus(); } diff --git a/packages/mui-base/test/describeConformanceUnstyled.tsx b/packages/mui-base/test/describeConformanceUnstyled.tsx index 47efb7c54f4bdd..516ea6d92d757f 100644 --- a/packages/mui-base/test/describeConformanceUnstyled.tsx +++ b/packages/mui-base/test/describeConformanceUnstyled.tsx @@ -267,7 +267,7 @@ function testSlotPropsProp( }); } -function testClassName(element: React.ReactElement, getOptions: () => ConformanceOptions) { +function testClassName(element: React.ReactElement<any>, getOptions: () => ConformanceOptions) { it('applies the className to the root component', async () => { const { render } = getOptions(); diff --git a/packages/mui-joy/src/Autocomplete/Autocomplete.tsx b/packages/mui-joy/src/Autocomplete/Autocomplete.tsx index 96bbf5621d67ef..1d688d448de91e 100644 --- a/packages/mui-joy/src/Autocomplete/Autocomplete.tsx +++ b/packages/mui-joy/src/Autocomplete/Autocomplete.tsx @@ -45,7 +45,7 @@ import useSlot from '../utils/useSlot'; type OwnerState = Omit<AutocompleteOwnerState<any, any, any, any>, 'onChange' | 'defaultValue'>; -const defaultIsActiveElementInListbox = (listboxRef: React.RefObject<HTMLElement>) => +const defaultIsActiveElementInListbox = (listboxRef: React.RefObject<HTMLElement | null>) => listboxRef.current !== null && listboxRef.current.contains(document.activeElement); // @ts-ignore const defaultGetOptionLabel = (option) => option.label ?? option; diff --git a/packages/mui-joy/src/ButtonGroup/ButtonGroup.tsx b/packages/mui-joy/src/ButtonGroup/ButtonGroup.tsx index 00cd3fbff6f73c..5e4dfb829c243c 100644 --- a/packages/mui-joy/src/ButtonGroup/ButtonGroup.tsx +++ b/packages/mui-joy/src/ButtonGroup/ButtonGroup.tsx @@ -18,6 +18,7 @@ import ButtonGroupContext from './ButtonGroupContext'; import useSlot from '../utils/useSlot'; import buttonClasses from '../Button/buttonClasses'; import iconButtonClasses from '../IconButton/iconButtonClasses'; +import { DividerProps } from '../Divider'; const useUtilityClasses = (ownerState: ButtonGroupOwnerState) => { const { size, variant, color, orientation } = ownerState; @@ -236,11 +237,11 @@ const ButtonGroup = React.forwardRef(function ButtonGroup(inProps, ref) { } const extraProps: Record<string, any> = {}; if (isMuiElement(child, ['Divider'])) { - extraProps.inset = 'inset' in child.props ? child.props.inset : 'context'; + const childProps = child.props as DividerProps; + extraProps.inset = childProps?.inset ?? 'context'; const dividerOrientation = orientation === 'vertical' ? 'horizontal' : 'vertical'; - extraProps.orientation = - 'orientation' in child.props ? child.props.orientation : dividerOrientation; + extraProps.orientation = childProps?.orientation ?? dividerOrientation; extraProps.role = 'presentation'; extraProps.component = 'span'; } diff --git a/packages/mui-joy/src/Card/Card.tsx b/packages/mui-joy/src/Card/Card.tsx index 3fdd38efa29774..7ee7eda5de52d1 100644 --- a/packages/mui-joy/src/Card/Card.tsx +++ b/packages/mui-joy/src/Card/Card.tsx @@ -15,6 +15,7 @@ import { getCardUtilityClass } from './cardClasses'; import { CardProps, CardOwnerState, CardTypeMap } from './CardProps'; import { resolveSxValue } from '../styles/styleUtils'; import useSlot from '../utils/useSlot'; +import { DividerProps } from '../Divider'; const useUtilityClasses = (ownerState: CardOwnerState) => { const { size, variant, color, orientation } = ownerState; @@ -166,11 +167,11 @@ const Card = React.forwardRef(function Card(inProps, ref) { } const extraProps: Record<string, any> = {}; if (isMuiElement(child, ['Divider'])) { - extraProps.inset = 'inset' in child.props ? child.props.inset : 'context'; + const childProps = child.props as DividerProps; + extraProps.inset = childProps?.inset ?? 'context'; const dividerOrientation = orientation === 'vertical' ? 'horizontal' : 'vertical'; - extraProps.orientation = - 'orientation' in child.props ? child.props.orientation : dividerOrientation; + extraProps.orientation = childProps?.orientation ?? dividerOrientation; } if (index === 0) { extraProps['data-first-child'] = ''; diff --git a/packages/mui-joy/src/ListItem/ListItem.tsx b/packages/mui-joy/src/ListItem/ListItem.tsx index 3e9eb9baba8cc0..00c73d6a801214 100644 --- a/packages/mui-joy/src/ListItem/ListItem.tsx +++ b/packages/mui-joy/src/ListItem/ListItem.tsx @@ -11,7 +11,7 @@ import { unstable_composeClasses as composeClasses } from '@mui/base/composeClas import { styled, useThemeProps } from '../styles'; import useSlot from '../utils/useSlot'; -import { ListItemOwnerState, ListItemTypeMap } from './ListItemProps'; +import { ListItemOwnerState, ListItemProps, ListItemTypeMap } from './ListItemProps'; import listItemClasses, { getListItemUtilityClass } from './listItemClasses'; import NestedListContext from '../List/NestedListContext'; import RowListContext from '../List/RowListContext'; @@ -256,7 +256,7 @@ const ListItem = React.forwardRef(function ListItem(inProps, ref) { ...(index === 0 && { 'data-first-child': '' }), ...(isMuiElement(child, ['ListItem']) && { // The ListItem of ListItem should not be 'li' - component: child.props.component || 'div', + component: (child.props as ListItemProps)?.component || 'div', }), }) : child, diff --git a/packages/mui-joy/src/ModalDialog/ModalDialog.tsx b/packages/mui-joy/src/ModalDialog/ModalDialog.tsx index 36c6da2fd58d8d..633ee0ee3b2d2f 100644 --- a/packages/mui-joy/src/ModalDialog/ModalDialog.tsx +++ b/packages/mui-joy/src/ModalDialog/ModalDialog.tsx @@ -18,6 +18,7 @@ import ModalDialogSizeContext from './ModalDialogSizeContext'; import ModalDialogVariantColorContext from './ModalDialogVariantColorContext'; import useSlot from '../utils/useSlot'; import { StyledCardRoot } from '../Card/Card'; +import { DividerProps } from '../Divider'; const useUtilityClasses = (ownerState: ModalDialogOwnerState) => { const { variant, color, size, layout } = ownerState; @@ -195,11 +196,11 @@ const ModalDialog = React.forwardRef(function ModalDialog(inProps, ref) { } const extraProps: Record<string, any> = {}; if (isMuiElement(child, ['Divider'])) { - extraProps.inset = 'inset' in child.props ? child.props.inset : 'context'; + const childProps = child.props as DividerProps; + extraProps.inset = childProps?.inset ?? 'context'; const dividerOrientation = orientation === 'vertical' ? 'horizontal' : 'vertical'; - extraProps.orientation = - 'orientation' in child.props ? child.props.orientation : dividerOrientation; + extraProps.orientation = childProps?.orientation ?? dividerOrientation; } if (index === 0) { extraProps['data-first-child'] = ''; diff --git a/packages/mui-joy/src/Tab/Tab.tsx b/packages/mui-joy/src/Tab/Tab.tsx index 493758e11fe364..b8b84b45e3c5dc 100644 --- a/packages/mui-joy/src/Tab/Tab.tsx +++ b/packages/mui-joy/src/Tab/Tab.tsx @@ -150,7 +150,7 @@ const Tab = React.forwardRef(function Tab(inProps, ref) { ...other } = props; - const tabRef = React.useRef<HTMLButtonElement | HTMLAnchorElement | HTMLElement>(); + const tabRef = React.useRef<HTMLButtonElement | HTMLAnchorElement | HTMLElement | null>(null); const handleRef = useForkRef(tabRef, ref) as React.RefCallback<Element>; const { active, focusVisible, setFocusVisible, selected, getRootProps } = useTab({ diff --git a/packages/mui-joy/src/ToggleButtonGroup/ToggleButtonGroup.tsx b/packages/mui-joy/src/ToggleButtonGroup/ToggleButtonGroup.tsx index 85282d67ef56aa..82b747a653e911 100644 --- a/packages/mui-joy/src/ToggleButtonGroup/ToggleButtonGroup.tsx +++ b/packages/mui-joy/src/ToggleButtonGroup/ToggleButtonGroup.tsx @@ -21,6 +21,7 @@ import useSlot from '../utils/useSlot'; import { StyledButtonGroup } from '../ButtonGroup/ButtonGroup'; import ButtonGroupContext from '../ButtonGroup/ButtonGroupContext'; import ToggleButtonGroupContext from './ToggleButtonGroupContext'; +import { DividerProps } from '../Divider'; interface InternalChangeEventHandler<Value> { (event: React.MouseEvent, value: Value | Array<Value> | null): void; @@ -161,11 +162,11 @@ const ToggleButtonGroup = React.forwardRef(function ToggleButtonGroup< } const extraProps: Record<string, any> = {}; if (isMuiElement(child, ['Divider'])) { - extraProps.inset = 'inset' in child.props ? child.props.inset : 'context'; + const childProps = child.props as DividerProps; + extraProps.inset = childProps?.inset ?? 'context'; const dividerOrientation = orientation === 'vertical' ? 'horizontal' : 'vertical'; - extraProps.orientation = - 'orientation' in child.props ? child.props.orientation : dividerOrientation; + extraProps.orientation = childProps?.orientation ?? dividerOrientation; extraProps.role = 'presentation'; extraProps.component = 'span'; } diff --git a/packages/mui-joy/src/Tooltip/Tooltip.tsx b/packages/mui-joy/src/Tooltip/Tooltip.tsx index 7f48d74360228b..e34cf2596709ec 100644 --- a/packages/mui-joy/src/Tooltip/Tooltip.tsx +++ b/packages/mui-joy/src/Tooltip/Tooltip.tsx @@ -262,7 +262,7 @@ const Tooltip = React.forwardRef(function Tooltip(inProps, ref) { const id = useId(idProp); - const prevUserSelect: React.MutableRefObject<string | undefined> = React.useRef(); + const prevUserSelect = React.useRef<string | undefined>(undefined); const stopTouchInteraction = useEventCallback(() => { if (prevUserSelect.current !== undefined) { (document.body.style as unknown as { WebkitUserSelect?: string }).WebkitUserSelect = diff --git a/packages/mui-lab/src/Timeline/Timeline.tsx b/packages/mui-lab/src/Timeline/Timeline.tsx index f388d198b084d3..f5c7689f857c0d 100644 --- a/packages/mui-lab/src/Timeline/Timeline.tsx +++ b/packages/mui-lab/src/Timeline/Timeline.tsx @@ -21,8 +21,8 @@ const useUtilityClasses = (ownerState: OwnerState) => { return composeClasses(slots, getTimelineUtilityClass, classes); }; -const TimelineRoot = styled('ul' as const, { - name: 'MuiTimeline' as const, +const TimelineRoot = styled('ul', { + name: 'MuiTimeline', slot: 'Root', overridesResolver: (props, styles) => { const { ownerState } = props; @@ -62,7 +62,6 @@ const Timeline = React.forwardRef<HTMLUListElement, TimelineProps>(function Time <TimelineRoot className={clsx(classes.root, className)} ownerState={ownerState} - // @ts-expect-error TypeScript bug, need to keep unknown for DX ref={ref} {...other} /> diff --git a/packages/mui-lab/src/Timeline/Timeline.types.ts b/packages/mui-lab/src/Timeline/Timeline.types.ts index 01e9cbf6df0176..22207ea2316e96 100644 --- a/packages/mui-lab/src/Timeline/Timeline.types.ts +++ b/packages/mui-lab/src/Timeline/Timeline.types.ts @@ -4,7 +4,7 @@ import { Theme } from '@mui/material/styles'; import { SxProps } from '@mui/system'; import { TimelineClasses } from './timelineClasses'; -export interface TimelineProps extends StandardProps<React.HTMLAttributes<HTMLUListElement>> { +export interface TimelineProps extends StandardProps<React.ComponentProps<'ul'>> { /** * The position where the TimelineContent should appear relative to the time axis. * @default 'right' diff --git a/packages/mui-lab/test/describeConformance.ts b/packages/mui-lab/test/describeConformance.ts index 4715d91bad6817..5de62933d19dc5 100644 --- a/packages/mui-lab/test/describeConformance.ts +++ b/packages/mui-lab/test/describeConformance.ts @@ -5,7 +5,7 @@ import { import { ThemeProvider, createTheme } from '@mui/material/styles'; export default function describeConformance( - minimalElement: React.ReactElement<any>, + minimalElement: React.ReactElement<unknown>, getOptions: () => ConformanceOptions, ) { function getOptionsWithDefaults() { diff --git a/packages/mui-material-nextjs/src/v13-pagesRouter/pagesRouterV13Document.tsx b/packages/mui-material-nextjs/src/v13-pagesRouter/pagesRouterV13Document.tsx index 2bc922d62dd059..924b38638f4bfc 100644 --- a/packages/mui-material-nextjs/src/v13-pagesRouter/pagesRouterV13Document.tsx +++ b/packages/mui-material-nextjs/src/v13-pagesRouter/pagesRouterV13Document.tsx @@ -37,7 +37,7 @@ export function createGetInitialProps(plugins: Plugin[]) { } export interface DocumentHeadTagsProps { - emotionStyleTags: React.ReactElement<any>[]; + emotionStyleTags: React.ReactElement<unknown>[]; } export function DocumentHeadTags(props: DocumentHeadTagsProps) { diff --git a/packages/mui-material/src/Popper/Popper.spec.tsx b/packages/mui-material/src/Popper/Popper.spec.tsx index 0431883265da3f..94a4cad381add3 100644 --- a/packages/mui-material/src/Popper/Popper.spec.tsx +++ b/packages/mui-material/src/Popper/Popper.spec.tsx @@ -3,7 +3,7 @@ import { Instance } from '@popperjs/core'; import Tooltip from '@mui/material/Tooltip'; interface Props { - children: React.ReactElement<any>; + children: React.ReactElement<unknown>; value: number; } diff --git a/packages/mui-material/src/Slider/useSlider.ts b/packages/mui-material/src/Slider/useSlider.ts index 55c59e4d442a13..8437f59b13340e 100644 --- a/packages/mui-material/src/Slider/useSlider.ts +++ b/packages/mui-material/src/Slider/useSlider.ts @@ -220,7 +220,7 @@ export function useSlider(parameters: UseSliderParameters): UseSliderReturnValue value: valueProp, } = parameters; - const touchId = React.useRef<number>(); + const touchId = React.useRef<number | undefined>(undefined); // We can't use the :active browser pseudo-classes. // - The active state isn't triggered when clicking on the rail. // - The active state isn't transferred when inversing a range slider. @@ -275,7 +275,7 @@ export function useSlider(parameters: UseSliderParameters): UseSliderReturnValue } = useIsFocusVisible(); const [focusedThumbIndex, setFocusedThumbIndex] = React.useState(-1); - const sliderRef = React.useRef<HTMLSpanElement>(); + const sliderRef = React.useRef<HTMLSpanElement | null>(null); const handleFocusRef = useForkRef(focusVisibleRef, sliderRef); const handleRef = useForkRef(ref, handleFocusRef); @@ -407,7 +407,7 @@ export function useSlider(parameters: UseSliderParameters): UseSliderReturnValue changeValue(event, event.target.valueAsNumber); }; - const previousIndex = React.useRef<number>(); + const previousIndex = React.useRef<number | undefined>(undefined); let axis = orientation; if (isRtl && orientation === 'horizontal') { axis += '-reverse'; diff --git a/packages/mui-material/src/styles/styled.spec.tsx b/packages/mui-material/src/styles/styled.spec.tsx index 8053428c818c6a..b6646c7845c926 100644 --- a/packages/mui-material/src/styles/styled.spec.tsx +++ b/packages/mui-material/src/styles/styled.spec.tsx @@ -125,8 +125,8 @@ function Button({ return styles; }, startIcon: ({ ownerState: { startIcon, endIcon } }) => [ - startIcon && { marginRight: 8 }, - endIcon && { marginLeft: 8 }, + !!startIcon && { marginRight: 8 }, + !!endIcon && { marginLeft: 8 }, ], }, }, diff --git a/packages/mui-material/src/useAutocomplete/useAutocomplete.d.ts b/packages/mui-material/src/useAutocomplete/useAutocomplete.d.ts index 6c74f9c5f251b6..b1717d2db05788 100644 --- a/packages/mui-material/src/useAutocomplete/useAutocomplete.d.ts +++ b/packages/mui-material/src/useAutocomplete/useAutocomplete.d.ts @@ -49,7 +49,7 @@ export interface UseAutocompleteProps< * Temporary for Joy UI because the parent listbox is the document object * TODO v6: Normalize the logic and remove this param. */ - unstable_isActiveElementInListbox?: (listbox: React.RefObject<HTMLElement>) => boolean; + unstable_isActiveElementInListbox?: (listbox: React.RefObject<HTMLElement | null>) => boolean; /** * If `true`, the portion of the selected suggestion that the user hasn't typed, * known as the completion string, appears inline after the input cursor in the textbox. diff --git a/packages/mui-material/test/describeConformance.ts b/packages/mui-material/test/describeConformance.ts index 4715d91bad6817..5de62933d19dc5 100644 --- a/packages/mui-material/test/describeConformance.ts +++ b/packages/mui-material/test/describeConformance.ts @@ -5,7 +5,7 @@ import { import { ThemeProvider, createTheme } from '@mui/material/styles'; export default function describeConformance( - minimalElement: React.ReactElement<any>, + minimalElement: React.ReactElement<unknown>, getOptions: () => ConformanceOptions, ) { function getOptionsWithDefaults() { diff --git a/packages/mui-styled-engine-sc/src/GlobalStyles/GlobalStyles.d.ts b/packages/mui-styled-engine-sc/src/GlobalStyles/GlobalStyles.d.ts index 0c2ef1cd47e33f..d1881586abe383 100644 --- a/packages/mui-styled-engine-sc/src/GlobalStyles/GlobalStyles.d.ts +++ b/packages/mui-styled-engine-sc/src/GlobalStyles/GlobalStyles.d.ts @@ -8,4 +8,4 @@ export interface GlobalStylesProps<Theme extends object = {}> { export default function Global<Theme extends object = {}>( props: GlobalStylesProps<Theme>, -): React.ReactElement<any>; +): React.JSX.Element; diff --git a/packages/mui-styled-engine-sc/src/GlobalStyles/GlobalStyles.spec.tsx b/packages/mui-styled-engine-sc/src/GlobalStyles/GlobalStyles.spec.tsx index f253f453661a40..8365b797407f18 100644 --- a/packages/mui-styled-engine-sc/src/GlobalStyles/GlobalStyles.spec.tsx +++ b/packages/mui-styled-engine-sc/src/GlobalStyles/GlobalStyles.spec.tsx @@ -25,7 +25,7 @@ export interface GlobalStylesProps { styles: SCGlobalStylesProps<Theme>['styles']; } -function GlobalStyles(props: GlobalStylesProps): React.ReactElement<any> { +function GlobalStyles(props: GlobalStylesProps): React.JSX.Element { return <SCGlobalStyles {...props} defaultTheme={defaultTheme} />; } diff --git a/packages/mui-styled-engine/src/GlobalStyles/GlobalStyles.d.ts b/packages/mui-styled-engine/src/GlobalStyles/GlobalStyles.d.ts index e746c3036a3a62..a7a7f66f2c78d5 100644 --- a/packages/mui-styled-engine/src/GlobalStyles/GlobalStyles.d.ts +++ b/packages/mui-styled-engine/src/GlobalStyles/GlobalStyles.d.ts @@ -8,4 +8,4 @@ export interface GlobalStylesProps<Theme = {}> { export default function GlobalStyles<Theme = {}>( props: GlobalStylesProps<Theme>, -): React.ReactElement<any>; +): React.JSX.Element; diff --git a/packages/mui-styled-engine/src/GlobalStyles/GlobalStyles.spec.tsx b/packages/mui-styled-engine/src/GlobalStyles/GlobalStyles.spec.tsx index 13b34d7f29b019..142e29f5d4bb75 100644 --- a/packages/mui-styled-engine/src/GlobalStyles/GlobalStyles.spec.tsx +++ b/packages/mui-styled-engine/src/GlobalStyles/GlobalStyles.spec.tsx @@ -25,7 +25,7 @@ export interface GlobalStylesProps { styles: EmGlobalStylesProps<Theme>['styles']; } -function GlobalStyles(props: GlobalStylesProps): React.ReactElement<any> { +function GlobalStyles(props: GlobalStylesProps): React.JSX.Element { return <EmGlobalStyles {...props} defaultTheme={defaultTheme} />; } diff --git a/packages/mui-system/src/Stack/createStack.tsx b/packages/mui-system/src/Stack/createStack.tsx index 0f1f9659ebb952..3f9eb3877487bb 100644 --- a/packages/mui-system/src/Stack/createStack.tsx +++ b/packages/mui-system/src/Stack/createStack.tsx @@ -50,7 +50,7 @@ function useThemePropsDefault<T extends {}>(props: T) { * > joinChildren([1,2,3], 0) * [1,0,2,0,3] */ -function joinChildren(children: React.ReactNode, separator: React.ReactElement<any>) { +function joinChildren(children: React.ReactNode, separator: React.ReactElement<unknown>) { const childrenArray = React.Children.toArray(children).filter(Boolean); return childrenArray.reduce<React.ReactNode[]>((output, child, index) => { @@ -209,7 +209,7 @@ export default function createStack( className={clsx(classes.root, className)} {...other} > - {divider ? joinChildren(children, divider as React.ReactElement<any>) : children} + {divider ? joinChildren(children, divider as React.ReactElement<unknown>) : children} </StackRoot> ); }) as OverridableComponent<StackTypeMap>; diff --git a/packages/mui-system/src/Unstable_Grid/createGrid.tsx b/packages/mui-system/src/Unstable_Grid/createGrid.tsx index e0984a90dd7f23..24c6756da8527b 100644 --- a/packages/mui-system/src/Unstable_Grid/createGrid.tsx +++ b/packages/mui-system/src/Unstable_Grid/createGrid.tsx @@ -164,9 +164,12 @@ export default function createGrid( {...other} > {React.Children.map(children, (child) => { - if (React.isValidElement(child) && isMuiElement(child, ['Grid'])) { + if ( + React.isValidElement<{ container?: unknown }>(child) && + isMuiElement(child, ['Grid']) + ) { return React.cloneElement(child, { - unstable_level: (child.props as any).unstable_level ?? level + 1, + unstable_level: (child.props as GridProps)?.unstable_level ?? level + 1, } as GridProps); } return child; diff --git a/packages/mui-system/src/cssVars/createCssVarsProvider.d.ts b/packages/mui-system/src/cssVars/createCssVarsProvider.d.ts index 00737cb84b8ee5..dd508d52640bc6 100644 --- a/packages/mui-system/src/cssVars/createCssVarsProvider.d.ts +++ b/packages/mui-system/src/cssVars/createCssVarsProvider.d.ts @@ -90,7 +90,7 @@ export interface CreateCssVarsProviderResult< disableStyleSheetGeneration?: boolean; } >, - ) => React.ReactElement<any>; + ) => React.JSX.Element; useColorScheme: () => ColorSchemeContextValue<ColorScheme>; getInitColorSchemeScript: typeof InitColorSchemeScript; } diff --git a/packages/mui-system/test/describeConformance.ts b/packages/mui-system/test/describeConformance.ts index aa876199917f98..125489ae430922 100644 --- a/packages/mui-system/test/describeConformance.ts +++ b/packages/mui-system/test/describeConformance.ts @@ -5,7 +5,7 @@ import { import { ThemeProvider, createTheme } from '@mui/system'; export default function describeConformance( - minimalElement: React.ReactElement<any>, + minimalElement: React.ReactElement<unknown>, getOptions: () => ConformanceOptions, ) { function getOptionsWithDefaults() { diff --git a/packages/mui-utils/src/getValidReactChildren/getValidReactChildren.ts b/packages/mui-utils/src/getValidReactChildren/getValidReactChildren.ts index ea1132e5fc32ba..f7e33f77d73551 100644 --- a/packages/mui-utils/src/getValidReactChildren/getValidReactChildren.ts +++ b/packages/mui-utils/src/getValidReactChildren/getValidReactChildren.ts @@ -9,5 +9,5 @@ import * as React from 'react'; export default function getValidReactChildren(children: React.ReactNode) { return React.Children.toArray(children).filter((child) => React.isValidElement(child), - ) as React.ReactElement<any>[]; + ) as React.ReactElement<unknown>[]; } diff --git a/packages/mui-utils/src/setRef/setRef.spec.tsx b/packages/mui-utils/src/setRef/setRef.spec.tsx index c9c90757c0d8af..a5be046dd0914a 100644 --- a/packages/mui-utils/src/setRef/setRef.spec.tsx +++ b/packages/mui-utils/src/setRef/setRef.spec.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import setRef from './setRef'; function MyRef() { - const ref = React.useRef<HTMLDivElement>(); + const ref = React.useRef<HTMLDivElement | null>(null); const handleRef = React.useCallback((node: HTMLDivElement) => { setRef(ref, node); diff --git a/packages/test-utils/src/createRenderer.tsx b/packages/test-utils/src/createRenderer.tsx index 8c3785247c75af..627783c6693c7a 100644 --- a/packages/test-utils/src/createRenderer.tsx +++ b/packages/test-utils/src/createRenderer.tsx @@ -281,8 +281,12 @@ export interface MuiRenderToStringResult { hydrate(): MuiRenderResult; } +interface DataAttributes { + [key: `data-${string}`]: string; +} + function render( - element: React.ReactElement<any>, + element: React.ReactElement<DataAttributes>, configuration: ClientRenderConfiguration, ): MuiRenderResult { const { container, hydrate, wrapper } = configuration; @@ -317,7 +321,7 @@ function render( } function renderToString( - element: React.ReactElement<any>, + element: React.ReactElement<DataAttributes>, configuration: ServerRenderConfiguration, ): { container: HTMLElement; hydrate(): MuiRenderResult } { const { container, wrapper: Wrapper } = configuration; @@ -439,9 +443,9 @@ function createClock(defaultMode: 'fake' | 'real', config: ClockConfig): Clock { interface Renderer { clock: Clock; - render(element: React.ReactElement<any>, options?: RenderOptions): MuiRenderResult; + render(element: React.ReactElement<DataAttributes>, options?: RenderOptions): MuiRenderResult; renderToString( - element: React.ReactElement<any>, + element: React.ReactElement<DataAttributes>, options?: RenderOptions, ): MuiRenderToStringResult; } @@ -581,7 +585,7 @@ export function createRenderer(globalOptions: CreateRendererOptions = {}): Rende return { clock, - render(element: React.ReactElement<any>, options: RenderOptions = {}) { + render(element: React.ReactElement<DataAttributes>, options: RenderOptions = {}) { if (!prepared) { throw new Error( 'Unable to finish setup before `render()` was called. ' + @@ -596,7 +600,7 @@ export function createRenderer(globalOptions: CreateRendererOptions = {}): Rende wrapper: createWrapper(options), }); }, - renderToString(element: React.ReactElement<any>, options: RenderOptions = {}) { + renderToString(element: React.ReactElement<DataAttributes>, options: RenderOptions = {}) { if (!prepared) { throw new Error( 'Unable to finish setup before `render()` was called. ' +