Chore/React18: Update component prop types (#56898)

This commit is contained in:
kay delaney 2022-10-14 10:24:32 +01:00 committed by GitHub
parent 4eea326ee8
commit e85917f041
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
85 changed files with 195 additions and 182 deletions

View File

@ -2651,9 +2651,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "3"], [0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"] [0, 0, 0, "Unexpected any. Specify a different type.", "4"]
], ],
"public/app/core/navigation/RouterDebugger.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/core/navigation/__mocks__/routeProps.ts:5381": [ "public/app/core/navigation/__mocks__/routeProps.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"], [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"], [0, 0, 0, "Unexpected any. Specify a different type.", "1"],

View File

@ -1,5 +1,5 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React, { FC } from 'react'; import React from 'react';
import { stylesFactory } from '../../themes'; import { stylesFactory } from '../../themes';
@ -7,7 +7,7 @@ export interface Props {
className?: string; className?: string;
} }
export const FullWidthButtonContainer: FC<Props> = ({ className, children }) => { export const FullWidthButtonContainer = ({ className, children }: React.PropsWithChildren<Props>) => {
const styles = getStyles(); const styles = getStyles();
return <div className={cx(styles, className)}>{children}</div>; return <div className={cx(styles, className)}>{children}</div>;

View File

@ -21,7 +21,7 @@ interface State {
hasEventListener: boolean; hasEventListener: boolean;
} }
export class ClickOutsideWrapper extends PureComponent<Props, State> { export class ClickOutsideWrapper extends PureComponent<React.PropsWithChildren<Props>, State> {
static defaultProps = { static defaultProps = {
includeButtonPress: true, includeButtonPress: true,
parent: typeof window !== 'undefined' ? window : null, parent: typeof window !== 'undefined' ? window : null,

View File

@ -123,7 +123,7 @@ export const ControlledCollapse: FunctionComponent<Props> = ({ isOpen, onToggle,
); );
}; };
export const Collapse: FunctionComponent<Props> = ({ export const Collapse = ({
isOpen, isOpen,
label, label,
loading, loading,
@ -131,7 +131,7 @@ export const Collapse: FunctionComponent<Props> = ({
onToggle, onToggle,
className, className,
children, children,
}) => { }: React.PropsWithChildren<Props>) => {
const style = useStyles2(getStyles); const style = useStyles2(getStyles);
const onClickToggle = () => { const onClickToggle = () => {
if (onToggle) { if (onToggle) {

View File

@ -27,7 +27,7 @@ type ColorPickerTriggerRenderer = (props: {
}) => React.ReactNode; }) => React.ReactNode;
export const colorPickerFactory = <T extends ColorPickerProps>( export const colorPickerFactory = <T extends ColorPickerProps>(
popover: React.ComponentType<T>, popover: React.ComponentType<React.PropsWithChildren<T>>,
displayName = 'ColorPicker' displayName = 'ColorPicker'
) => { ) => {
return class ColorPicker extends Component<T & { children?: ColorPickerTriggerRenderer }, any> { return class ColorPicker extends Component<T & { children?: ColorPickerTriggerRenderer }, any> {

View File

@ -36,7 +36,7 @@ interface State {
showConfirm: boolean; showConfirm: boolean;
} }
class UnThemedConfirmButton extends PureComponent<Props, State> { class UnThemedConfirmButton extends PureComponent<React.PropsWithChildren<Props>, State> {
mainButtonRef = React.createRef<HTMLButtonElement>(); mainButtonRef = React.createRef<HTMLButtonElement>();
confirmButtonRef = React.createRef<HTMLButtonElement>(); confirmButtonRef = React.createRef<HTMLButtonElement>();
state: State = { state: State = {

View File

@ -1,4 +1,4 @@
import React, { FC } from 'react'; import React from 'react';
import { ComponentSize } from '../../types/size'; import { ComponentSize } from '../../types/size';
import { Button } from '../Button'; import { Button } from '../Button';
@ -17,7 +17,7 @@ export interface Props {
closeOnConfirm?: boolean; closeOnConfirm?: boolean;
} }
export const DeleteButton: FC<Props> = ({ size, disabled, onConfirm, 'aria-label': ariaLabel, closeOnConfirm }) => { export const DeleteButton = ({ size, disabled, onConfirm, 'aria-label': ariaLabel, closeOnConfirm }: Props) => {
return ( return (
<ConfirmButton <ConfirmButton
confirmText="Delete" confirmText="Delete"

View File

@ -1,5 +1,5 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React, { FC, RefCallback, useCallback, useEffect, useRef } from 'react'; import React, { RefCallback, useCallback, useEffect, useRef } from 'react';
import Scrollbars, { positionValues } from 'react-custom-scrollbars-2'; import Scrollbars, { positionValues } from 'react-custom-scrollbars-2';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
@ -31,7 +31,7 @@ interface Props {
/** /**
* Wraps component into <Scrollbars> component from `react-custom-scrollbars` * Wraps component into <Scrollbars> component from `react-custom-scrollbars`
*/ */
export const CustomScrollbar: FC<Props> = ({ export const CustomScrollbar = ({
autoHide = false, autoHide = false,
autoHideTimeout = 200, autoHideTimeout = 200,
setScrollTop, setScrollTop,
@ -48,7 +48,7 @@ export const CustomScrollbar: FC<Props> = ({
scrollTop, scrollTop,
onScroll, onScroll,
children, children,
}) => { }: React.PropsWithChildren<Props>) => {
const ref = useRef<Scrollbars & { view: HTMLDivElement }>(null); const ref = useRef<Scrollbars & { view: HTMLDivElement }>(null);
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);

View File

@ -1,13 +1,13 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import classNames from 'classnames'; import classNames from 'classnames';
import React, { FC, useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '../../themes'; import { useStyles2 } from '../../themes';
import { Icon } from '../Icon/Icon'; import { Icon } from '../Icon/Icon';
export const ScrollIndicators: FC = ({ children }) => { export const ScrollIndicators = ({ children }: React.PropsWithChildren<{}>) => {
const [showScrollTopIndicator, setShowTopScrollIndicator] = useState(false); const [showScrollTopIndicator, setShowTopScrollIndicator] = useState(false);
const [showScrollBottomIndicator, setShowBottomScrollIndicator] = useState(false); const [showScrollBottomIndicator, setShowBottomScrollIndicator] = useState(false);
const scrollTopMarker = useRef<HTMLDivElement>(null); const scrollTopMarker = useRef<HTMLDivElement>(null);

View File

@ -20,7 +20,7 @@ export interface DataLinksContextMenuApi {
targetClassName?: string; targetClassName?: string;
} }
export const DataLinksContextMenu: React.FC<DataLinksContextMenuProps> = ({ children, links, style }) => { export const DataLinksContextMenu = ({ children, links, style }: DataLinksContextMenuProps) => {
const itemsGroup: MenuItemsGroup[] = [{ items: linkModelToContextMenuItems(links), label: 'Data links' }]; const itemsGroup: MenuItemsGroup[] = [{ items: linkModelToContextMenuItems(links), label: 'Data links' }];
const linksCounter = itemsGroup[0].items.length; const linksCounter = itemsGroup[0].items.length;
const renderMenuGroupItems = () => { const renderMenuGroupItems = () => {

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { PropsWithChildren, useMemo } from 'react'; import React, { useMemo } from 'react';
import { GrafanaTheme2, TimeZoneInfo } from '@grafana/data'; import { GrafanaTheme2, TimeZoneInfo } from '@grafana/data';
@ -9,7 +9,7 @@ interface Props {
info?: TimeZoneInfo; info?: TimeZoneInfo;
} }
export const TimeZoneDescription: React.FC<PropsWithChildren<Props>> = ({ info }) => { export const TimeZoneDescription = ({ info }: Props) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const description = useDescription(info); const description = useDescription(info);

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { PropsWithChildren } from 'react'; import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
@ -7,11 +7,12 @@ import { useStyles2 } from '../../../themes';
interface Props { interface Props {
label: string | undefined; label: string | undefined;
children?: React.ReactNode;
} }
const stopPropagation = (event: React.MouseEvent) => event.stopPropagation(); const stopPropagation = (event: React.MouseEvent) => event.stopPropagation();
export const TimeZoneGroup: React.FC<PropsWithChildren<Props>> = (props) => { export const TimeZoneGroup = (props: Props) => {
const { children, label } = props; const { children, label } = props;
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);

View File

@ -1,6 +1,6 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import { isString } from 'lodash'; import { isString } from 'lodash';
import React, { PropsWithChildren } from 'react'; import React from 'react';
import { GrafanaTheme2, TimeZone, dateTimeFormat } from '@grafana/data'; import { GrafanaTheme2, TimeZone, dateTimeFormat } from '@grafana/data';
@ -12,7 +12,7 @@ interface Props {
className?: string; className?: string;
} }
export const TimeZoneOffset: React.FC<PropsWithChildren<Props>> = (props) => { export const TimeZoneOffset = (props: Props) => {
const { timestamp, timeZone, className } = props; const { timestamp, timeZone, className } = props;
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);

View File

@ -65,7 +65,7 @@ export const WideTimeZoneOption: React.FC<PropsWithChildren<Props>> = (props, re
); );
}; };
export const CompactTimeZoneOption: React.FC<PropsWithChildren<Props>> = (props, ref) => { export const CompactTimeZoneOption: React.FC<React.PropsWithChildren<Props>> = (props, ref) => {
const { children, innerProps, data, isSelected, isFocused } = props; const { children, innerProps, data, isSelected, isFocused } = props;
const theme = useTheme2(); const theme = useTheme2();
const styles = getStyles(theme); const styles = getStyles(theme);

View File

@ -1,5 +1,5 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React, { FC, FormEvent, useCallback, useState } from 'react'; import React, { FormEvent, useCallback, useState } from 'react';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
@ -25,13 +25,13 @@ export interface Props {
showFileName?: boolean; showFileName?: boolean;
} }
export const FileUpload: FC<Props> = ({ export const FileUpload = ({
onFileUpload, onFileUpload,
className, className,
children = 'Upload file', children = 'Upload file',
accept = '*', accept = '*',
size = 'md', size = 'md',
}) => { }: React.PropsWithChildren<Props>) => {
const style = useStyles2(getStyles(size)); const style = useStyles2(getStyles(size));
const [fileName, setFileName] = useState(''); const [fileName, setFileName] = useState('');
const id = uuidv4(); const id = uuidv4();

View File

@ -72,7 +72,11 @@ export const getFieldValidationMessageStyles = stylesFactory((theme: GrafanaThem
}; };
}); });
export const FieldValidationMessage: React.FC<FieldValidationMessageProps> = ({ children, horizontal, className }) => { export const FieldValidationMessage = ({
children,
horizontal,
className,
}: React.PropsWithChildren<FieldValidationMessageProps>) => {
const theme = useTheme2(); const theme = useTheme2();
const styles = getFieldValidationMessageStyles(theme); const styles = getFieldValidationMessageStyles(theme);
const cssName = cx(horizontal ? styles.horizontal : styles.vertical, className); const cssName = cx(horizontal ? styles.horizontal : styles.vertical, className);

View File

@ -4,7 +4,7 @@ import { useForm, Mode, DeepPartial, UnpackNestedValue, SubmitHandler, FieldValu
import { FormAPI } from '../../types'; import { FormAPI } from '../../types';
interface FormProps<T extends FieldValues> extends Omit<HTMLProps<HTMLFormElement>, 'onSubmit'> { interface FormProps<T extends FieldValues> extends Omit<HTMLProps<HTMLFormElement>, 'onSubmit' | 'children'> {
validateOn?: Mode; validateOn?: Mode;
validateOnMount?: boolean; validateOnMount?: boolean;
validateFieldsOnMount?: string | string[]; validateFieldsOnMount?: string | string[];

View File

@ -1,5 +1,5 @@
import { cx, css } from '@emotion/css'; import { cx, css } from '@emotion/css';
import React, { FC } from 'react'; import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
@ -11,7 +11,7 @@ export interface Props {
} }
/** @beta */ /** @beta */
export const InlineSegmentGroup: FC<Props> = ({ children, className, grow, ...htmlProps }) => { export const InlineSegmentGroup = ({ children, className, grow, ...htmlProps }: React.PropsWithChildren<Props>) => {
const styles = useStyles2((theme) => getStyles(theme, grow)); const styles = useStyles2((theme) => getStyles(theme, grow));
return ( return (

View File

@ -115,7 +115,7 @@ DisabledList.args = {
}; };
export const Dots: Story = () => { export const Dots: Story = () => {
const Wrapper: React.FC<{ title: string }> = ({ title, children }) => ( const Wrapper: React.FC<React.PropsWithChildren<{ title: string }>> = ({ title, children }) => (
<div style={{ marginBottom: 20 }}> <div style={{ marginBottom: 20 }}>
<h5>{title}</h5> <h5>{title}</h5>
{children} {children}

View File

@ -1,18 +1,20 @@
import React from 'react'; import React from 'react';
import { TooltipDisplayMode } from '@grafana/schema';
import { VizTooltipContentProps } from '../../VizTooltip'; import { VizTooltipContentProps } from '../../VizTooltip';
import { MultiModeGraphTooltip } from './MultiModeGraphTooltip'; import { MultiModeGraphTooltip } from './MultiModeGraphTooltip';
import { SingleModeGraphTooltip } from './SingleModeGraphTooltip'; import { SingleModeGraphTooltip } from './SingleModeGraphTooltip';
import { GraphDimensions } from './types'; import { GraphDimensions } from './types';
export const GraphTooltip: React.FC<VizTooltipContentProps<GraphDimensions>> = ({ export const GraphTooltip = ({
mode = 'single', mode = TooltipDisplayMode.Single,
dimensions, dimensions,
activeDimensions, activeDimensions,
pos, pos,
timeZone, timeZone,
}) => { }: VizTooltipContentProps<GraphDimensions>) => {
// When // When
// [1] no active dimension or // [1] no active dimension or
// [2] no xAxis position // [2] no xAxis position

View File

@ -30,7 +30,7 @@ export interface ContainerProps {
shrink?: number; shrink?: number;
} }
export const Layout: React.FC<LayoutProps> = ({ export const Layout = ({
children, children,
orientation = Orientation.Horizontal, orientation = Orientation.Horizontal,
spacing = 'sm', spacing = 'sm',
@ -40,7 +40,7 @@ export const Layout: React.FC<LayoutProps> = ({
width = '100%', width = '100%',
height = '100%', height = '100%',
...rest ...rest
}) => { }: LayoutProps) => {
const styles = useStyles2( const styles = useStyles2(
useCallback( useCallback(
(theme) => getStyles(theme, orientation, spacing, justify, align, wrap), (theme) => getStyles(theme, orientation, spacing, justify, align, wrap),
@ -63,7 +63,7 @@ export const Layout: React.FC<LayoutProps> = ({
); );
}; };
export const HorizontalGroup: React.FC<Omit<LayoutProps, 'orientation'>> = ({ export const HorizontalGroup = ({
children, children,
spacing, spacing,
justify, justify,
@ -71,7 +71,7 @@ export const HorizontalGroup: React.FC<Omit<LayoutProps, 'orientation'>> = ({
wrap, wrap,
width, width,
height, height,
}) => ( }: Omit<LayoutProps, 'orientation'>) => (
<Layout <Layout
spacing={spacing} spacing={spacing}
justify={justify} justify={justify}
@ -84,14 +84,14 @@ export const HorizontalGroup: React.FC<Omit<LayoutProps, 'orientation'>> = ({
{children} {children}
</Layout> </Layout>
); );
export const VerticalGroup: React.FC<Omit<LayoutProps, 'orientation' | 'wrap'>> = ({ export const VerticalGroup = ({
children, children,
spacing, spacing,
justify, justify,
align, align,
width, width,
height, height,
}) => ( }: Omit<LayoutProps, 'orientation' | 'wrap'>) => (
<Layout <Layout
spacing={spacing} spacing={spacing}
justify={justify} justify={justify}
@ -104,7 +104,7 @@ export const VerticalGroup: React.FC<Omit<LayoutProps, 'orientation' | 'wrap'>>
</Layout> </Layout>
); );
export const Container: React.FC<ContainerProps> = ({ children, padding, margin, grow, shrink }) => { export const Container = ({ children, padding, margin, grow, shrink }: React.PropsWithChildren<ContainerProps>) => {
const styles = useStyles2(useCallback((theme) => getContainerStyles(theme, padding, margin), [padding, margin])); const styles = useStyles2(useCallback((theme) => getContainerStyles(theme, padding, margin), [padding, margin]));
return ( return (

View File

@ -1,5 +1,5 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React, { HTMLAttributes, SFC } from 'react'; import React, { HTMLAttributes } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
@ -16,7 +16,7 @@ export interface LoadingPlaceholderProps extends HTMLAttributes<HTMLDivElement>
/** /**
* @public * @public
*/ */
export const LoadingPlaceholder: SFC<LoadingPlaceholderProps> = ({ text, className, ...rest }) => { export const LoadingPlaceholder = ({ text, className, ...rest }: LoadingPlaceholderProps) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
return ( return (
<div className={cx(styles.container, className)} {...rest}> <div className={cx(styles.container, className)} {...rest}>

View File

@ -15,7 +15,7 @@ interface Props {
} }
/** @internal */ /** @internal */
export const ModalHeader: React.FC<Props> = ({ icon, iconTooltip, title, children, id }) => { export const ModalHeader = ({ icon, iconTooltip, title, children, id }: React.PropsWithChildren<Props>) => {
const styles = useStyles2(getModalStyles); const styles = useStyles2(getModalStyles);
return ( return (

View File

@ -10,7 +10,7 @@ interface Props {
} }
/** @internal */ /** @internal */
export const ModalTabContent: React.FC<Props> = ({ children }) => { export const ModalTabContent = ({ children }: React.PropsWithChildren<Props>) => {
return ( return (
<div className="share-modal-body"> <div className="share-modal-body">
<div className="share-modal-header"> <div className="share-modal-header">

View File

@ -4,6 +4,6 @@ import { Stack } from './Stack';
interface EditorFieldGroupProps {} interface EditorFieldGroupProps {}
export const EditorFieldGroup: React.FC<EditorFieldGroupProps> = ({ children }) => { export const EditorFieldGroup = ({ children }: React.PropsWithChildren<EditorFieldGroupProps>) => {
return <Stack gap={1}>{children}</Stack>; return <Stack gap={1}>{children}</Stack>;
}; };

View File

@ -7,7 +7,7 @@ import { stylesFactory, useTheme2 } from '../../themes';
interface EditorHeaderProps {} interface EditorHeaderProps {}
export const EditorHeader: React.FC<EditorHeaderProps> = ({ children }) => { export const EditorHeader = ({ children }: React.PropsWithChildren<EditorHeaderProps>) => {
const theme = useTheme2(); const theme = useTheme2();
const styles = getStyles(theme); const styles = getStyles(theme);

View File

@ -9,7 +9,7 @@ import { Stack } from './Stack';
interface EditorRowProps {} interface EditorRowProps {}
export const EditorRow: React.FC<EditorRowProps> = ({ children }) => { export const EditorRow = ({ children }: React.PropsWithChildren<EditorRowProps>) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
return ( return (

View File

@ -4,7 +4,7 @@ import { Stack } from './Stack';
interface EditorRowsProps {} interface EditorRowsProps {}
export const EditorRows: React.FC<EditorRowsProps> = ({ children }) => { export const EditorRows = ({ children }: React.PropsWithChildren<EditorRowsProps>) => {
return ( return (
<Stack gap={0.5} direction="column"> <Stack gap={0.5} direction="column">
{children} {children}

View File

@ -13,7 +13,7 @@ interface StackProps {
flexGrow?: CSSProperties['flexGrow']; flexGrow?: CSSProperties['flexGrow'];
} }
export const Stack: React.FC<StackProps> = ({ children, ...props }) => { export const Stack = ({ children, ...props }: React.PropsWithChildren<StackProps>) => {
const styles = useStyles2(useCallback((theme) => getStyles(theme, props), [props])); const styles = useStyles2(useCallback((theme) => getStyles(theme, props), [props]));
return <div className={styles.root}>{children}</div>; return <div className={styles.root}>{children}</div>;

View File

@ -9,7 +9,7 @@ interface MultiValueContainerProps {
innerProps: JSX.IntrinsicElements['div']; innerProps: JSX.IntrinsicElements['div'];
} }
export const MultiValueContainer: React.FC<MultiValueContainerProps> = ({ innerProps, children }) => { export const MultiValueContainer = ({ innerProps, children }: React.PropsWithChildren<MultiValueContainerProps>) => {
const theme = useTheme2(); const theme = useTheme2();
const styles = getSelectStyles(theme); const styles = getSelectStyles(theme);
@ -24,7 +24,7 @@ export type MultiValueRemoveProps = {
innerProps: IconButtonProps; innerProps: IconButtonProps;
}; };
export const MultiValueRemove: React.FC<MultiValueRemoveProps> = ({ children, innerProps }) => { export const MultiValueRemove = ({ children, innerProps }: React.PropsWithChildren<MultiValueRemoveProps>) => {
const theme = useTheme2(); const theme = useTheme2();
const styles = getSelectStyles(theme); const styles = getSelectStyles(theme);
return <IconButton {...innerProps} name="times" size="sm" className={styles.multiValueRemove} />; return <IconButton {...innerProps} name="times" size="sm" className={styles.multiValueRemove} />;

View File

@ -1,6 +1,6 @@
import { cx } from '@emotion/css'; import { cx } from '@emotion/css';
import { max } from 'lodash'; import { max } from 'lodash';
import React, { FC, RefCallback } from 'react'; import React, { RefCallback } from 'react';
import { MenuListProps } from 'react-select'; import { MenuListProps } from 'react-select';
import { FixedSizeList as List } from 'react-window'; import { FixedSizeList as List } from 'react-window';
@ -18,7 +18,7 @@ interface SelectMenuProps {
innerProps: {}; innerProps: {};
} }
export const SelectMenu: FC<SelectMenuProps> = ({ children, maxHeight, innerRef, innerProps }) => { export const SelectMenu = ({ children, maxHeight, innerRef, innerProps }: React.PropsWithChildren<SelectMenuProps>) => {
const theme = useTheme2(); const theme = useTheme2();
const styles = getSelectStyles(theme); const styles = getSelectStyles(theme);
@ -44,12 +44,7 @@ const VIRTUAL_LIST_WIDTH_ESTIMATE_MULTIPLIER = 7;
// //
// VIRTUAL_LIST_ITEM_HEIGHT and WIDTH_ESTIMATE_MULTIPLIER are both magic numbers. // VIRTUAL_LIST_ITEM_HEIGHT and WIDTH_ESTIMATE_MULTIPLIER are both magic numbers.
// Some characters (such as emojis and other unicode characters) may consist of multiple code points in which case the width would be inaccurate (but larger than needed). // Some characters (such as emojis and other unicode characters) may consist of multiple code points in which case the width would be inaccurate (but larger than needed).
export const VirtualizedSelectMenu: FC<MenuListProps<SelectableValue>> = ({ export const VirtualizedSelectMenu = ({ children, maxHeight, options, getValue }: MenuListProps<SelectableValue>) => {
children,
maxHeight,
options,
getValue,
}) => {
const theme = useTheme2(); const theme = useTheme2();
const styles = getSelectStyles(theme); const styles = getSelectStyles(theme);
const [value] = getValue(); const [value] = getValue();
@ -91,7 +86,7 @@ interface SelectMenuOptionProps<T> {
data: SelectableValue<T>; data: SelectableValue<T>;
} }
export const SelectMenuOptions: FC<SelectMenuOptionProps<any>> = ({ export const SelectMenuOptions = ({
children, children,
data, data,
innerProps, innerProps,
@ -99,7 +94,7 @@ export const SelectMenuOptions: FC<SelectMenuOptionProps<any>> = ({
isFocused, isFocused,
isSelected, isSelected,
renderOptionLabel, renderOptionLabel,
}) => { }: React.PropsWithChildren<SelectMenuOptionProps<any>>) => {
const theme = useTheme2(); const theme = useTheme2();
const styles = getSelectStyles(theme); const styles = getSelectStyles(theme);
const icon = data.icon ? toIconName(data.icon) : undefined; const icon = data.icon ? toIconName(data.icon) : undefined;

View File

@ -209,10 +209,10 @@ interface PortalProps {
style: string; style: string;
} }
class Portal extends PureComponent<PortalProps, {}> { class Portal extends PureComponent<React.PropsWithChildren<PortalProps>, {}> {
node: HTMLElement; node: HTMLElement;
constructor(props: PortalProps) { constructor(props: React.PropsWithChildren<PortalProps>) {
super(props); super(props);
const { index = 0, origin = 'query', style } = props; const { index = 0, origin = 'query', style } = props;
this.node = document.createElement('div'); this.node = document.createElement('div');

View File

@ -34,7 +34,7 @@ export interface VizTooltipProps {
content?: React.ReactElement; content?: React.ReactElement;
/** Optional component to be used as a tooltip content */ /** Optional component to be used as a tooltip content */
tooltipComponent?: React.ComponentType<VizTooltipContentProps>; tooltipComponent?: React.ComponentType<React.PropsWithChildren<VizTooltipContentProps>>;
/** x/y position relative to the window */ /** x/y position relative to the window */
position?: { x: number; y: number }; position?: { x: number; y: number };
@ -51,7 +51,7 @@ export interface VizTooltipProps {
/** /**
* @public * @public
*/ */
export const VizTooltip: React.FC<VizTooltipProps> = ({ content, position, offset }) => { export const VizTooltip = ({ content, position, offset }: VizTooltipProps) => {
const styles = useStyles(getStyles); const styles = useStyles(getStyles);
if (position) { if (position) {
return ( return (

View File

@ -9,7 +9,7 @@ interface MarkerProps {
// An abstraction over a component rendered within a chart canvas. // An abstraction over a component rendered within a chart canvas.
// Marker is rendered with DOM coords of the chart bounding box. // Marker is rendered with DOM coords of the chart bounding box.
export const Marker: React.FC<MarkerProps> = ({ x, y, children }) => { export const Marker = ({ x, y, children }: React.PropsWithChildren<MarkerProps>) => {
return ( return (
<div <div
style={{ style={{

View File

@ -10,7 +10,7 @@ interface XYCanvasProps {
* Renders absolutely positioned element on top of the uPlot's plotting area (axes are not included!). * Renders absolutely positioned element on top of the uPlot's plotting area (axes are not included!).
* Useful when you want to render some overlay with canvas-independent elements on top of the plot. * Useful when you want to render some overlay with canvas-independent elements on top of the plot.
*/ */
export const XYCanvas: React.FC<XYCanvasProps> = ({ children, left, top }) => { export const XYCanvas = ({ children, left, top }: React.PropsWithChildren<XYCanvasProps>) => {
const className = useMemo(() => { const className = useMemo(() => {
return css` return css`
position: absolute; position: absolute;

View File

@ -4,12 +4,13 @@ import React from 'react';
import { RenderFunction } from '../../types'; import { RenderFunction } from '../../types';
const StoryContainer: React.FC<{ width?: number; height?: number; showBoundaries: boolean }> = ({ interface Props {
children, width?: number;
width, height?: number;
height, showBoundaries: boolean;
showBoundaries, }
}) => {
const StoryContainer = ({ width, height, showBoundaries, children }: React.PropsWithChildren<Props>) => {
const checkColor = '#f0f0f0'; const checkColor = '#f0f0f0';
const finalWidth = width ? `${width}px` : '100%'; const finalWidth = width ? `${width}px` : '100%';
const finalHeight = height !== 0 ? `${height}px` : 'auto'; const finalHeight = height !== 0 ? `${height}px` : 'auto';

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { FC, useState } from 'react'; import React, { useState } from 'react';
import { GrafanaTheme } from '@grafana/data'; import { GrafanaTheme } from '@grafana/data';
import { getBackendSrv } from '@grafana/runtime'; import { getBackendSrv } from '@grafana/runtime';
@ -18,7 +18,7 @@ const paragraphStyles = (theme: GrafanaTheme) => css`
display: block; display: block;
`; `;
export const ForgottenPassword: FC = () => { export const ForgottenPassword = () => {
const [emailSent, setEmailSent] = useState(false); const [emailSent, setEmailSent] = useState(false);
const styles = useStyles(paragraphStyles); const styles = useStyles(paragraphStyles);
const loginHref = `${config.appSubUrl}/login`; const loginHref = `${config.appSubUrl}/login`;

View File

@ -1,10 +1,10 @@
import React, { FC } from 'react'; import React from 'react';
import { LoginLayout, InnerBox } from '../Login/LoginLayout'; import { LoginLayout, InnerBox } from '../Login/LoginLayout';
import { ForgottenPassword } from './ForgottenPassword'; import { ForgottenPassword } from './ForgottenPassword';
export const SendResetMailPage: FC = () => ( export const SendResetMailPage = () => (
<LoginLayout> <LoginLayout>
<InnerBox> <InnerBox>
<ForgottenPassword /> <ForgottenPassword />

View File

@ -1,5 +1,5 @@
import { cx, css, keyframes } from '@emotion/css'; import { cx, css, keyframes } from '@emotion/css';
import React, { FC, useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2, styleMixins } from '@grafana/ui'; import { useStyles2, styleMixins } from '@grafana/ui';
@ -11,7 +11,7 @@ import { Footer } from '../Footer/Footer';
interface InnerBoxProps { interface InnerBoxProps {
enterAnimation?: boolean; enterAnimation?: boolean;
} }
export const InnerBox: FC<InnerBoxProps> = ({ children, enterAnimation = true }) => { export const InnerBox = ({ children, enterAnimation = true }: React.PropsWithChildren<InnerBoxProps>) => {
const loginStyles = useStyles2(getLoginStyles); const loginStyles = useStyles2(getLoginStyles);
return <div className={cx(loginStyles.loginInnerBox, enterAnimation && loginStyles.enterAnimation)}>{children}</div>; return <div className={cx(loginStyles.loginInnerBox, enterAnimation && loginStyles.enterAnimation)}>{children}</div>;
}; };
@ -21,7 +21,7 @@ export interface LoginLayoutProps {
branding?: BrandingSettings; branding?: BrandingSettings;
} }
export const LoginLayout: FC<LoginLayoutProps> = ({ children, branding }) => { export const LoginLayout = ({ children, branding }: React.PropsWithChildren<LoginLayoutProps>) => {
const loginStyles = useStyles2(getLoginStyles); const loginStyles = useStyles2(getLoginStyles);
const [startAnim, setStartAnim] = useState(false); const [startAnim, setStartAnim] = useState(false);
const subTitle = branding?.loginSubtitle ?? Branding.GetLoginSubTitle(); const subTitle = branding?.loginSubtitle ?? Branding.GetLoginSubTitle();

View File

@ -1,6 +1,6 @@
// Libraries // Libraries
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { FC } from 'react'; import React from 'react';
// Components // Components
import { HorizontalGroup, LinkButton } from '@grafana/ui'; import { HorizontalGroup, LinkButton } from '@grafana/ui';
@ -20,7 +20,7 @@ const forgottenPasswordStyles = css`
margin-top: 4px; margin-top: 4px;
`; `;
export const LoginPage: FC = () => { export const LoginPage = () => {
document.title = Branding.AppTitle; document.title = Branding.AppTitle;
return ( return (
<LoginLayout> <LoginLayout>

View File

@ -1,4 +1,4 @@
import React, { FC, useState } from 'react'; import React, { useState } from 'react';
import { getBackendSrv } from '@grafana/runtime'; import { getBackendSrv } from '@grafana/runtime';
import { Form, Field, Input, Button, Legend, Container, HorizontalGroup, LinkButton } from '@grafana/ui'; import { Form, Field, Input, Button, Legend, Container, HorizontalGroup, LinkButton } from '@grafana/ui';
@ -9,7 +9,7 @@ interface EmailDTO {
email: string; email: string;
} }
export const VerifyEmail: FC = () => { export const VerifyEmail = () => {
const notifyApp = useAppNotification(); const notifyApp = useAppNotification();
const [emailSent, setEmailSent] = useState(false); const [emailSent, setEmailSent] = useState(false);

View File

@ -1,10 +1,10 @@
import React, { FC } from 'react'; import React from 'react';
import { LoginLayout, InnerBox } from '../Login/LoginLayout'; import { LoginLayout, InnerBox } from '../Login/LoginLayout';
import { VerifyEmail } from './VerifyEmail'; import { VerifyEmail } from './VerifyEmail';
export const VerifyEmailPage: FC = () => { export const VerifyEmailPage = () => {
return ( return (
<LoginLayout> <LoginLayout>
<InnerBox> <InnerBox>

View File

@ -1,10 +1,10 @@
import React, { FunctionComponent } from 'react'; import React from 'react';
export interface Props { export interface Props {
featureToggle: boolean; featureToggle: boolean;
} }
export const WithFeatureToggle: FunctionComponent<Props> = ({ featureToggle, children }) => { export const WithFeatureToggle = ({ featureToggle, children }: React.PropsWithChildren<Props>) => {
if (featureToggle === true) { if (featureToggle === true) {
return <>{children}</>; return <>{children}</>;
} }

View File

@ -6,7 +6,7 @@ import { PageContents } from '../components/Page/PageContents';
import { RouteDescriptor } from './types'; import { RouteDescriptor } from './types';
export const RouterDebugger: React.FC<any> = () => { export const RouterDebugger = () => {
const manualRoutes: RouteDescriptor[] = []; const manualRoutes: RouteDescriptor[] = [];
return ( return (
<PageContents> <PageContents>

View File

@ -77,7 +77,7 @@ interface CircleProps {
style?: React.CSSProperties; style?: React.CSSProperties;
} }
export const Circle: React.FC<CircleProps> = ({ size, style, children }) => { export const Circle = ({ size, style, children }: React.PropsWithChildren<CircleProps>) => {
return ( return (
<div <div
style={{ style={{

View File

@ -36,7 +36,7 @@ interface UpgradeInfoProps {
editionNotice?: string; editionNotice?: string;
} }
export const UpgradeInfo: React.FC<UpgradeInfoProps> = ({ editionNotice }) => { export const UpgradeInfo = ({ editionNotice }: UpgradeInfoProps) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
return ( return (
@ -70,7 +70,7 @@ const getStyles = (theme: GrafanaTheme2) => {
}; };
}; };
const GetEnterprise: React.FC = () => { const GetEnterprise = () => {
return ( return (
<div style={{ marginTop: '40px', marginBottom: '30px' }}> <div style={{ marginTop: '40px', marginBottom: '30px' }}>
<h2 style={titleStyles}>Get Grafana Enterprise</h2> <h2 style={titleStyles}>Get Grafana Enterprise</h2>
@ -83,7 +83,7 @@ const GetEnterprise: React.FC = () => {
); );
}; };
const CallToAction: React.FC = () => { const CallToAction = () => {
return ( return (
<LinkButton <LinkButton
variant="primary" variant="primary"
@ -95,7 +95,7 @@ const CallToAction: React.FC = () => {
); );
}; };
const ServiceInfo: React.FC = () => { const ServiceInfo = () => {
return ( return (
<div> <div>
<h4>At your service</h4> <h4>At your service</h4>
@ -127,7 +127,7 @@ const ServiceInfo: React.FC = () => {
); );
}; };
const FeatureInfo: React.FC = () => { const FeatureInfo = () => {
return ( return (
<div style={{ paddingRight: '11px' }}> <div style={{ paddingRight: '11px' }}>
<h4>Enhanced functionality</h4> <h4>Enhanced functionality</h4>
@ -136,7 +136,7 @@ const FeatureInfo: React.FC = () => {
); );
}; };
const FeatureListing: React.FC = () => { const FeatureListing = () => {
return ( return (
<List> <List>
<Item title="Data source permissions" /> <Item title="Data source permissions" />
@ -182,7 +182,7 @@ interface ListProps {
nested?: boolean; nested?: boolean;
} }
const List: React.FC<ListProps> = ({ children, nested }) => { const List = ({ children, nested }: React.PropsWithChildren<ListProps>) => {
const listStyle = css` const listStyle = css`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -201,7 +201,7 @@ interface ItemProps {
image?: string; image?: string;
} }
const Item: React.FC<ItemProps> = ({ children, title, image }) => { const Item = ({ children, title, image }: React.PropsWithChildren<ItemProps>) => {
const imageUrl = image ? image : 'public/img/licensing/checkmark.svg'; const imageUrl = image ? image : 'public/img/licensing/checkmark.svg';
const itemStyle = css` const itemStyle = css`
display: flex; display: flex;

View File

@ -23,7 +23,7 @@ const pageNav: NavModelItem = {
breadcrumbs: [{ title: 'Server admin', url: 'admin/users' }], breadcrumbs: [{ title: 'Server admin', url: 'admin/users' }],
}; };
const UserCreatePage: React.FC = () => { const UserCreatePage = () => {
const history = useHistory(); const history = useHistory();
const onSubmit = useCallback( const onSubmit = useCallback(

View File

@ -462,7 +462,7 @@ export function ChangeOrgButton({
); );
} }
const ExternalUserTooltip: React.FC = () => { const ExternalUserTooltip = () => {
const theme = useTheme(); const theme = useTheme();
const styles = getTooltipStyles(theme); const styles = getTooltipStyles(theme);

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { Alert, LoadingPlaceholder, useStyles2, withErrorBoundary } from '@grafana/ui'; import { Alert, LoadingPlaceholder, useStyles2, withErrorBoundary } from '@grafana/ui';
@ -24,7 +24,7 @@ import { amRouteToFormAmRoute, formAmRouteToAmRoute, stringsToSelectableValues }
import { isVanillaPrometheusAlertManagerDataSource } from './utils/datasource'; import { isVanillaPrometheusAlertManagerDataSource } from './utils/datasource';
import { initialAsyncRequestState } from './utils/redux'; import { initialAsyncRequestState } from './utils/redux';
const AmRoutes: FC = () => { const AmRoutes = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const [isRootRouteEditMode, setIsRootRouteEditMode] = useState(false); const [isRootRouteEditMode, setIsRootRouteEditMode] = useState(false);

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import pluralize from 'pluralize'; import pluralize from 'pluralize';
import React, { FC, useEffect } from 'react'; import React, { useEffect } from 'react';
import { Redirect, Route, RouteChildrenProps, Switch, useLocation, useParams } from 'react-router-dom'; import { Redirect, Route, RouteChildrenProps, Switch, useLocation, useParams } from 'react-router-dom';
import { NavModelItem, GrafanaTheme2 } from '@grafana/data'; import { NavModelItem, GrafanaTheme2 } from '@grafana/data';
@ -48,7 +48,7 @@ function NotificationError({ errorCount }: NotificationErrorProps) {
); );
} }
const Receivers: FC = () => { const Receivers = () => {
const alertManagers = useAlertManagersByPermission('notification'); const alertManagers = useAlertManagersByPermission('notification');
const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName(alertManagers); const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName(alertManagers);
const dispatch = useDispatch(); const dispatch = useDispatch();

View File

@ -1,4 +1,4 @@
import React, { FC } from 'react'; import React from 'react';
import { useAsync } from 'react-use'; import { useAsync } from 'react-use';
import { NavModelItem } from '@grafana/data'; import { NavModelItem } from '@grafana/data';
@ -31,7 +31,7 @@ const getPageNav = (state: 'edit' | 'add') => {
return undefined; return undefined;
}; };
const RuleEditor: FC<RuleEditorProps> = ({ match }) => { const RuleEditor = ({ match }: RuleEditorProps) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { id } = match.params; const { id } = match.params;
const identifier = ruleId.tryParse(id, true); const identifier = ruleId.tryParse(id, true);

View File

@ -1,4 +1,4 @@
import React, { FC, useCallback, useEffect } from 'react'; import React, { useCallback, useEffect } from 'react';
import { Redirect, Route, RouteChildrenProps, Switch, useLocation } from 'react-router-dom'; import { Redirect, Route, RouteChildrenProps, Switch, useLocation } from 'react-router-dom';
import { Alert, withErrorBoundary } from '@grafana/ui'; import { Alert, withErrorBoundary } from '@grafana/ui';
@ -19,7 +19,7 @@ import { fetchAmAlertsAction, fetchSilencesAction } from './state/actions';
import { SILENCES_POLL_INTERVAL_MS } from './utils/constants'; import { SILENCES_POLL_INTERVAL_MS } from './utils/constants';
import { AsyncRequestState, initialAsyncRequestState } from './utils/redux'; import { AsyncRequestState, initialAsyncRequestState } from './utils/redux';
const Silences: FC = () => { const Silences = () => {
const alertManagers = useAlertManagersByPermission('instance'); const alertManagers = useAlertManagersByPermission('instance');
const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName(alertManagers); const [alertManagerSourceName, setAlertManagerSourceName] = useAlertManagerSourceName(alertManagers);

View File

@ -1,4 +1,4 @@
import React, { FC } from 'react'; import React from 'react';
import { NavModelItem } from '@grafana/data'; import { NavModelItem } from '@grafana/data';
import { Page } from 'app/core/components/Page/Page'; import { Page } from 'app/core/components/Page/Page';
@ -9,7 +9,7 @@ interface Props {
pageNav?: NavModelItem; pageNav?: NavModelItem;
} }
export const AlertingPageWrapper: FC<Props> = ({ children, pageId, pageNav, isLoading }) => { export const AlertingPageWrapper = ({ children, pageId, pageNav, isLoading }: React.PropsWithChildren<Props>) => {
return ( return (
<Page pageNav={pageNav} navId={pageId}> <Page pageNav={pageNav} navId={pageId}>
<Page.Contents isLoading={isLoading}>{children}</Page.Contents> <Page.Contents isLoading={isLoading}>{children}</Page.Contents>

View File

@ -1,4 +1,4 @@
import React, { FC } from 'react'; import React from 'react';
import { contextSrv } from 'app/core/services/context_srv'; import { contextSrv } from 'app/core/services/context_srv';
import { AccessControlAction } from 'app/types'; import { AccessControlAction } from 'app/types';
@ -8,7 +8,7 @@ type Props = {
fallback?: boolean; fallback?: boolean;
}; };
export const Authorize: FC<Props> = ({ actions, children, fallback = true }) => { export const Authorize = ({ actions, children, fallback = true }: React.PropsWithChildren<Props>) => {
if (actions.some((action) => contextSrv.hasAccess(action, fallback))) { if (actions.some((action) => contextSrv.hasAccess(action, fallback))) {
return <>{children}</>; return <>{children}</>;
} else { } else {

View File

@ -1,5 +1,5 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React, { FC } from 'react'; import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '@grafana/ui'; import { useStyles2 } from '@grafana/ui';
@ -10,7 +10,7 @@ interface Props {
horizontal?: boolean; horizontal?: boolean;
} }
export const DetailsField: FC<Props> = ({ className, label, horizontal, children }) => { export const DetailsField = ({ className, label, horizontal, children }: React.PropsWithChildren<Props>) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
return ( return (

View File

@ -1,10 +1,10 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { FC } from 'react'; import React from 'react';
import { GrafanaTheme } from '@grafana/data'; import { GrafanaTheme } from '@grafana/data';
import { useStyles } from '@grafana/ui'; import { useStyles } from '@grafana/ui';
export const EmptyArea: FC = ({ children }) => { export const EmptyArea = ({ children }: React.PropsWithChildren<{}>) => {
const styles = useStyles(getStyles); const styles = useStyles(getStyles);
return <div className={styles.container}>{children}</div>; return <div className={styles.container}>{children}</div>;

View File

@ -1,9 +1,9 @@
import React, { FC } from 'react'; import React from 'react';
import { config } from '@grafana/runtime'; import { config } from '@grafana/runtime';
import { Alert } from '@grafana/ui'; import { Alert } from '@grafana/ui';
const EvaluationIntervalLimitExceeded: FC = () => ( const EvaluationIntervalLimitExceeded = () => (
<Alert severity="warning" title="Global evalutation interval limit exceeded"> <Alert severity="warning" title="Global evalutation interval limit exceeded">
A minimum evaluation interval of <strong>{config.unifiedAlerting.minInterval}</strong> has been configured in A minimum evaluation interval of <strong>{config.unifiedAlerting.minInterval}</strong> has been configured in
Grafana. Grafana.

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { FC } from 'react'; import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '@grafana/ui'; import { useStyles2 } from '@grafana/ui';
@ -9,7 +9,7 @@ type Props = {
status: PromAlertingRuleState | 'neutral'; status: PromAlertingRuleState | 'neutral';
}; };
export const StateColoredText: FC<Props> = ({ children, status }) => { export const StateColoredText = ({ children, status }: React.PropsWithChildren<Props>) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
return <span className={styles[status]}>{children || status}</span>; return <span className={styles[status]}>{children || status}</span>;

View File

@ -1,5 +1,5 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React, { FC } from 'react'; import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '@grafana/ui'; import { useStyles2 } from '@grafana/ui';
@ -11,7 +11,7 @@ type Props = {
size?: 'md' | 'sm'; size?: 'md' | 'sm';
}; };
export const StateTag: FC<Props> = ({ children, state, size = 'md' }) => { export const StateTag = ({ children, state, size = 'md' }: React.PropsWithChildren<Props>) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
return <span className={cx(styles.common, styles[state], styles[size])}>{children || state}</span>; return <span className={cx(styles.common, styles[state], styles[size])}>{children || state}</span>;

View File

@ -1,5 +1,5 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React, { FC } from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
@ -14,7 +14,7 @@ interface Props {
showButton?: boolean; showButton?: boolean;
} }
export const ReceiversSection: FC<Props> = ({ export const ReceiversSection = ({
className, className,
title, title,
description, description,
@ -22,7 +22,7 @@ export const ReceiversSection: FC<Props> = ({
addButtonTo, addButtonTo,
children, children,
showButton = true, showButton = true,
}) => { }: React.PropsWithChildren<Props>) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
return ( return (
<> <>

View File

@ -1,5 +1,5 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React, { FC, useState } from 'react'; import React, { useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { IconSize, useStyles2 } from '@grafana/ui'; import { IconSize, useStyles2 } from '@grafana/ui';
@ -13,7 +13,13 @@ interface Props {
size?: IconSize; size?: IconSize;
} }
export const CollapsibleSection: FC<Props> = ({ label, description, children, className, size = 'xl' }) => { export const CollapsibleSection = ({
label,
description,
children,
className,
size = 'xl',
}: React.PropsWithChildren<Props>) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const [isCollapsed, setIsCollapsed] = useState(true); const [isCollapsed, setIsCollapsed] = useState(true);

View File

@ -1,5 +1,5 @@
import { css, cx } from '@emotion/css'; import { css, cx } from '@emotion/css';
import React, { FC, useCallback } from 'react'; import React, { useCallback } from 'react';
import { useFieldArray, useFormContext } from 'react-hook-form'; import { useFieldArray, useFormContext } from 'react-hook-form';
import { GrafanaTheme } from '@grafana/data'; import { GrafanaTheme } from '@grafana/data';
@ -9,7 +9,7 @@ import { RuleFormValues } from '../../types/rule-form';
import { AnnotationKeyInput } from './AnnotationKeyInput'; import { AnnotationKeyInput } from './AnnotationKeyInput';
const AnnotationsField: FC = () => { const AnnotationsField = () => {
const styles = useStyles(getStyles); const styles = useStyles(getStyles);
const { const {
control, control,

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { FC } from 'react'; import React from 'react';
import { useFormContext } from 'react-hook-form'; import { useFormContext } from 'react-hook-form';
import { GrafanaTheme } from '@grafana/data'; import { GrafanaTheme } from '@grafana/data';
@ -11,7 +11,7 @@ import { timeOptions } from '../../utils/time';
import { PreviewRule } from './PreviewRule'; import { PreviewRule } from './PreviewRule';
import { RuleEditorSection } from './RuleEditorSection'; import { RuleEditorSection } from './RuleEditorSection';
export const CloudEvaluationBehavior: FC = () => { export const CloudEvaluationBehavior = () => {
const styles = useStyles(getStyles); const styles = useStyles(getStyles);
const { const {
register, register,

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { FC, useState } from 'react'; import React, { useState } from 'react';
import { RegisterOptions, useFormContext } from 'react-hook-form'; import { RegisterOptions, useFormContext } from 'react-hook-form';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
@ -75,7 +75,7 @@ export const evaluateEveryValidationOptions: RegisterOptions = {
}, },
}; };
export const GrafanaEvaluationBehavior: FC = () => { export const GrafanaEvaluationBehavior = () => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const [showErrorHandling, setShowErrorHandling] = useState(false); const [showErrorHandling, setShowErrorHandling] = useState(false);
const { const {

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { FC, useState } from 'react'; import React, { useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { Card, Link, useStyles2, useTheme2 } from '@grafana/ui'; import { Card, Link, useStyles2, useTheme2 } from '@grafana/ui';
@ -7,7 +7,7 @@ import { Card, Link, useStyles2, useTheme2 } from '@grafana/ui';
import LabelsField from './LabelsField'; import LabelsField from './LabelsField';
import { RuleEditorSection } from './RuleEditorSection'; import { RuleEditorSection } from './RuleEditorSection';
export const NotificationsStep: FC = () => { export const NotificationsStep = () => {
const [hideFlowChart, setHideFlowChart] = useState(false); const [hideFlowChart, setHideFlowChart] = useState(false);
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const theme = useTheme2(); const theme = useTheme2();

View File

@ -150,7 +150,7 @@ export const QueryWrapper: FC<Props> = ({
); );
}; };
export const EmptyQueryWrapper: FC<{}> = ({ children }) => { export const EmptyQueryWrapper = ({ children }: React.PropsWithChildren<{}>) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
return <div className={styles.wrapper}>{children}</div>; return <div className={styles.wrapper}>{children}</div>;
}; };

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { FC } from 'react'; import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { FieldSet, useStyles2 } from '@grafana/ui'; import { FieldSet, useStyles2 } from '@grafana/ui';
@ -10,7 +10,12 @@ export interface RuleEditorSectionProps {
description?: string; description?: string;
} }
export const RuleEditorSection: FC<RuleEditorSectionProps> = ({ title, stepNo, children, description }) => { export const RuleEditorSection = ({
title,
stepNo,
children,
description,
}: React.PropsWithChildren<RuleEditorSectionProps>) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
return ( return (

View File

@ -1,4 +1,4 @@
import React, { FC } from 'react'; import React from 'react';
import { Tooltip } from '@grafana/ui'; import { Tooltip } from '@grafana/ui';
@ -6,7 +6,7 @@ type Props = {
visible: boolean; visible: boolean;
}; };
const DisabledTooltip: FC<Props> = ({ children, visible = false }) => { const DisabledTooltip = ({ children, visible = false }: React.PropsWithChildren<Props>) => {
if (!visible) { if (!visible) {
return <>{children}</>; return <>{children}</>;
} }

View File

@ -1,4 +1,4 @@
import React, { FC } from 'react'; import React from 'react';
import { logInfo } from '@grafana/runtime'; import { logInfo } from '@grafana/runtime';
import { CallToActionCard } from '@grafana/ui'; import { CallToActionCard } from '@grafana/ui';
@ -7,7 +7,7 @@ import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
import { LogMessages } from '../../Analytics'; import { LogMessages } from '../../Analytics';
import { useRulesAccess } from '../../utils/accessControlHooks'; import { useRulesAccess } from '../../utils/accessControlHooks';
export const NoRulesSplash: FC = () => { export const NoRulesSplash = () => {
const { canCreateGrafanaRules, canCreateCloudRules } = useRulesAccess(); const { canCreateGrafanaRules, canCreateCloudRules } = useRulesAccess();
if (canCreateGrafanaRules || canCreateCloudRules) { if (canCreateGrafanaRules || canCreateCloudRules) {

View File

@ -178,7 +178,7 @@ function renderTimestampCell(item: StateHistoryRow) {
); );
} }
const LabelsWrapper: FC<{}> = ({ children }) => { const LabelsWrapper = ({ children }: React.PropsWithChildren<{}>) => {
const { wrapper } = useStyles2(getStyles); const { wrapper } = useStyles2(getStyles);
return <div className={wrapper}>{children}</div>; return <div className={wrapper}>{children}</div>;
}; };

View File

@ -10,13 +10,15 @@ const expanderContainerStyles = css`
height: 100%; height: 100%;
`; `;
export const ExpanderCell = ({ row }: CellProps<object, void>) => ( export function ExpanderCell<K extends object>({ row }: CellProps<K, void>) {
<div className={expanderContainerStyles}> return (
<IconButton <div className={expanderContainerStyles}>
// @ts-expect-error react-table doesn't ship with useExpanded types and we can't use declaration merging without affecting the table viz <IconButton
name={row.isExpanded ? 'angle-down' : 'angle-right'} // @ts-expect-error react-table doesn't ship with useExpanded types and we can't use declaration merging without affecting the table viz
// @ts-expect-error same as the line above name={row.isExpanded ? 'angle-down' : 'angle-right'}
{...row.getToggleRowExpandedProps({})} // @ts-expect-error same as the line above
/> {...row.getToggleRowExpandedProps({})}
</div> />
); </div>
);
}

View File

@ -1,4 +1,4 @@
import React, { FC, HTMLAttributes, MouseEvent, ReactElement, useCallback, useState } from 'react'; import React, { HTMLAttributes, MouseEvent, ReactElement, useCallback, useState } from 'react';
import { CartesianCoords2D } from '@grafana/data'; import { CartesianCoords2D } from '@grafana/data';
@ -7,11 +7,11 @@ interface PanelHeaderMenuTriggerApi {
closeMenu: () => void; closeMenu: () => void;
} }
interface Props extends HTMLAttributes<HTMLDivElement> { interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
children: (props: PanelHeaderMenuTriggerApi) => ReactElement; children: (props: PanelHeaderMenuTriggerApi) => ReactElement;
} }
export const PanelHeaderMenuTrigger: FC<Props> = ({ children, ...divProps }) => { export const PanelHeaderMenuTrigger = ({ children, ...divProps }: Props) => {
const [clickCoordinates, setClickCoordinates] = useState<CartesianCoords2D>({ x: 0, y: 0 }); const [clickCoordinates, setClickCoordinates] = useState<CartesianCoords2D>({ x: 0, y: 0 });
const [panelMenuOpen, setPanelMenuOpen] = useState<boolean>(false); const [panelMenuOpen, setPanelMenuOpen] = useState<boolean>(false);

View File

@ -1,5 +1,5 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import React, { FC } from 'react'; import React from 'react';
import { GrafanaTheme } from '@grafana/data'; import { GrafanaTheme } from '@grafana/data';
import { useStyles } from '@grafana/ui'; import { useStyles } from '@grafana/ui';
@ -11,7 +11,7 @@ const getStyles = (theme: GrafanaTheme) => css`
color: ${theme.colors.textWeak}; color: ${theme.colors.textWeak};
`; `;
export const DetailText: FC = ({ children }) => { export const DetailText = ({ children }: React.PropsWithChildren<{}>) => {
const collapsedTextStyles = useStyles(getStyles); const collapsedTextStyles = useStyles(getStyles);
return <p className={collapsedTextStyles}>{children}</p>; return <p className={collapsedTextStyles}>{children}</p>;
}; };

View File

@ -51,9 +51,9 @@ export const DeleteLibraryPanelModal: FC<Props> = ({ libraryPanel, onDismiss, on
); );
}; };
const LoadingIndicator: FC = () => <span>Loading library panel...</span>; const LoadingIndicator = () => <span>Loading library panel...</span>;
const Confirm: FC = () => { const Confirm = () => {
const styles = useStyles(getModalStyles); const styles = useStyles(getModalStyles);
return <div className={styles.modalText}>Do you want to delete this panel?</div>; return <div className={styles.modalText}>Do you want to delete this panel?</div>;

View File

@ -1,4 +1,4 @@
import React, { FC, useState, useCallback } from 'react'; import React, { useState, useCallback } from 'react';
import useAsync from 'react-use/lib/useAsync'; import useAsync from 'react-use/lib/useAsync';
import { getBackendSrv, locationService } from '@grafana/runtime'; import { getBackendSrv, locationService } from '@grafana/runtime';
@ -16,7 +16,7 @@ export function getSnapshots() {
})); }));
}); });
} }
export const SnapshotListTable: FC = () => { export const SnapshotListTable = () => {
const [snapshots, setSnapshots] = useState<Snapshot[]>([]); const [snapshots, setSnapshots] = useState<Snapshot[]>([]);
const [removeSnapshot, setRemoveSnapshot] = useState<Snapshot | undefined>(); const [removeSnapshot, setRemoveSnapshot] = useState<Snapshot | undefined>();
const currentPath = locationService.getLocation().pathname; const currentPath = locationService.getLocation().pathname;

View File

@ -17,7 +17,7 @@ interface Props {
description?: string; description?: string;
} }
export const PanelTypeCard: React.FC<Props> = ({ export const PanelTypeCard = ({
isCurrent, isCurrent,
title, title,
plugin, plugin,
@ -27,7 +27,7 @@ export const PanelTypeCard: React.FC<Props> = ({
showBadge, showBadge,
description, description,
children, children,
}) => { }: React.PropsWithChildren<Props>) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
const isDisabled = disabled || plugin.state === PluginState.deprecated; const isDisabled = disabled || plugin.state === PluginState.deprecated;
const cssClass = cx({ const cssClass = cx({
@ -157,7 +157,7 @@ interface PanelPluginBadgeProps {
plugin: PanelPluginMeta; plugin: PanelPluginMeta;
} }
const PanelPluginBadge: React.FC<PanelPluginBadgeProps> = ({ plugin }) => { const PanelPluginBadge = ({ plugin }: PanelPluginBadgeProps) => {
if (isUnsignedPluginSignature(plugin.signature)) { if (isUnsignedPluginSignature(plugin.signature)) {
return <PluginSignatureBadge status={plugin.signature} />; return <PluginSignatureBadge status={plugin.signature} />;
} }

View File

@ -44,7 +44,7 @@ export function PluginSignatureDetailsBadge({ signatureType, signatureOrg = '' }
); );
} }
export const DetailsBadge: React.FC = ({ children }) => { export const DetailsBadge = ({ children }: React.PropsWithChildren<{}>) => {
const styles = useStyles2(getStyles); const styles = useStyles2(getStyles);
return <Badge color="green" className={styles.badge} text={<>{children}</>} />; return <Badge color="green" className={styles.badge} text={<>{children}</>} />;

View File

@ -4,8 +4,8 @@ type Props = {
fallBackComponent?: React.ReactNode; fallBackComponent?: React.ReactNode;
}; };
export class ErrorBoundary extends React.Component<Props, { hasError: boolean }> { export class ErrorBoundary extends React.Component<React.PropsWithChildren<Props>, { hasError: boolean }> {
constructor(props: Props) { constructor(props: React.PropsWithChildren<Props>) {
super(props); super(props);
this.state = { hasError: false }; this.state = { hasError: false };
} }

View File

@ -91,7 +91,7 @@ export const UserProfileEditForm: FC<Props> = ({ user, isSavingUser, updateProfi
export default UserProfileEditForm; export default UserProfileEditForm;
const InputSuffix: FC = () => { const InputSuffix = () => {
return disableLoginForm ? ( return disableLoginForm ? (
<Tooltip content="Login details locked because they are managed in another system."> <Tooltip content="Login details locked because they are managed in another system.">
<Icon name="lock" /> <Icon name="lock" />

View File

@ -10,7 +10,7 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => ({
`, `,
})); }));
export const HelpToggle: React.FunctionComponent = ({ children }) => { export const HelpToggle = ({ children }: React.PropsWithChildren<{}>) => {
const [isHelpVisible, setIsHelpVisible] = useState(false); const [isHelpVisible, setIsHelpVisible] = useState(false);
const theme = useTheme(); const theme = useTheme();
const styles = getStyles(theme); const styles = getStyles(theme);

View File

@ -1,9 +1,9 @@
import React, { FC } from 'react'; import React from 'react';
import { VerticalGroup } from '@grafana/ui'; import { VerticalGroup } from '@grafana/ui';
import { EmotionPerfTest } from '@grafana/ui/src/components/ThemeDemos/EmotionPerfTest'; import { EmotionPerfTest } from '@grafana/ui/src/components/ThemeDemos/EmotionPerfTest';
export const BenchmarksPage: FC = () => { export const BenchmarksPage = () => {
return ( return (
<VerticalGroup> <VerticalGroup>
<EmotionPerfTest /> <EmotionPerfTest />

View File

@ -1,4 +1,4 @@
import React, { FC, useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import { useObservable } from 'react-use'; import { useObservable } from 'react-use';
import AutoSizer from 'react-virtualized-auto-sizer'; import AutoSizer from 'react-virtualized-auto-sizer';
@ -26,7 +26,7 @@ interface State {
data?: PanelData; data?: PanelData;
} }
export const TestStuffPage: FC = () => { export const TestStuffPage = () => {
const [state, setState] = useState<State>(getDefaultState()); const [state, setState] = useState<State>(getDefaultState());
const { queryOptions, queryRunner } = state; const { queryOptions, queryRunner } = state;

View File

@ -1,4 +1,4 @@
import React, { FC, memo } from 'react'; import React, { memo } from 'react';
import { config } from '@grafana/runtime'; import { config } from '@grafana/runtime';
import { useUrlParams } from 'app/core/navigation/hooks'; import { useUrlParams } from 'app/core/navigation/hooks';
@ -6,7 +6,7 @@ import { useUrlParams } from 'app/core/navigation/hooks';
import { DashboardSearch } from './DashboardSearch'; import { DashboardSearch } from './DashboardSearch';
import { DashboardSearchModal } from './DashboardSearchModal'; import { DashboardSearchModal } from './DashboardSearchModal';
export const SearchWrapper: FC = memo(() => { export const SearchWrapper = memo(() => {
const [params] = useUrlParams(); const [params] = useUrlParams();
const isOpen = params.get('search') === 'open'; const isOpen = params.get('search') === 'open';
const isTopnav = config.featureToggles.topnav; const isTopnav = config.featureToggles.topnav;

View File

@ -1,6 +1,6 @@
import React, { FC } from 'react'; import React from 'react';
export const AnnotationsHelp: FC = () => { export const AnnotationsHelp = () => {
return ( return (
<div className="gf-form grafana-info-box alert-info"> <div className="gf-form grafana-info-box alert-info">
<div> <div>

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
const TestProvider: React.FC = ({ children }) => { const TestProvider = ({ children }: React.PropsWithChildren<{}>) => {
return <>{children}</>; return <>{children}</>;
}; };