React 19: non-breaking type and test changes (#114760)

non-breaking type and test changes needed for react 19
This commit is contained in:
Ashley Harrison
2025-12-04 16:19:25 +00:00
committed by GitHub
parent 030c7099cb
commit d7d0c104ab
35 changed files with 82 additions and 83 deletions
@@ -19,7 +19,7 @@ export interface Props<T = string> extends Omit<FieldProps, 'children'> {
/** Custom error message to display on saving */
saveErrorMessage?: string;
/** Input that will save its value on change */
children: (onChange: (newValue: T) => void) => React.ReactElement;
children: (onChange: (newValue: T) => void) => React.ReactElement<Record<string, unknown>>;
}
/**
@@ -22,7 +22,7 @@ type BaseProps = {
size?: ComponentSize;
variant?: ButtonVariant;
fill?: ButtonFill;
icon?: IconName | React.ReactElement;
icon?: IconName | React.ReactElement<IconElementProps>;
className?: string;
fullWidth?: boolean;
type?: string;
@@ -207,8 +207,13 @@ export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
LinkButton.displayName = 'LinkButton';
type IconElementProps = {
className?: string;
size?: IconSize;
};
interface IconRendererProps {
icon?: IconName | React.ReactElement<{ className?: string; size?: IconSize }>;
icon?: IconName | React.ReactElement<IconElementProps>;
size?: IconSize;
className?: string;
iconType?: IconType;
@@ -316,7 +316,9 @@ const BaseActions = ({ children, disabled, variant, className }: ActionsProps) =
return (
<div className={cx(css, className)}>
{React.Children.map(children, (child) => {
return React.isValidElement(child) ? cloneElement(child, { disabled: isDisabled, ...child.props }) : null;
return React.isValidElement<Record<string, unknown>>(child)
? cloneElement(child, child.type !== React.Fragment ? { disabled: isDisabled, ...child.props } : undefined)
: null;
})}
</div>
);
@@ -530,8 +530,8 @@ describe('Combobox', () => {
const input = screen.getByRole('combobox');
await user.click(input);
await user.type(input, 'fir');
await act(async () => {
await user.type(input, 'fir');
jest.advanceTimersByTime(500); // Custom value while typing
});
@@ -604,8 +604,8 @@ describe('Combobox', () => {
const input = screen.getByRole('combobox');
await user.click(input);
await user.type(input, 'Opt');
await act(async () => {
await user.type(input, 'Opt');
jest.advanceTimersByTime(500); // Custom value while typing
});
@@ -12,7 +12,7 @@ import { Button, ButtonVariant } from '../Button/Button';
export interface Props {
/** Confirm action callback */
onConfirm(): void;
children: string | ReactElement;
children: string | ReactElement<Record<string, unknown>>;
/** Custom button styles */
className?: string;
/** Button size */
@@ -24,7 +24,7 @@ import { TooltipPlacement } from '../Tooltip/types';
export interface Props {
overlay: React.ReactElement | (() => React.ReactElement);
placement?: TooltipPlacement;
children: React.ReactElement;
children: React.ReactElement<Record<string, unknown>>;
root?: HTMLElement;
/** Amount in pixels to nudge the dropdown vertically and horizontally, respectively. */
offset?: [number, number];
@@ -12,7 +12,7 @@ import { Label } from './Label';
export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
/** Form input element, i.e Input or Switch */
children: React.ReactElement;
children: React.ReactElement<Record<string, unknown>>;
/** Label for the field */
label?: React.ReactNode;
/** Description of the field */
@@ -85,7 +85,7 @@ export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
<div className={cx(styles.field, horizontal && styles.fieldHorizontal, className)} {...otherProps}>
{labelElement}
<div>
<div ref={ref}>{React.cloneElement(children, childProps)}</div>
<div ref={ref}>{React.cloneElement(children, children.type !== React.Fragment ? childProps : undefined)}</div>
{invalid && error && !horizontal && (
<div
className={cx(styles.fieldValidationWrapper, {
@@ -212,14 +212,13 @@ export class UnThemedQueryField extends PureComponent<QueryFieldProps, QueryFiel
<div className="slate-query-field" data-testid={selectors.components.QueryField.container}>
<Editor
ref={(editor) => {
this.editor = editor!;
this.editor = editor;
}}
schema={SCHEMA}
autoCorrect={false}
readOnly={this.props.disabled}
onBlur={this.handleBlur}
onClick={this.props.onClick}
// onKeyDown={this.onKeyDown}
onChange={(change: { value: Value }) => {
this.onChange(change.value, false);
}}
@@ -197,7 +197,7 @@ export const VirtualizedSelectMenu = ({
// check if a child has array children (and is therefore a react-select group)
// we need to flatten these so the correct count and elements are passed to the virtualized list
const hasArrayChildren = (child: React.ReactNode) => {
return React.isValidElement(child) && Array.isArray(child.props.children);
return React.isValidElement<Record<string, unknown>>(child) && Array.isArray(child.props.children);
};
VirtualizedSelectMenu.displayName = 'VirtualizedSelectMenu';
@@ -1,5 +1,6 @@
import { css } from '@emotion/css';
import { createElement, CSSProperties } from 'react';
import { CSSObject } from '@emotion/serialize';
import { createElement } from 'react';
import * as React from 'react';
import { GrafanaTheme2, ThemeTypographyVariantTypes } from '@grafana/data';
@@ -25,7 +26,7 @@ export interface TextProps extends Omit<React.HTMLAttributes<HTMLElement>, 'clas
/** If true, numbers will have fixed width, useful for displaying tabular data. False by default */
tabular?: boolean;
/** Whether to align the text to left, center or right */
textAlignment?: CSSProperties['textAlign'];
textAlignment?: CSSObject['textAlign'];
children: NonNullable<React.ReactNode>;
}
@@ -8,7 +8,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '../../themes/ThemeContext';
type Props = {
children: React.ReactElement;
children: React.ReactElement<Record<string, unknown>>;
visible: boolean;
duration?: number;
};
@@ -8,7 +8,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '../../themes/ThemeContext';
type Props = {
children: React.ReactElement;
children: React.ReactElement<Record<string, unknown>>;
visible: boolean;
size: number;
@@ -19,7 +19,7 @@ import {
import { VizLegendOptions } from '@grafana/schema';
import { PanelContext, PanelContextRoot } from '../../components/PanelChrome/PanelContext';
import { VizLayout } from '../../components/VizLayout/VizLayout';
import { VizLayout, VizLayoutLegendProps } from '../../components/VizLayout/VizLayout';
import { UPlotChart } from '../../components/uPlot/Plot';
import { AxisProps } from '../../components/uPlot/config/UPlotAxisBuilder';
import { Renderers, UPlotConfigBuilder } from '../../components/uPlot/config/UPlotConfigBuilder';
@@ -54,7 +54,7 @@ export interface GraphNGProps extends Themeable2 {
prepConfig: (alignedFrame: DataFrame, allFrames: DataFrame[], getTimeRange: () => TimeRange) => UPlotConfigBuilder;
propsToDiff?: Array<string | PropDiffFn>;
preparePlotFrame?: (frames: DataFrame[], dimFields: XYFieldMatchers) => DataFrame | null;
renderLegend: (config: UPlotConfigBuilder) => React.ReactElement | null;
renderLegend: (config: UPlotConfigBuilder) => React.ReactElement<VizLayoutLegendProps> | null;
/**
* needed for propsToDiff to re-init the plot & config
+1 -1
View File
@@ -2,7 +2,7 @@ import { ReactElement } from 'react';
import * as React from 'react';
/** Returns the ID value of the first, and only, child element */
export function getChildId(children: ReactElement): string | undefined {
export function getChildId(children: ReactElement<Record<string, unknown>>): string | undefined {
let inputId: unknown;
// Get the first, and only, child to retrieve form input's id