Skip to content

Commit

Permalink
[material-ui][mui-system] Refactor types so they're compatible with u…
Browse files Browse the repository at this point in the history
…pcoming React 19 (#43276)
  • Loading branch information
DiegoAndai authored Aug 13, 2024
1 parent ae6fb01 commit 795a8c9
Show file tree
Hide file tree
Showing 40 changed files with 88 additions and 72 deletions.
2 changes: 1 addition & 1 deletion docs/data/joy/components/input/DebouncedInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Box from '@mui/joy/Box';
function DebounceInput(props) {
const { handleDebounce, debounceTimeout, ...other } = props;

const timerRef = React.useRef();
const timerRef = React.useRef(undefined);

const handleChange = (event) => {
clearTimeout(timerRef.current);
Expand Down
4 changes: 3 additions & 1 deletion docs/data/joy/components/input/DebouncedInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ type DebounceProps = {
function DebounceInput(props: InputProps & DebounceProps) {
const { handleDebounce, debounceTimeout, ...other } = 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);
Expand Down
4 changes: 2 additions & 2 deletions docs/data/joy/components/snackbar/SnackbarHideDuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand Down
4 changes: 2 additions & 2 deletions docs/data/joy/components/snackbar/SnackbarHideDuration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 && {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 && {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
() => () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
() => () => {
Expand Down
4 changes: 2 additions & 2 deletions docs/pages/base-ui/api/use-autocomplete.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@
},
"unstable_isActiveElementInListbox": {
"type": {
"name": "(listbox: React.RefObject&lt;HTMLElement&gt;) =&gt; boolean",
"description": "(listbox: React.RefObject&lt;HTMLElement&gt;) =&gt; boolean"
"name": "(listbox: React.RefObject&lt;HTMLElement | null&gt;) =&gt; boolean",
"description": "(listbox: React.RefObject&lt;HTMLElement | null&gt;) =&gt; boolean"
}
},
"value": {
Expand Down
2 changes: 1 addition & 1 deletion docs/src/components/animation/FlashCode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const FlashCode = React.forwardRef(function FlashCode(
startLine?: number;
lineHeight?: number | string;
},
ref: React.Ref<HTMLDivElement>,
ref: React.ForwardedRef<HTMLDivElement>,
) {
const { children, startLine = 0, endLine = startLine, lineHeight = '0.75rem', ...other } = props;

Expand Down
21 changes: 13 additions & 8 deletions docs/src/modules/components/JoyThemeBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,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,
Expand All @@ -996,13 +1000,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 };
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/Tab/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/useAutocomplete/useAutocomplete.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions packages/mui-base/src/useButton/useButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -200,7 +200,7 @@ export function useButton(parameters: UseButtonParameters = {}): UseButtonReturn
}
if (disabled) {
buttonProps['aria-disabled'] = disabled as boolean;
buttonProps.tabIndex = focusableWhenDisabled ? tabIndex ?? 0 : -1;
buttonProps.tabIndex = focusableWhenDisabled ? (tabIndex ?? 0) : -1;
}
}

Expand Down
8 changes: 4 additions & 4 deletions packages/mui-base/src/useCompound/useCompound.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down Expand Up @@ -188,7 +188,7 @@ describe('compound components', () => {
const { children } = props;
const { contextValue } = useCompoundParent<
string,
{ ref: React.RefObject<HTMLSpanElement> }
{ ref: React.RefObject<HTMLSpanElement | null> }
>();

return (
Expand Down Expand Up @@ -240,7 +240,7 @@ describe('compound components', () => {
const { children } = props;
const { contextValue } = useCompoundParent<
number,
{ ref: React.RefObject<HTMLLIElement> }
{ ref: React.RefObject<HTMLLIElement | null> }
>();

return (
Expand All @@ -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 }), []),
);
Expand Down
9 changes: 6 additions & 3 deletions packages/mui-base/src/useCompound/useCompoundParent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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) => {
Expand Down Expand Up @@ -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>());
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/useMenu/menuReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/useMenuItem/useMenuItem.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 &
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/useOption/useOption.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
8 changes: 4 additions & 4 deletions packages/mui-base/src/useSlider/useSlider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -267,7 +267,7 @@ export function useSlider(parameters: UseSliderParameters): UseSliderReturnValue

const [focusedThumbIndex, setFocusedThumbIndex] = React.useState(-1);

const sliderRef = React.useRef<HTMLSpanElement>();
const sliderRef = React.useRef<HTMLSpanElement | null>(null);
const handleRef = useForkRef(ref, sliderRef);

const createHandleHiddenInputFocus =
Expand Down Expand Up @@ -396,7 +396,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';
Expand Down Expand Up @@ -712,7 +712,7 @@ export function useSlider(parameters: UseSliderParameters): UseSliderReturnValue
type: 'range',
min: parameters.min,
max: parameters.max,
step: parameters.step === null && parameters.marks ? 'any' : parameters.step ?? undefined,
step: parameters.step === null && parameters.marks ? 'any' : (parameters.step ?? undefined),
disabled,
...externalProps,
...mergedEventHandlers,
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/useTabs/TabsProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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> &
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/useTabs/useTabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/src/utils/useMessageBus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-base/test/describeConformanceUnstyled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
2 changes: 1 addition & 1 deletion packages/mui-docs/src/Ad/Ad.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export function Ad() {
const ad = React.useContext(AdContext);
const eventLabel = label ? `${label}-${ad.placement}-${adShape}` : null;

const timerAdblock = React.useRef<ReturnType<typeof setTimeout>>();
const timerAdblock = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined);

const checkAdblock = React.useCallback(
(attempt = 1) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-docs/src/CodeCopy/useClipboardCopy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import clipboardCopy from 'clipboard-copy';

export default function useClipboardCopy() {
const [isCopied, setIsCopied] = React.useState(false);
const timeout = React.useRef<ReturnType<typeof setTimeout>>();
const timeout = React.useRef<ReturnType<typeof setTimeout> | undefined>(undefined);

React.useEffect(
() => () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-joy/src/Autocomplete/Autocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 4 additions & 3 deletions packages/mui-joy/src/ButtonGroup/ButtonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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';
}
Expand Down
Loading

0 comments on commit 795a8c9

Please sign in to comment.