Skip to content

Commit 5e71b4c

Browse files
committed
fix(react-components): use custom RefAttributes instead of React.RefAttributes
1 parent 813b1fb commit 5e71b4c

File tree

11 files changed

+85
-77
lines changed

11 files changed

+85
-77
lines changed

packages/eslint-plugin/src/configs/react.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ module.exports = {
3737
},
3838
],
3939
'react-compiler/react-compiler': ['error'],
40+
'@typescript-eslint/no-restricted-types': [
41+
'error',
42+
{
43+
types: {
44+
'React.RefAttributes': {
45+
message:
46+
'`React.RefAttributes` is leaking string starting @types/[email protected] creating invalid type contracts. Use `RefAttributes` from @fluentui/react-utilities instead',
47+
fixWith: 'RefAttributes',
48+
},
49+
},
50+
},
51+
],
4052
},
4153
overrides: [
4254
// Enable rules requiring type info only for appropriate files/circumstances

packages/react-components/react-migration-v8-v9/library/src/components/Button/ActionButtonShim.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ import * as React from 'react';
33
import type { IButtonProps } from '@fluentui/react';
44

55
import { Button } from '@fluentui/react-components';
6+
import type { RefAttributes } from '@fluentui/react-utilities';
67

78
import { shimButtonProps } from './shimButtonProps';
89

910
/**
1011
* Shims a v8 ActionButton to render a v9 Button
1112
*/
12-
export const ActionButtonShim: React.ForwardRefExoticComponent<IButtonProps & React.RefAttributes<HTMLButtonElement>> =
13-
React.forwardRef((props, _ref) => {
14-
const variantProps = {
15-
...props,
16-
variantClassName: 'ms-Button--action ms-Button--command',
17-
};
13+
export const ActionButtonShim = React.forwardRef((props: IButtonProps, _ref: React.ForwardedRef<HTMLButtonElement>) => {
14+
const variantProps = {
15+
...props,
16+
variantClassName: 'ms-Button--action ms-Button--command',
17+
};
1818

19-
const shimProps = shimButtonProps(variantProps);
19+
const shimProps = shimButtonProps(variantProps);
2020

21-
return <Button {...(props as React.RefAttributes<HTMLButtonElement>)} {...shimProps} appearance="transparent" />;
22-
});
21+
return <Button {...(props as RefAttributes<HTMLButtonElement>)} {...shimProps} appearance="transparent" />;
22+
});

packages/react-components/react-migration-v8-v9/library/src/components/Button/ButtonShim.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@ import * as React from 'react';
33
import type { IBaseButtonProps } from '@fluentui/react';
44

55
import { Button } from '@fluentui/react-components';
6+
import type { RefAttributes } from '@fluentui/react-utilities';
67

78
import { shimButtonProps } from './shimButtonProps';
89
import { ToggleButtonShim } from './ToggleButtonShim';
910
import { CompoundButtonShim } from './CompoundButtonShim';
1011

11-
export const ButtonShim: React.ForwardRefExoticComponent<IBaseButtonProps & React.RefAttributes<HTMLButtonElement>> =
12-
React.forwardRef((props, _ref) => {
13-
const shimProps = shimButtonProps(props);
12+
export const ButtonShim = React.forwardRef<HTMLButtonElement, IBaseButtonProps>((props, _ref) => {
13+
const shimProps = shimButtonProps(props);
1414

15-
if (props.toggle) {
16-
return <ToggleButtonShim {...props}>{props.children}</ToggleButtonShim>;
17-
}
18-
if (props.secondaryText || props.onRenderDescription?.(props)) {
19-
return <CompoundButtonShim {...props} />;
20-
}
15+
if (props.toggle) {
16+
return <ToggleButtonShim {...props}>{props.children}</ToggleButtonShim>;
17+
}
18+
if (props.secondaryText || props.onRenderDescription?.(props)) {
19+
return <CompoundButtonShim {...props} />;
20+
}
2121

22-
return <Button {...(props as React.RefAttributes<HTMLButtonElement>)} {...shimProps} />;
23-
});
22+
return <Button {...(props as RefAttributes<HTMLButtonElement>)} {...shimProps} />;
23+
});

packages/react-components/react-migration-v8-v9/library/src/components/Button/CompoundButtonShim.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ import type { IButtonProps } from '@fluentui/react';
44

55
import { CompoundButton } from '@fluentui/react-components';
66
import type { CompoundButtonProps } from '@fluentui/react-components';
7+
import type { RefAttributes } from '@fluentui/react-utilities';
78

89
import { shimButtonProps } from './shimButtonProps';
910

1011
/**
1112
* Shims v8 CompoundButton to render a v9 CompoundButton
1213
*/
13-
export const CompoundButtonShim: React.ForwardRefExoticComponent<
14-
IButtonProps & React.RefAttributes<HTMLButtonElement>
15-
> = React.forwardRef((props, _ref) => {
14+
export const CompoundButtonShim = React.forwardRef<HTMLButtonElement, IButtonProps>((props, _ref) => {
1615
const variantProps = {
1716
...props,
1817
variantClassName: props.primary ? 'ms-Button--compoundPrimary' : 'ms-Button--compound',
@@ -23,5 +22,5 @@ export const CompoundButtonShim: React.ForwardRefExoticComponent<
2322
secondaryContent: props.secondaryText || props.onRenderDescription?.(props),
2423
};
2524

26-
return <CompoundButton {...(props as React.RefAttributes<HTMLButtonElement>)} {...shimProps} />;
25+
return <CompoundButton {...(props as RefAttributes<HTMLButtonElement>)} {...shimProps} />;
2726
});

packages/react-components/react-migration-v8-v9/library/src/components/Button/DefaultButtonShim.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { ButtonShim } from './ButtonShim';
77
/**
88
* Shims a v8 DefaultButton to render a v9 Button
99
*/
10-
export const DefaultButtonShim: React.ForwardRefExoticComponent<IButtonProps & React.RefAttributes<HTMLButtonElement>> =
11-
React.forwardRef((props, _ref) => {
12-
return <ButtonShim {...props} variantClassName={props.primary ? 'ms-Button--primary' : 'ms-Button--default'} />;
13-
});
10+
export const DefaultButtonShim = React.forwardRef<HTMLButtonElement, IButtonProps>((props, _ref) => {
11+
return <ButtonShim {...props} variantClassName={props.primary ? 'ms-Button--primary' : 'ms-Button--default'} />;
12+
});

packages/react-components/react-migration-v8-v9/library/src/components/Button/MenuButtonShim.tsx

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,32 @@ import { MenuItemShim, shimMenuProps } from '../Menu/index';
77

88
import { shimButtonProps } from './shimButtonProps';
99

10-
export const MenuButtonShim: React.ForwardRefExoticComponent<IButtonProps & React.RefAttributes<HTMLButtonElement>> =
11-
React.forwardRef((props, _ref) => {
12-
const variantProps = {
13-
...props,
14-
variantClassName: props.primary ? 'ms-Button--primary' : 'ms-Button--default',
15-
};
10+
export const MenuButtonShim = React.forwardRef<HTMLButtonElement, IButtonProps>((props, _ref) => {
11+
const variantProps = {
12+
...props,
13+
variantClassName: props.primary ? 'ms-Button--primary' : 'ms-Button--default',
14+
};
1615

17-
const shimProps: MenuButtonProps = {
18-
...shimButtonProps(variantProps),
19-
};
16+
const shimProps: MenuButtonProps = {
17+
...shimButtonProps(variantProps),
18+
};
2019

21-
const shimmedMenuProps = props.menuProps ? shimMenuProps(props.menuProps) : {};
20+
const shimmedMenuProps = props.menuProps ? shimMenuProps(props.menuProps) : {};
2221

23-
return (
24-
<Menu {...shimmedMenuProps}>
25-
<MenuTrigger>
26-
<MenuButton {...shimProps} />
27-
</MenuTrigger>
28-
<MenuPopover>
29-
<MenuList>
30-
{props.menuProps?.items.map(item => (
31-
// key is added through item spread
32-
// eslint-disable-next-line react/jsx-key
33-
<MenuItemShim {...item} />
34-
))}
35-
</MenuList>
36-
</MenuPopover>
37-
</Menu>
38-
);
39-
});
22+
return (
23+
<Menu {...shimmedMenuProps}>
24+
<MenuTrigger>
25+
<MenuButton {...shimProps} />
26+
</MenuTrigger>
27+
<MenuPopover>
28+
<MenuList>
29+
{props.menuProps?.items.map(item => (
30+
// key is added through item spread
31+
// eslint-disable-next-line react/jsx-key
32+
<MenuItemShim {...item} />
33+
))}
34+
</MenuList>
35+
</MenuPopover>
36+
</Menu>
37+
);
38+
});

packages/react-components/react-migration-v8-v9/library/src/components/Button/PrimaryButtonShim.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { ButtonShim } from './ButtonShim';
66
/**
77
* Shims v8 PrimaryButton to render a v9 Button
88
*/
9-
export const PrimaryButtonShim: React.ForwardRefExoticComponent<IButtonProps & React.RefAttributes<HTMLButtonElement>> =
10-
React.forwardRef((props, _ref) => {
11-
return <ButtonShim {...props} primary variantClassName="ms-Button--primary" />;
12-
});
9+
export const PrimaryButtonShim = React.forwardRef<HTMLButtonElement, IButtonProps>((props, _ref) => {
10+
return <ButtonShim {...props} primary variantClassName="ms-Button--primary" />;
11+
});

packages/react-components/react-migration-v8-v9/library/src/components/Button/ToggleButtonShim.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,24 @@ import type { IButtonProps } from '@fluentui/react';
44

55
import { ToggleButton } from '@fluentui/react-components';
66
import type { ToggleButtonProps } from '@fluentui/react-components';
7+
import type { RefAttributes } from '@fluentui/react-utilities';
78

89
import { shimButtonProps } from './shimButtonProps';
910

1011
/**
1112
* Shims v8 ToggleButton to render a v9 ToggleButton
1213
*/
13-
export const ToggleButtonShim: React.ForwardRefExoticComponent<IButtonProps & React.RefAttributes<HTMLButtonElement>> =
14-
React.forwardRef((props, _ref) => {
15-
const variantProps = {
16-
...props,
17-
variantClassName: props.primary ? 'ms-Button--compoundPrimary' : 'ms-Button--compound',
18-
};
14+
export const ToggleButtonShim = React.forwardRef<HTMLButtonElement, IButtonProps>((props, _ref) => {
15+
const variantProps = {
16+
...props,
17+
variantClassName: props.primary ? 'ms-Button--compoundPrimary' : 'ms-Button--compound',
18+
};
1919

20-
const shimProps: ToggleButtonProps = {
21-
...shimButtonProps(variantProps),
22-
checked: props.checked,
23-
defaultChecked: props.defaultChecked,
24-
};
20+
const shimProps: ToggleButtonProps = {
21+
...shimButtonProps(variantProps),
22+
checked: props.checked,
23+
defaultChecked: props.defaultChecked,
24+
};
2525

26-
return <ToggleButton {...(props as React.RefAttributes<HTMLButtonElement>)} {...shimProps} />;
27-
});
26+
return <ToggleButton {...(props as RefAttributes<HTMLButtonElement>)} {...shimProps} />;
27+
});

packages/react-components/react-nav-preview/library/src/components/NavDrawer/useNavDrawer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import { Drawer, DrawerProps } from '@fluentui/react-drawer';
33
import { useArrowNavigationGroup } from '@fluentui/react-tabster';
4-
import { slot } from '@fluentui/react-utilities';
4+
import { RefAttributes, slot } from '@fluentui/react-utilities';
55

66
import { useNav_unstable } from '../Nav/useNav';
77
import type { NavDrawerProps, NavDrawerState } from './NavDrawer.types';
@@ -49,7 +49,7 @@ export const useNavDrawer_unstable = (props: NavDrawerProps, ref: React.Ref<HTML
4949
// this is a problem with the lack of support for union types on React v18
5050
// ComponentState is using React.ComponentType which will try to infer propType
5151
// propTypes WeakValidator signature will break distributive unions making this type invalid
52-
elementType: Drawer as React.FC<DrawerProps & React.RefAttributes<HTMLDivElement>>,
52+
elementType: Drawer as React.FC<DrawerProps & RefAttributes<HTMLDivElement>>,
5353
},
5454
),
5555
};

packages/react-components/react-utilities/etc/react-utilities.api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export function getEventClientCoords(event: TouchOrMouseEvent): {
7272
};
7373

7474
// @public
75-
export const getIntrinsicElementProps: <Props extends UnknownSlotProps, ExcludedPropKeys extends Extract<keyof Props, string> = never>(tagName: NonNullable<Props["as"]>, props: Props & React_2.RefAttributes<InferredElementRefType<Props>>, excludedPropNames?: ExcludedPropKeys[] | undefined) => DistributiveOmit<Props, ExcludedPropKeys | Exclude<keyof Props, "as" | keyof HTMLAttributes>>;
75+
export const getIntrinsicElementProps: <Props extends UnknownSlotProps, ExcludedPropKeys extends Extract<keyof Props, string> = never>(tagName: NonNullable<Props["as"]>, props: Props & RefAttributes<InferredElementRefType<Props>>, excludedPropNames?: ExcludedPropKeys[] | undefined) => DistributiveOmit<Props, ExcludedPropKeys | Exclude<keyof Props, "as" | keyof HTMLAttributes>>;
7676

7777
// @public @deprecated
7878
export function getNativeElementProps<TAttributes extends React_2.HTMLAttributes<any>>(tagName: string, props: {}, excludedPropNames?: string[]): TAttributes;

packages/react-components/react-utilities/src/compose/getIntrinsicElementProps.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import { getNativeElementProps } from '../utils/getNativeElementProps';
33
import type { InferredElementRefType, UnknownSlotProps } from './types';
4-
import type { DistributiveOmit } from '../utils/types';
4+
import type { DistributiveOmit, RefAttributes } from '../utils/types';
55

66
// eslint-disable-next-line @typescript-eslint/no-explicit-any
77
type HTMLAttributes = React.HTMLAttributes<any>;
@@ -19,7 +19,7 @@ export const getIntrinsicElementProps = <
1919
/** The slot's default element type (e.g. 'div') */
2020
tagName: NonNullable<Props['as']>,
2121
/** The component's props object */
22-
props: Props & React.RefAttributes<InferredElementRefType<Props>>,
22+
props: Props & RefAttributes<InferredElementRefType<Props>>,
2323
/** List of native props to exclude from the returned value */
2424
excludedPropNames?: ExcludedPropKeys[],
2525
) => {

0 commit comments

Comments
 (0)