diff --git a/package-lock.json b/package-lock.json index b13b2a1d24..b89cdbe4ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -102,8 +102,8 @@ "yarn": "Please use npm instead of yarn to install dependencies" }, "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/@aashutoshrathi/word-wrap": { diff --git a/package.json b/package.json index 3d5fd72be6..2684a8ad8a 100644 --- a/package.json +++ b/package.json @@ -204,8 +204,8 @@ "typescript": "^5.3.3" }, "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "nano-staged": { "*.{scss}": [ diff --git a/src/components/ActionTooltip/ActionTooltip.tsx b/src/components/ActionTooltip/ActionTooltip.tsx index c65ec3bdd5..ad2b5e38b9 100644 --- a/src/components/ActionTooltip/ActionTooltip.tsx +++ b/src/components/ActionTooltip/ActionTooltip.tsx @@ -11,6 +11,7 @@ import {Popup} from '../Popup'; import type {PopupPlacement} from '../Popup'; import type {DOMProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {getElementRef} from '../utils/getElementRef'; import './ActionTooltip.scss'; @@ -77,7 +78,7 @@ export function ActionTooltip(props: ActionTooltipProps) { }; const child = React.Children.only(children); - const childRef = (child as any).ref; + const childRef = getElementRef(child); const ref = useForkRef(setAnchorElement, childRef); diff --git a/src/components/Tooltip/Tooltip.tsx b/src/components/Tooltip/Tooltip.tsx index 45b9a9b487..d9390f8a88 100644 --- a/src/components/Tooltip/Tooltip.tsx +++ b/src/components/Tooltip/Tooltip.tsx @@ -10,6 +10,7 @@ import type {PopupPlacement} from '../Popup'; import {Text} from '../Text'; import type {DOMProps, QAProps} from '../types'; import {block} from '../utils/cn'; +import {getElementRef} from '../utils/getElementRef'; import './Tooltip.scss'; @@ -75,7 +76,7 @@ export const Tooltip = (props: TooltipProps) => { }; const child = React.Children.only(children); - const childRef = (child as any).ref; + const childRef = getElementRef(child); const ref = useForkRef(setAnchorElement, childRef); diff --git a/src/components/index.ts b/src/components/index.ts index 400a4dfdf1..2b9b1d0d15 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -66,3 +66,4 @@ export * from './utils/layer-manager'; export {Lang, configure, getConfig} from './utils/configure'; export * from './utils/xpath'; export {getUniqId} from './utils/common'; +export {getElementRef} from './utils/getElementRef'; diff --git a/src/components/utils/FocusTrap.tsx b/src/components/utils/FocusTrap.tsx index 97f032a848..5d60e36eca 100644 --- a/src/components/utils/FocusTrap.tsx +++ b/src/components/utils/FocusTrap.tsx @@ -7,6 +7,8 @@ import type {FocusTrap as FocusTrapInstance} from 'focus-trap'; import {useForkRef, useUniqId} from '../../hooks'; +import {getElementRef} from './getElementRef'; + interface FocusTrapContext { addNode: (id: string, node: HTMLElement) => void; removeNode: (id: string) => void; @@ -90,7 +92,7 @@ export function FocusTrap({ if (!React.isValidElement(child)) { throw new Error('Children must contain only one valid element'); } - const childRef = (child as any).ref; + const childRef = getElementRef(child); const ref = useForkRef(handleNodeRef, childRef); diff --git a/src/components/utils/getElementRef.ts b/src/components/utils/getElementRef.ts new file mode 100644 index 0000000000..bedf8c1ed2 --- /dev/null +++ b/src/components/utils/getElementRef.ts @@ -0,0 +1,11 @@ +// Access the element's ref using a method that doesn't produce a warning. +export function getElementRef(element: React.ReactElement) { + if (process.env.NODE_ENV !== 'production') { + // Before React 19, there is an access check for ReactElement's props.ref in dev builds. + const getter = Object.getOwnPropertyDescriptor(element.props, 'ref')?.get; + if (getter && 'isReactWarning' in getter && getter.isReactWarning) { + return (element as any).ref; + } + } + return element.props.ref ?? (element as any).ref; +}