mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Clean up usage of deprecated stylesFactory function (#78419)
This commit is contained in:
@@ -1,20 +1,20 @@
|
|||||||
import { css, cx } from '@emotion/css';
|
import { css, cx } from '@emotion/css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { stylesFactory } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FullWidthButtonContainer = ({ className, children }: React.PropsWithChildren<Props>) => {
|
export const FullWidthButtonContainer = ({ className, children }: React.PropsWithChildren<Props>) => {
|
||||||
const styles = getStyles();
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
return <div className={cx(styles, className)}>{children}</div>;
|
return <div className={cx(styles, className)}>{children}</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory(() => {
|
const getStyles = () =>
|
||||||
return css({
|
css({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
|
||||||
button: {
|
button: {
|
||||||
@@ -31,4 +31,3 @@ const getStyles = stylesFactory(() => {
|
|||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory, useTheme2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { IconName } from '../../types/icon';
|
import { IconName } from '../../types/icon';
|
||||||
import { Button, ButtonProps } from '../Button';
|
import { Button, ButtonProps } from '../Button';
|
||||||
import { CascaderOption } from '../Cascader/Cascader';
|
import { CascaderOption } from '../Cascader/Cascader';
|
||||||
@@ -27,27 +27,9 @@ export interface ButtonCascaderProps {
|
|||||||
hideDownIcon?: boolean;
|
hideDownIcon?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
|
||||||
return {
|
|
||||||
popup: css({
|
|
||||||
label: 'popup',
|
|
||||||
zIndex: theme.zIndex.dropdown,
|
|
||||||
}),
|
|
||||||
icons: {
|
|
||||||
right: css({
|
|
||||||
margin: '1px 0 0 4px',
|
|
||||||
}),
|
|
||||||
left: css({
|
|
||||||
margin: '-1px 4px 0 0',
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const ButtonCascader = (props: ButtonCascaderProps) => {
|
export const ButtonCascader = (props: ButtonCascaderProps) => {
|
||||||
const { onChange, className, loadData, icon, buttonProps, hideDownIcon, variant, disabled, ...rest } = props;
|
const { onChange, className, loadData, icon, buttonProps, hideDownIcon, variant, disabled, ...rest } = props;
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles);
|
||||||
const styles = getStyles(theme);
|
|
||||||
|
|
||||||
// Weird way to do this bit it goes around a styling issue in Button where even null/undefined child triggers
|
// Weird way to do this bit it goes around a styling issue in Button where even null/undefined child triggers
|
||||||
// styling change which messes up the look if there is only single icon content.
|
// styling change which messes up the look if there is only single icon content.
|
||||||
@@ -72,3 +54,20 @@ export const ButtonCascader = (props: ButtonCascaderProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
ButtonCascader.displayName = 'ButtonCascader';
|
ButtonCascader.displayName = 'ButtonCascader';
|
||||||
|
|
||||||
|
const getStyles = (theme: GrafanaTheme2) => {
|
||||||
|
return {
|
||||||
|
popup: css({
|
||||||
|
label: 'popup',
|
||||||
|
zIndex: theme.zIndex.dropdown,
|
||||||
|
}),
|
||||||
|
icons: {
|
||||||
|
right: css({
|
||||||
|
margin: '1px 0 0 4px',
|
||||||
|
}),
|
||||||
|
left: css({
|
||||||
|
margin: '-1px 4px 0 0',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { memo, cloneElement, FC, useMemo, useContext, ReactNode } from 'r
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { useStyles2, useTheme2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { getFocusStyles } from '../../themes/mixins';
|
import { getFocusStyles } from '../../themes/mixins';
|
||||||
|
|
||||||
import { CardContainer, CardContainerProps, getCardContainerStyles } from './CardContainer';
|
import { CardContainer, CardContainerProps, getCardContainerStyles } from './CardContainer';
|
||||||
@@ -55,8 +55,7 @@ export const Card: CardInterface = ({ disabled, href, onClick, children, isSelec
|
|||||||
|
|
||||||
const disableHover = disabled || (!onClick && !href);
|
const disableHover = disabled || (!onClick && !href);
|
||||||
const onCardClick = onClick && !disabled ? onClick : undefined;
|
const onCardClick = onClick && !disabled ? onClick : undefined;
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getCardContainerStyles, disabled, disableHover, isSelected);
|
||||||
const styles = getCardContainerStyles(theme, disabled, disableHover, isSelected);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardContainer
|
<CardContainer
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { HTMLAttributes } from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { styleMixins, stylesFactory, useStyles2, useTheme2 } from '../../themes';
|
import { styleMixins, useStyles2 } from '../../themes';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
@@ -57,8 +57,8 @@ export const CardContainer = ({
|
|||||||
href,
|
href,
|
||||||
...props
|
...props
|
||||||
}: CardContainerProps) => {
|
}: CardContainerProps) => {
|
||||||
const theme = useTheme2();
|
const { oldContainer } = useStyles2(getCardContainerStyles, disableEvents, disableHover, isSelected);
|
||||||
const { oldContainer } = getCardContainerStyles(theme, disableEvents, disableHover, isSelected);
|
|
||||||
return (
|
return (
|
||||||
<div {...props} className={cx(oldContainer, className)}>
|
<div {...props} className={cx(oldContainer, className)}>
|
||||||
<CardInner href={href}>{children}</CardInner>
|
<CardInner href={href}>{children}</CardInner>
|
||||||
@@ -66,71 +66,74 @@ export const CardContainer = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getCardContainerStyles = stylesFactory(
|
export const getCardContainerStyles = (
|
||||||
(theme: GrafanaTheme2, disabled = false, disableHover = false, isSelected) => {
|
theme: GrafanaTheme2,
|
||||||
const isSelectable = isSelected !== undefined;
|
disabled = false,
|
||||||
|
disableHover = false,
|
||||||
|
isSelected?: boolean
|
||||||
|
) => {
|
||||||
|
const isSelectable = isSelected !== undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
container: css({
|
container: css({
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
gridTemplateColumns: 'auto 1fr auto',
|
gridTemplateColumns: 'auto 1fr auto',
|
||||||
gridTemplateRows: '1fr auto auto auto',
|
gridTemplateRows: '1fr auto auto auto',
|
||||||
gridAutoColumns: '1fr',
|
gridAutoColumns: '1fr',
|
||||||
gridAutoFlow: 'row',
|
gridAutoFlow: 'row',
|
||||||
gridTemplateAreas: `
|
gridTemplateAreas: `
|
||||||
"Figure Heading Tags"
|
"Figure Heading Tags"
|
||||||
"Figure Meta Tags"
|
"Figure Meta Tags"
|
||||||
"Figure Description Tags"
|
"Figure Description Tags"
|
||||||
"Figure Actions Secondary"`,
|
"Figure Actions Secondary"`,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
padding: theme.spacing(2),
|
padding: theme.spacing(2),
|
||||||
background: theme.colors.background.secondary,
|
background: theme.colors.background.secondary,
|
||||||
borderRadius: theme.shape.radius.default,
|
borderRadius: theme.shape.radius.default,
|
||||||
marginBottom: '8px',
|
marginBottom: '8px',
|
||||||
pointerEvents: disabled ? 'none' : 'auto',
|
pointerEvents: disabled ? 'none' : 'auto',
|
||||||
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
|
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
|
||||||
duration: theme.transitions.duration.short,
|
duration: theme.transitions.duration.short,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
...(!disableHover && {
|
...(!disableHover && {
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
background: theme.colors.emphasize(theme.colors.background.secondary, 0.03),
|
background: theme.colors.emphasize(theme.colors.background.secondary, 0.03),
|
||||||
cursor: 'pointer',
|
|
||||||
zIndex: 1,
|
|
||||||
},
|
|
||||||
'&:focus': styleMixins.getFocusStyles(theme),
|
|
||||||
}),
|
|
||||||
|
|
||||||
...(isSelectable && {
|
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
}),
|
zIndex: 1,
|
||||||
|
},
|
||||||
...(isSelected && {
|
'&:focus': styleMixins.getFocusStyles(theme),
|
||||||
outline: `solid 2px ${theme.colors.primary.border}`,
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
oldContainer: css({
|
|
||||||
display: 'flex',
|
|
||||||
width: '100%',
|
|
||||||
background: theme.colors.background.secondary,
|
|
||||||
borderRadius: theme.shape.radius.default,
|
|
||||||
position: 'relative',
|
|
||||||
pointerEvents: disabled ? 'none' : 'auto',
|
|
||||||
marginBottom: theme.spacing(1),
|
|
||||||
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
|
|
||||||
duration: theme.transitions.duration.short,
|
|
||||||
}),
|
|
||||||
|
|
||||||
...(!disableHover && {
|
...(isSelectable && {
|
||||||
'&:hover': {
|
cursor: 'pointer',
|
||||||
background: theme.colors.emphasize(theme.colors.background.secondary, 0.03),
|
|
||||||
cursor: 'pointer',
|
|
||||||
zIndex: 1,
|
|
||||||
},
|
|
||||||
'&:focus': styleMixins.getFocusStyles(theme),
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
};
|
|
||||||
}
|
...(isSelected && {
|
||||||
);
|
outline: `solid 2px ${theme.colors.primary.border}`,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
oldContainer: css({
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
background: theme.colors.background.secondary,
|
||||||
|
borderRadius: theme.shape.radius.default,
|
||||||
|
position: 'relative',
|
||||||
|
pointerEvents: disabled ? 'none' : 'auto',
|
||||||
|
marginBottom: theme.spacing(1),
|
||||||
|
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
|
||||||
|
duration: theme.transitions.duration.short,
|
||||||
|
}),
|
||||||
|
|
||||||
|
...(!disableHover && {
|
||||||
|
'&:hover': {
|
||||||
|
background: theme.colors.emphasize(theme.colors.background.secondary, 0.03),
|
||||||
|
cursor: 'pointer',
|
||||||
|
zIndex: 1,
|
||||||
|
},
|
||||||
|
'&:focus': styleMixins.getFocusStyles(theme),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import React, { useState } from 'react';
|
|||||||
|
|
||||||
import { DataFrame, DataLink, GrafanaTheme2, VariableSuggestion } from '@grafana/data';
|
import { DataFrame, DataLink, GrafanaTheme2, VariableSuggestion } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory, useTheme2 } from '../../../themes';
|
import { useStyles2 } from '../../../themes';
|
||||||
import { Button } from '../../Button/Button';
|
import { Button } from '../../Button/Button';
|
||||||
import { Modal } from '../../Modal/Modal';
|
import { Modal } from '../../Modal/Modal';
|
||||||
|
|
||||||
@@ -19,11 +19,10 @@ interface DataLinksInlineEditorProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const DataLinksInlineEditor = ({ links, onChange, getSuggestions, data }: DataLinksInlineEditorProps) => {
|
export const DataLinksInlineEditor = ({ links, onChange, getSuggestions, data }: DataLinksInlineEditorProps) => {
|
||||||
const theme = useTheme2();
|
|
||||||
const [editIndex, setEditIndex] = useState<number | null>(null);
|
const [editIndex, setEditIndex] = useState<number | null>(null);
|
||||||
const [isNew, setIsNew] = useState(false);
|
const [isNew, setIsNew] = useState(false);
|
||||||
|
|
||||||
const styles = getDataLinksInlineEditorStyles(theme);
|
const styles = useStyles2(getDataLinksInlineEditorStyles);
|
||||||
const linksSafe: DataLink[] = links ?? [];
|
const linksSafe: DataLink[] = links ?? [];
|
||||||
const isEditing = editIndex !== null;
|
const isEditing = editIndex !== null;
|
||||||
|
|
||||||
@@ -110,10 +109,8 @@ export const DataLinksInlineEditor = ({ links, onChange, getSuggestions, data }:
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDataLinksInlineEditorStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getDataLinksInlineEditorStyles = (theme: GrafanaTheme2) => ({
|
||||||
return {
|
wrapper: css({
|
||||||
wrapper: css({
|
marginBottom: theme.spacing(2),
|
||||||
marginBottom: theme.spacing(2),
|
}),
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { DataFrame, DataLink, GrafanaTheme2 } from '@grafana/data';
|
import { DataFrame, DataLink, GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory, useTheme2 } from '../../../themes';
|
import { useStyles2 } from '../../../themes';
|
||||||
import { isCompactUrl } from '../../../utils/dataLinks';
|
import { isCompactUrl } from '../../../utils/dataLinks';
|
||||||
import { FieldValidationMessage } from '../../Forms/FieldValidationMessage';
|
import { FieldValidationMessage } from '../../Forms/FieldValidationMessage';
|
||||||
import { IconButton } from '../../IconButton/IconButton';
|
import { IconButton } from '../../IconButton/IconButton';
|
||||||
@@ -19,8 +19,7 @@ export interface DataLinksListItemProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const DataLinksListItem = ({ link, onEdit, onRemove }: DataLinksListItemProps) => {
|
export const DataLinksListItem = ({ link, onEdit, onRemove }: DataLinksListItemProps) => {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getDataLinkListItemStyles);
|
||||||
const styles = getDataLinkListItemStyles(theme);
|
|
||||||
const { title = '', url = '' } = link;
|
const { title = '', url = '' } = link;
|
||||||
|
|
||||||
const hasTitle = title.trim() !== '';
|
const hasTitle = title.trim() !== '';
|
||||||
@@ -52,7 +51,7 @@ export const DataLinksListItem = ({ link, onEdit, onRemove }: DataLinksListItemP
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDataLinkListItemStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getDataLinkListItemStyles = (theme: GrafanaTheme2) => {
|
||||||
return {
|
return {
|
||||||
wrapper: css({
|
wrapper: css({
|
||||||
marginBottom: theme.spacing(2),
|
marginBottom: theme.spacing(2),
|
||||||
@@ -95,4 +94,4 @@ const getDataLinkListItemStyles = stylesFactory((theme: GrafanaTheme2) => {
|
|||||||
maxWidth: '90%',
|
maxWidth: '90%',
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import React, { PureComponent } from 'react';
|
|||||||
|
|
||||||
import { DataSourceSettings } from '@grafana/data';
|
import { DataSourceSettings } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { Button } from '../Button';
|
import { Button } from '../Button';
|
||||||
import { FormField } from '../FormField/FormField';
|
import { FormField } from '../FormField/FormField';
|
||||||
import { Icon } from '../Icon/Icon';
|
import { Icon } from '../Icon/Icon';
|
||||||
@@ -36,26 +36,25 @@ interface CustomHeaderRowProps {
|
|||||||
onBlur: () => void;
|
onBlur: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getCustomHeaderRowStyles = stylesFactory(() => {
|
const getCustomHeaderRowStyles = () => ({
|
||||||
return {
|
layout: css({
|
||||||
layout: css({
|
display: 'flex',
|
||||||
display: 'flex',
|
alignItems: 'center',
|
||||||
alignItems: 'center',
|
marginBottom: '4px',
|
||||||
marginBottom: '4px',
|
'> *': {
|
||||||
'> *': {
|
marginLeft: '4px',
|
||||||
marginLeft: '4px',
|
marginBottom: 0,
|
||||||
marginBottom: 0,
|
height: '100%',
|
||||||
height: '100%',
|
'&:first-child, &:last-child': {
|
||||||
'&:first-child, &:last-child': {
|
marginLeft: 0,
|
||||||
marginLeft: 0,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
};
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }: CustomHeaderRowProps) => {
|
const CustomHeaderRow = ({ header, onBlur, onChange, onRemove, onReset }: CustomHeaderRowProps) => {
|
||||||
const styles = getCustomHeaderRowStyles();
|
const styles = useStyles2(getCustomHeaderRowStyles);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.layout}>
|
<div className={styles.layout}>
|
||||||
<FormField
|
<FormField
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export const DateTimePicker = ({
|
|||||||
const { dialogProps } = useDialog({}, ref);
|
const { dialogProps } = useDialog({}, ref);
|
||||||
|
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
const { modalBackdrop } = getModalStyles(theme);
|
const { modalBackdrop } = useStyles2(getModalStyles);
|
||||||
const isFullscreen = useMedia(`(min-width: ${theme.breakpoints.values.lg}px)`);
|
const isFullscreen = useMedia(`(min-width: ${theme.breakpoints.values.lg}px)`);
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import React, { FormEvent, MouseEvent, useState } from 'react';
|
|||||||
import { dateTime, getDefaultTimeRange, GrafanaTheme2, TimeRange, TimeZone } from '@grafana/data';
|
import { dateTime, getDefaultTimeRange, GrafanaTheme2, TimeRange, TimeZone } from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
import { stylesFactory } from '../../themes';
|
import { useStyles2 } from '../../themes/ThemeContext';
|
||||||
import { useTheme2 } from '../../themes/ThemeContext';
|
|
||||||
import { ClickOutsideWrapper } from '../ClickOutsideWrapper/ClickOutsideWrapper';
|
import { ClickOutsideWrapper } from '../ClickOutsideWrapper/ClickOutsideWrapper';
|
||||||
import { Icon } from '../Icon/Icon';
|
import { Icon } from '../Icon/Icon';
|
||||||
import { getInputStyles } from '../Input/Input';
|
import { getInputStyles } from '../Input/Input';
|
||||||
@@ -47,8 +46,7 @@ export const TimeRangeInput = ({
|
|||||||
showIcon = false,
|
showIcon = false,
|
||||||
}: TimeRangeInputProps) => {
|
}: TimeRangeInputProps) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles, disabled);
|
||||||
const styles = getStyles(theme, disabled);
|
|
||||||
|
|
||||||
const onOpen = (event: FormEvent<HTMLButtonElement>) => {
|
const onOpen = (event: FormEvent<HTMLButtonElement>) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@@ -115,7 +113,7 @@ export const TimeRangeInput = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2, disabled = false) => {
|
const getStyles = (theme: GrafanaTheme2, disabled = false) => {
|
||||||
const inputStyles = getInputStyles({ theme, invalid: false });
|
const inputStyles = getInputStyles({ theme, invalid: false });
|
||||||
return {
|
return {
|
||||||
container: css({
|
container: css({
|
||||||
@@ -163,4 +161,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, disabled = false) => {
|
|||||||
marginRight: theme.spacing(0.5),
|
marginRight: theme.spacing(0.5),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
import { useStyles2, useTheme2 } from '../../themes/ThemeContext';
|
import { useStyles2 } from '../../themes/ThemeContext';
|
||||||
import { t, Trans } from '../../utils/i18n';
|
import { t, Trans } from '../../utils/i18n';
|
||||||
import { ButtonGroup } from '../Button';
|
import { ButtonGroup } from '../Button';
|
||||||
import { getModalStyles } from '../Modal/getModalStyles';
|
import { getModalStyles } from '../Modal/getModalStyles';
|
||||||
@@ -106,9 +106,8 @@ export function TimeRangePicker(props: TimeRangePickerProps) {
|
|||||||
);
|
);
|
||||||
const { dialogProps } = useDialog({}, overlayRef);
|
const { dialogProps } = useDialog({}, overlayRef);
|
||||||
|
|
||||||
const theme = useTheme2();
|
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
const { modalBackdrop } = getModalStyles(theme);
|
const { modalBackdrop } = useStyles2(getModalStyles);
|
||||||
const hasAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to);
|
const hasAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to);
|
||||||
const variant = isSynced ? 'active' : isOnCanvas ? 'canvas' : 'default';
|
const variant = isSynced ? 'active' : isOnCanvas ? 'canvas' : 'default';
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import React, { FormEvent, memo } from 'react';
|
|||||||
import { DateTime, GrafanaTheme2, TimeZone } from '@grafana/data';
|
import { DateTime, GrafanaTheme2, TimeZone } from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
import { useTheme2 } from '../../../themes';
|
import { useStyles2, useTheme2 } from '../../../themes';
|
||||||
import { getModalStyles } from '../../Modal/getModalStyles';
|
import { getModalStyles } from '../../Modal/getModalStyles';
|
||||||
|
|
||||||
import { Body } from './CalendarBody';
|
import { Body } from './CalendarBody';
|
||||||
@@ -68,7 +68,7 @@ export interface TimePickerCalendarProps {
|
|||||||
|
|
||||||
function TimePickerCalendar(props: TimePickerCalendarProps) {
|
function TimePickerCalendar(props: TimePickerCalendarProps) {
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
const { modalBackdrop } = getModalStyles(theme);
|
const { modalBackdrop } = useStyles2(getModalStyles);
|
||||||
const styles = getStyles(theme, props.isReversed);
|
const styles = getStyles(theme, props.isReversed);
|
||||||
const { isOpen, isFullscreen, onClose } = props;
|
const { isOpen, isFullscreen, onClose } = props;
|
||||||
const ref = React.createRef<HTMLElement>();
|
const ref = React.createRef<HTMLElement>();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import React, { memo, useMemo, useState } from 'react';
|
|||||||
import { GrafanaTheme2, isDateTime, rangeUtil, RawTimeRange, TimeOption, TimeRange, TimeZone } from '@grafana/data';
|
import { GrafanaTheme2, isDateTime, rangeUtil, RawTimeRange, TimeOption, TimeRange, TimeZone } from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
import { stylesFactory, useTheme2 } from '../../../themes';
|
import { useStyles2, useTheme2 } from '../../../themes';
|
||||||
import { getFocusStyles } from '../../../themes/mixins';
|
import { getFocusStyles } from '../../../themes/mixins';
|
||||||
import { t, Trans } from '../../../utils/i18n';
|
import { t, Trans } from '../../../utils/i18n';
|
||||||
import { CustomScrollbar } from '../../CustomScrollbar/CustomScrollbar';
|
import { CustomScrollbar } from '../../CustomScrollbar/CustomScrollbar';
|
||||||
@@ -63,8 +63,7 @@ export const TimePickerContentWithScreenSize = (props: PropsWithScreenSize) => {
|
|||||||
const isHistoryEmpty = !history?.length;
|
const isHistoryEmpty = !history?.length;
|
||||||
const isContainerTall =
|
const isContainerTall =
|
||||||
(isFullscreen && showHistory) || (!isFullscreen && ((showHistory && !isHistoryEmpty) || !hideQuickRanges));
|
(isFullscreen && showHistory) || (!isFullscreen && ((showHistory && !isHistoryEmpty) || !hideQuickRanges));
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles, isReversed, hideQuickRanges, isContainerTall, isFullscreen);
|
||||||
const styles = getStyles(theme, isReversed, hideQuickRanges, isContainerTall, isFullscreen);
|
|
||||||
const historyOptions = mapToHistoryOptions(history, timeZone);
|
const historyOptions = mapToHistoryOptions(history, timeZone);
|
||||||
const timeOption = useTimeOption(value.raw, quickOptions);
|
const timeOption = useTimeOption(value.raw, quickOptions);
|
||||||
const [searchTerm, setSearchQuery] = useState('');
|
const [searchTerm, setSearchQuery] = useState('');
|
||||||
@@ -124,8 +123,7 @@ export const TimePickerContent = (props: Props) => {
|
|||||||
|
|
||||||
const NarrowScreenForm = (props: FormProps) => {
|
const NarrowScreenForm = (props: FormProps) => {
|
||||||
const { value, hideQuickRanges, onChange, timeZone, historyOptions = [], showHistory } = props;
|
const { value, hideQuickRanges, onChange, timeZone, historyOptions = [], showHistory } = props;
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getNarrowScreenStyles);
|
||||||
const styles = getNarrowScreenStyles(theme);
|
|
||||||
const isAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to);
|
const isAbsolute = isDateTime(value.raw.from) || isDateTime(value.raw.to);
|
||||||
const [collapsedFlag, setCollapsedFlag] = useState(!isAbsolute);
|
const [collapsedFlag, setCollapsedFlag] = useState(!isAbsolute);
|
||||||
const collapsed = hideQuickRanges ? false : collapsedFlag;
|
const collapsed = hideQuickRanges ? false : collapsedFlag;
|
||||||
@@ -176,8 +174,7 @@ const NarrowScreenForm = (props: FormProps) => {
|
|||||||
|
|
||||||
const FullScreenForm = (props: FormProps) => {
|
const FullScreenForm = (props: FormProps) => {
|
||||||
const { onChange, value, timeZone, fiscalYearStartMonth, isReversed, historyOptions } = props;
|
const { onChange, value, timeZone, fiscalYearStartMonth, isReversed, historyOptions } = props;
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getFullScreenStyles, props.hideQuickRanges);
|
||||||
const styles = getFullScreenStyles(theme, props.hideQuickRanges);
|
|
||||||
const onChangeTimeOption = (timeOption: TimeOption) => {
|
const onChangeTimeOption = (timeOption: TimeOption) => {
|
||||||
return onChange(mapOptionToTimeRange(timeOption, timeZone));
|
return onChange(mapOptionToTimeRange(timeOption, timeZone));
|
||||||
};
|
};
|
||||||
@@ -214,8 +211,7 @@ const FullScreenForm = (props: FormProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const EmptyRecentList = memo(() => {
|
const EmptyRecentList = memo(() => {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getEmptyListStyles);
|
||||||
const styles = getEmptyListStyles(theme);
|
|
||||||
const emptyRecentListText = t(
|
const emptyRecentListText = t(
|
||||||
'time-picker.content.empty-recent-list-info',
|
'time-picker.content.empty-recent-list-info',
|
||||||
"It looks like you haven't used this time picker before. As soon as you enter some time intervals, recently used intervals will appear here."
|
"It looks like you haven't used this time picker before. As soon as you enter some time intervals, recently used intervals will appear here."
|
||||||
@@ -263,104 +259,102 @@ const useTimeOption = (raw: RawTimeRange, quickOptions: TimeOption[]): TimeOptio
|
|||||||
}, [raw, quickOptions]);
|
}, [raw, quickOptions]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2, isReversed, hideQuickRanges, isContainerTall, isFullscreen) => {
|
const getStyles = (
|
||||||
return {
|
theme: GrafanaTheme2,
|
||||||
container: css({
|
isReversed?: boolean,
|
||||||
background: theme.colors.background.primary,
|
hideQuickRanges?: boolean,
|
||||||
boxShadow: theme.shadows.z3,
|
isContainerTall?: boolean,
|
||||||
width: `${isFullscreen ? '546px' : '262px'}`,
|
isFullscreen?: boolean
|
||||||
borderRadius: theme.shape.radius.default,
|
) => ({
|
||||||
border: `1px solid ${theme.colors.border.weak}`,
|
container: css({
|
||||||
[`${isReversed ? 'left' : 'right'}`]: 0,
|
background: theme.colors.background.primary,
|
||||||
}),
|
boxShadow: theme.shadows.z3,
|
||||||
body: css({
|
width: `${isFullscreen ? '546px' : '262px'}`,
|
||||||
display: 'flex',
|
borderRadius: theme.shape.radius.default,
|
||||||
flexDirection: 'row-reverse',
|
border: `1px solid ${theme.colors.border.weak}`,
|
||||||
height: `${isContainerTall ? '381px' : '217px'}`,
|
[`${isReversed ? 'left' : 'right'}`]: 0,
|
||||||
maxHeight: '100vh',
|
}),
|
||||||
}),
|
body: css({
|
||||||
leftSide: css({
|
display: 'flex',
|
||||||
display: 'flex',
|
flexDirection: 'row-reverse',
|
||||||
flexDirection: 'column',
|
height: `${isContainerTall ? '381px' : '217px'}`,
|
||||||
borderRight: `${isReversed ? 'none' : `1px solid ${theme.colors.border.weak}`}`,
|
maxHeight: '100vh',
|
||||||
width: `${!hideQuickRanges ? '60%' : '100%'}`,
|
}),
|
||||||
overflow: 'hidden',
|
leftSide: css({
|
||||||
order: isReversed ? 1 : 0,
|
display: 'flex',
|
||||||
}),
|
flexDirection: 'column',
|
||||||
rightSide: css({
|
borderRight: `${isReversed ? 'none' : `1px solid ${theme.colors.border.weak}`}`,
|
||||||
width: `${isFullscreen ? '40%' : '100%'}; !important`,
|
width: `${!hideQuickRanges ? '60%' : '100%'}`,
|
||||||
borderRight: isReversed ? `1px solid ${theme.colors.border.weak}` : 'none',
|
overflow: 'hidden',
|
||||||
display: 'flex',
|
order: isReversed ? 1 : 0,
|
||||||
flexDirection: 'column',
|
}),
|
||||||
}),
|
rightSide: css({
|
||||||
timeRangeFilter: css({
|
width: `${isFullscreen ? '40%' : '100%'}; !important`,
|
||||||
padding: theme.spacing(1),
|
borderRight: isReversed ? `1px solid ${theme.colors.border.weak}` : 'none',
|
||||||
}),
|
display: 'flex',
|
||||||
spacing: css({
|
flexDirection: 'column',
|
||||||
marginTop: '16px',
|
}),
|
||||||
}),
|
timeRangeFilter: css({
|
||||||
};
|
padding: theme.spacing(1),
|
||||||
|
}),
|
||||||
|
spacing: css({
|
||||||
|
marginTop: '16px',
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const getNarrowScreenStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getNarrowScreenStyles = (theme: GrafanaTheme2) => ({
|
||||||
return {
|
header: css({
|
||||||
header: css({
|
display: 'flex',
|
||||||
display: 'flex',
|
flexDirection: 'row',
|
||||||
flexDirection: 'row',
|
justifyContent: 'space-between',
|
||||||
justifyContent: 'space-between',
|
alignItems: 'center',
|
||||||
alignItems: 'center',
|
borderBottom: `1px solid ${theme.colors.border.weak}`,
|
||||||
borderBottom: `1px solid ${theme.colors.border.weak}`,
|
padding: '7px 9px 7px 9px',
|
||||||
padding: '7px 9px 7px 9px',
|
}),
|
||||||
}),
|
expandButton: css({
|
||||||
expandButton: css({
|
backgroundColor: 'transparent',
|
||||||
backgroundColor: 'transparent',
|
border: 'none',
|
||||||
border: 'none',
|
display: 'flex',
|
||||||
display: 'flex',
|
width: '100%',
|
||||||
width: '100%',
|
|
||||||
|
|
||||||
'&:focus-visible': getFocusStyles(theme),
|
'&:focus-visible': getFocusStyles(theme),
|
||||||
}),
|
}),
|
||||||
body: css({
|
body: css({
|
||||||
borderBottom: `1px solid ${theme.colors.border.weak}`,
|
borderBottom: `1px solid ${theme.colors.border.weak}`,
|
||||||
}),
|
}),
|
||||||
form: css({
|
form: css({
|
||||||
padding: '7px 9px 7px 9px',
|
padding: '7px 9px 7px 9px',
|
||||||
}),
|
}),
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const getFullScreenStyles = stylesFactory((theme: GrafanaTheme2, hideQuickRanges?: boolean) => {
|
const getFullScreenStyles = (theme: GrafanaTheme2, hideQuickRanges?: boolean) => ({
|
||||||
return {
|
container: css({
|
||||||
container: css({
|
paddingTop: '9px',
|
||||||
paddingTop: '9px',
|
paddingLeft: '11px',
|
||||||
paddingLeft: '11px',
|
paddingRight: !hideQuickRanges ? '20%' : '11px',
|
||||||
paddingRight: !hideQuickRanges ? '20%' : '11px',
|
}),
|
||||||
}),
|
title: css({
|
||||||
title: css({
|
marginBottom: '11px',
|
||||||
marginBottom: '11px',
|
}),
|
||||||
}),
|
recent: css({
|
||||||
recent: css({
|
flexGrow: 1,
|
||||||
flexGrow: 1,
|
display: 'flex',
|
||||||
display: 'flex',
|
flexDirection: 'column',
|
||||||
flexDirection: 'column',
|
justifyContent: 'flex-end',
|
||||||
justifyContent: 'flex-end',
|
paddingTop: theme.spacing(1),
|
||||||
paddingTop: theme.spacing(1),
|
}),
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const getEmptyListStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getEmptyListStyles = (theme: GrafanaTheme2) => ({
|
||||||
return {
|
container: css({
|
||||||
container: css({
|
padding: '12px',
|
||||||
padding: '12px',
|
margin: '12px',
|
||||||
margin: '12px',
|
|
||||||
|
|
||||||
'a, span': {
|
'a, span': {
|
||||||
fontSize: '13px',
|
fontSize: '13px',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
link: css({
|
link: css({
|
||||||
color: theme.colors.text.link,
|
color: theme.colors.text.link,
|
||||||
}),
|
}),
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import React, { useCallback, useState } from 'react';
|
|||||||
import { getTimeZoneInfo, GrafanaTheme2, TimeZone } from '@grafana/data';
|
import { getTimeZoneInfo, GrafanaTheme2, TimeZone } from '@grafana/data';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
import { stylesFactory, useTheme2 } from '../../../themes';
|
import { useStyles2 } from '../../../themes';
|
||||||
import { t, Trans } from '../../../utils/i18n';
|
import { t, Trans } from '../../../utils/i18n';
|
||||||
import { Button } from '../../Button';
|
import { Button } from '../../Button';
|
||||||
import { Field } from '../../Forms/Field';
|
import { Field } from '../../Forms/Field';
|
||||||
@@ -46,8 +46,7 @@ export const TimePickerFooter = (props: Props) => {
|
|||||||
[isEditing, setEditing]
|
[isEditing, setEditing]
|
||||||
);
|
);
|
||||||
|
|
||||||
const theme = useTheme2();
|
const style = useStyles2(getStyle);
|
||||||
const style = getStyle(theme);
|
|
||||||
|
|
||||||
if (!isString(timeZone)) {
|
if (!isString(timeZone)) {
|
||||||
return null;
|
return null;
|
||||||
@@ -136,43 +135,41 @@ export const TimePickerFooter = (props: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyle = stylesFactory((theme: GrafanaTheme2) => {
|
const getStyle = (theme: GrafanaTheme2) => ({
|
||||||
return {
|
container: css({
|
||||||
container: css({
|
borderTop: `1px solid ${theme.colors.border.weak}`,
|
||||||
borderTop: `1px solid ${theme.colors.border.weak}`,
|
padding: '11px',
|
||||||
padding: '11px',
|
display: 'flex',
|
||||||
display: 'flex',
|
flexDirection: 'row',
|
||||||
flexDirection: 'row',
|
justifyContent: 'space-between',
|
||||||
justifyContent: 'space-between',
|
alignItems: 'center',
|
||||||
alignItems: 'center',
|
}),
|
||||||
}),
|
editContainer: css({
|
||||||
editContainer: css({
|
borderTop: `1px solid ${theme.colors.border.weak}`,
|
||||||
borderTop: `1px solid ${theme.colors.border.weak}`,
|
padding: '11px',
|
||||||
padding: '11px',
|
justifyContent: 'space-between',
|
||||||
justifyContent: 'space-between',
|
alignItems: 'center',
|
||||||
alignItems: 'center',
|
}),
|
||||||
}),
|
spacer: css({
|
||||||
spacer: css({
|
marginLeft: '7px',
|
||||||
marginLeft: '7px',
|
}),
|
||||||
}),
|
timeSettingContainer: css({
|
||||||
timeSettingContainer: css({
|
paddingTop: theme.spacing(1),
|
||||||
paddingTop: theme.spacing(1),
|
}),
|
||||||
}),
|
fiscalYearField: css({
|
||||||
fiscalYearField: css({
|
marginBottom: 0,
|
||||||
marginBottom: 0,
|
}),
|
||||||
}),
|
timeZoneContainer: css({
|
||||||
timeZoneContainer: css({
|
display: 'flex',
|
||||||
display: 'flex',
|
flexDirection: 'row',
|
||||||
flexDirection: 'row',
|
justifyContent: 'space-between',
|
||||||
justifyContent: 'space-between',
|
alignItems: 'center',
|
||||||
alignItems: 'center',
|
flexGrow: 1,
|
||||||
flexGrow: 1,
|
}),
|
||||||
}),
|
timeZone: css({
|
||||||
timeZone: css({
|
display: 'flex',
|
||||||
display: 'flex',
|
flexDirection: 'row',
|
||||||
flexDirection: 'row',
|
alignItems: 'baseline',
|
||||||
alignItems: 'baseline',
|
flexGrow: 1,
|
||||||
flexGrow: 1,
|
}),
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,32 +3,12 @@ import React, { ReactNode } from 'react';
|
|||||||
|
|
||||||
import { TimeOption } from '@grafana/data';
|
import { TimeOption } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory } from '../../../themes';
|
import { useStyles2 } from '../../../themes';
|
||||||
import { t } from '../../../utils/i18n';
|
import { t } from '../../../utils/i18n';
|
||||||
|
|
||||||
import { TimePickerTitle } from './TimePickerTitle';
|
import { TimePickerTitle } from './TimePickerTitle';
|
||||||
import { TimeRangeOption } from './TimeRangeOption';
|
import { TimeRangeOption } from './TimeRangeOption';
|
||||||
|
|
||||||
const getStyles = stylesFactory(() => {
|
|
||||||
return {
|
|
||||||
title: css({
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
padding: '8px 16px 5px 9px',
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const getOptionsStyles = stylesFactory(() => {
|
|
||||||
return {
|
|
||||||
grow: css({
|
|
||||||
flexGrow: 1,
|
|
||||||
alignItems: 'flex-start',
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title?: string;
|
title?: string;
|
||||||
options: TimeOption[];
|
options: TimeOption[];
|
||||||
@@ -38,7 +18,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const TimeRangeList = (props: Props) => {
|
export const TimeRangeList = (props: Props) => {
|
||||||
const styles = getStyles();
|
const styles = useStyles2(getStyles);
|
||||||
const { title, options, placeholderEmpty } = props;
|
const { title, options, placeholderEmpty } = props;
|
||||||
|
|
||||||
if (typeof placeholderEmpty !== 'undefined' && options.length <= 0) {
|
if (typeof placeholderEmpty !== 'undefined' && options.length <= 0) {
|
||||||
@@ -62,7 +42,7 @@ export const TimeRangeList = (props: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Options = ({ options, value, onChange, title }: Props) => {
|
const Options = ({ options, value, onChange, title }: Props) => {
|
||||||
const styles = getOptionsStyles();
|
const styles = useStyles2(getOptionsStyles);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -92,3 +72,19 @@ function isEqual(x: TimeOption, y?: TimeOption): boolean {
|
|||||||
}
|
}
|
||||||
return y.from === x.from && y.to === x.to;
|
return y.from === x.from && y.to === x.to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getStyles = () => ({
|
||||||
|
title: css({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
padding: '8px 16px 5px 9px',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const getOptionsStyles = () => ({
|
||||||
|
grow: css({
|
||||||
|
flexGrow: 1,
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import React, { PropsWithChildren, RefCallback } from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2, SelectableValue, getTimeZoneInfo } from '@grafana/data';
|
import { GrafanaTheme2, SelectableValue, getTimeZoneInfo } from '@grafana/data';
|
||||||
|
|
||||||
import { useTheme2 } from '../../../themes/ThemeContext';
|
import { useStyles2 } from '../../../themes';
|
||||||
import { stylesFactory } from '../../../themes/stylesFactory';
|
|
||||||
import { Icon } from '../../Icon/Icon';
|
import { Icon } from '../../Icon/Icon';
|
||||||
|
|
||||||
import { TimeZoneDescription } from './TimeZoneDescription';
|
import { TimeZoneDescription } from './TimeZoneDescription';
|
||||||
@@ -28,8 +27,7 @@ export interface SelectableZone extends SelectableValue<string> {
|
|||||||
|
|
||||||
export const WideTimeZoneOption = (props: PropsWithChildren<Props>) => {
|
export const WideTimeZoneOption = (props: PropsWithChildren<Props>) => {
|
||||||
const { children, innerProps, innerRef, data, isSelected, isFocused } = props;
|
const { children, innerProps, innerRef, data, isSelected, isFocused } = props;
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles);
|
||||||
const styles = getStyles(theme);
|
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
const containerStyles = cx(styles.container, isFocused && styles.containerFocused);
|
const containerStyles = cx(styles.container, isFocused && styles.containerFocused);
|
||||||
|
|
||||||
@@ -68,8 +66,7 @@ export const WideTimeZoneOption = (props: PropsWithChildren<Props>) => {
|
|||||||
|
|
||||||
export const CompactTimeZoneOption = (props: React.PropsWithChildren<Props>) => {
|
export const CompactTimeZoneOption = (props: React.PropsWithChildren<Props>) => {
|
||||||
const { children, innerProps, innerRef, data, isSelected, isFocused } = props;
|
const { children, innerProps, innerRef, data, isSelected, isFocused } = props;
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles);
|
||||||
const styles = getStyles(theme);
|
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
const containerStyles = cx(styles.container, isFocused && styles.containerFocused);
|
const containerStyles = cx(styles.container, isFocused && styles.containerFocused);
|
||||||
|
|
||||||
@@ -113,49 +110,47 @@ export const CompactTimeZoneOption = (props: React.PropsWithChildren<Props>) =>
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
return {
|
container: css({
|
||||||
container: css({
|
display: 'flex',
|
||||||
display: 'flex',
|
alignItems: 'center',
|
||||||
alignItems: 'center',
|
flexDirection: 'row',
|
||||||
flexDirection: 'row',
|
flexShrink: 0,
|
||||||
flexShrink: 0,
|
whiteSpace: 'nowrap',
|
||||||
whiteSpace: 'nowrap',
|
cursor: 'pointer',
|
||||||
cursor: 'pointer',
|
padding: '6px 8px 4px',
|
||||||
padding: '6px 8px 4px',
|
|
||||||
|
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
background: theme.colors.action.hover,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
containerFocused: css({
|
|
||||||
background: theme.colors.action.hover,
|
background: theme.colors.action.hover,
|
||||||
}),
|
},
|
||||||
body: css({
|
}),
|
||||||
display: 'flex',
|
containerFocused: css({
|
||||||
fontWeight: theme.typography.fontWeightMedium,
|
background: theme.colors.action.hover,
|
||||||
flexDirection: 'column',
|
}),
|
||||||
flexGrow: 1,
|
body: css({
|
||||||
}),
|
display: 'flex',
|
||||||
row: css({
|
fontWeight: theme.typography.fontWeightMedium,
|
||||||
display: 'flex',
|
flexDirection: 'column',
|
||||||
flexDirection: 'row',
|
flexGrow: 1,
|
||||||
}),
|
}),
|
||||||
leftColumn: css({
|
row: css({
|
||||||
flexGrow: 1,
|
display: 'flex',
|
||||||
textOverflow: 'ellipsis',
|
flexDirection: 'row',
|
||||||
}),
|
}),
|
||||||
rightColumn: css({
|
leftColumn: css({
|
||||||
justifyContent: 'flex-end',
|
flexGrow: 1,
|
||||||
alignItems: 'center',
|
textOverflow: 'ellipsis',
|
||||||
}),
|
}),
|
||||||
wideRow: css({
|
rightColumn: css({
|
||||||
display: 'flex',
|
justifyContent: 'flex-end',
|
||||||
flexDirection: 'row',
|
alignItems: 'center',
|
||||||
alignItems: 'baseline',
|
}),
|
||||||
}),
|
wideRow: css({
|
||||||
spacer: css({
|
display: 'flex',
|
||||||
marginLeft: '6px',
|
flexDirection: 'row',
|
||||||
}),
|
alignItems: 'baseline',
|
||||||
};
|
}),
|
||||||
|
spacer: css({
|
||||||
|
marginLeft: '6px',
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,30 +1,34 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { stylesFactory } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
|
|
||||||
import { ErrorBoundaryApi } from './ErrorBoundary';
|
import { ErrorBoundaryApi } from './ErrorBoundary';
|
||||||
|
|
||||||
const getStyles = stylesFactory(() => {
|
|
||||||
return css({
|
|
||||||
width: '500px',
|
|
||||||
margin: '64px auto',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
export interface Props extends ErrorBoundaryApi {
|
export interface Props extends ErrorBoundaryApi {
|
||||||
title: string;
|
title: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ErrorWithStack = ({ error, errorInfo, title }: Props) => (
|
export const ErrorWithStack = ({ error, errorInfo, title }: Props) => {
|
||||||
<div className={getStyles()}>
|
const style = useStyles2(getStyles);
|
||||||
<h2>{title}</h2>
|
|
||||||
<details style={{ whiteSpace: 'pre-wrap' }}>
|
return (
|
||||||
{error && error.toString()}
|
<div className={style}>
|
||||||
<br />
|
<h2>{title}</h2>
|
||||||
{errorInfo && errorInfo.componentStack}
|
<details style={{ whiteSpace: 'pre-wrap' }}>
|
||||||
</details>
|
{error && error.toString()}
|
||||||
</div>
|
<br />
|
||||||
);
|
{errorInfo && errorInfo.componentStack}
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
ErrorWithStack.displayName = 'ErrorWithStack';
|
ErrorWithStack.displayName = 'ErrorWithStack';
|
||||||
|
|
||||||
|
const getStyles = () => {
|
||||||
|
return css({
|
||||||
|
width: '500px',
|
||||||
|
margin: '64px auto',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { HTMLProps, useCallback } from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { useTheme2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
|
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
|
||||||
|
|
||||||
import { getLabelStyles } from './Label';
|
import { getLabelStyles } from './Label';
|
||||||
@@ -36,8 +36,7 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
|||||||
},
|
},
|
||||||
[onChange]
|
[onChange]
|
||||||
);
|
);
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getCheckboxStyles, invalid);
|
||||||
const styles = getCheckboxStyles(theme, invalid);
|
|
||||||
|
|
||||||
const ariaChecked = indeterminate ? 'mixed' : undefined;
|
const ariaChecked = indeterminate ? 'mixed' : undefined;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { HTMLAttributes } from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory, useTheme2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { getChildId } from '../../utils/reactUtils';
|
import { getChildId } from '../../utils/reactUtils';
|
||||||
|
|
||||||
import { FieldValidationMessage } from './FieldValidationMessage';
|
import { FieldValidationMessage } from './FieldValidationMessage';
|
||||||
@@ -40,35 +40,6 @@ export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
|
|||||||
htmlFor?: string;
|
htmlFor?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getFieldStyles = stylesFactory((theme: GrafanaTheme2) => {
|
|
||||||
return {
|
|
||||||
field: css({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
marginBottom: theme.spacing(2),
|
|
||||||
}),
|
|
||||||
fieldHorizontal: css({
|
|
||||||
flexDirection: 'row',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
}),
|
|
||||||
fieldValidationWrapper: css({
|
|
||||||
marginTop: theme.spacing(0.5),
|
|
||||||
}),
|
|
||||||
fieldValidationWrapperHorizontal: css({
|
|
||||||
flex: '1 1 100%',
|
|
||||||
}),
|
|
||||||
validationMessageHorizontalOverflow: css({
|
|
||||||
width: 0,
|
|
||||||
overflowX: 'visible',
|
|
||||||
|
|
||||||
'& > *': {
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
@@ -88,8 +59,7 @@ export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
|||||||
}: FieldProps,
|
}: FieldProps,
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getFieldStyles);
|
||||||
const styles = getFieldStyles(theme);
|
|
||||||
const inputId = htmlFor ?? getChildId(children);
|
const inputId = htmlFor ?? getChildId(children);
|
||||||
|
|
||||||
const labelElement =
|
const labelElement =
|
||||||
@@ -143,3 +113,30 @@ function deleteUndefinedProps<T extends Object>(obj: T): Partial<T> {
|
|||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getFieldStyles = (theme: GrafanaTheme2) => ({
|
||||||
|
field: css({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
marginBottom: theme.spacing(2),
|
||||||
|
}),
|
||||||
|
fieldHorizontal: css({
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
}),
|
||||||
|
fieldValidationWrapper: css({
|
||||||
|
marginTop: theme.spacing(0.5),
|
||||||
|
}),
|
||||||
|
fieldValidationWrapperHorizontal: css({
|
||||||
|
flex: '1 1 100%',
|
||||||
|
}),
|
||||||
|
validationMessageHorizontalOverflow: css({
|
||||||
|
width: 0,
|
||||||
|
overflowX: 'visible',
|
||||||
|
|
||||||
|
'& > *': {
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { HTMLProps } from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory, useTheme2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
|
|
||||||
import { Legend } from './Legend';
|
import { Legend } from './Legend';
|
||||||
|
|
||||||
@@ -14,8 +14,7 @@ export interface Props extends Omit<HTMLProps<HTMLFieldSetElement>, 'label'> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const FieldSet = ({ label, children, className, ...rest }: Props) => {
|
export const FieldSet = ({ label, children, className, ...rest }: Props) => {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles);
|
||||||
const styles = getStyles(theme);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<fieldset className={cx(styles.wrapper, className)} {...rest}>
|
<fieldset className={cx(styles.wrapper, className)} {...rest}>
|
||||||
@@ -25,14 +24,12 @@ export const FieldSet = ({ label, children, className, ...rest }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
return {
|
wrapper: css({
|
||||||
wrapper: css({
|
marginBottom: theme.spacing(4),
|
||||||
marginBottom: theme.spacing(4),
|
|
||||||
|
|
||||||
'&:last-child': {
|
'&:last-child': {
|
||||||
marginBottom: 0,
|
marginBottom: 0,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory, useTheme2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { Icon } from '../Icon/Icon';
|
import { Icon } from '../Icon/Icon';
|
||||||
|
|
||||||
export interface FieldValidationMessageProps {
|
export interface FieldValidationMessageProps {
|
||||||
@@ -12,7 +12,23 @@ export interface FieldValidationMessageProps {
|
|||||||
horizontal?: boolean;
|
horizontal?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getFieldValidationMessageStyles = stylesFactory((theme: GrafanaTheme2) => {
|
export const FieldValidationMessage = ({
|
||||||
|
children,
|
||||||
|
horizontal,
|
||||||
|
className,
|
||||||
|
}: React.PropsWithChildren<FieldValidationMessageProps>) => {
|
||||||
|
const styles = useStyles2(getFieldValidationMessageStyles);
|
||||||
|
const cssName = cx(horizontal ? styles.horizontal : styles.vertical, className);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div role="alert" className={cssName}>
|
||||||
|
<Icon className={styles.fieldValidationMessageIcon} name="exclamation-triangle" />
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getFieldValidationMessageStyles = (theme: GrafanaTheme2) => {
|
||||||
const baseStyle = `
|
const baseStyle = `
|
||||||
font-size: ${theme.typography.size.sm};
|
font-size: ${theme.typography.size.sm};
|
||||||
font-weight: ${theme.typography.fontWeightMedium};
|
font-weight: ${theme.typography.fontWeightMedium};
|
||||||
@@ -69,21 +85,4 @@ export const getFieldValidationMessageStyles = stylesFactory((theme: GrafanaThem
|
|||||||
marginRight: theme.spacing(),
|
marginRight: theme.spacing(),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
|
||||||
export const FieldValidationMessage = ({
|
|
||||||
children,
|
|
||||||
horizontal,
|
|
||||||
className,
|
|
||||||
}: React.PropsWithChildren<FieldValidationMessageProps>) => {
|
|
||||||
const theme = useTheme2();
|
|
||||||
const styles = getFieldValidationMessageStyles(theme);
|
|
||||||
const cssName = cx(horizontal ? styles.horizontal : styles.vertical, className);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div role="alert" className={cssName}>
|
|
||||||
<Icon className={styles.fieldValidationMessageIcon} name="exclamation-triangle" />
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { useTheme2, stylesFactory } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { Icon } from '../Icon/Icon';
|
import { Icon } from '../Icon/Icon';
|
||||||
|
|
||||||
export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {
|
export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {
|
||||||
@@ -12,43 +12,8 @@ export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement>
|
|||||||
category?: React.ReactNode[];
|
category?: React.ReactNode[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getLabelStyles = stylesFactory((theme: GrafanaTheme2) => {
|
|
||||||
return {
|
|
||||||
label: css({
|
|
||||||
label: 'Label',
|
|
||||||
fontSize: theme.typography.size.sm,
|
|
||||||
fontWeight: theme.typography.fontWeightMedium,
|
|
||||||
lineHeight: 1.25,
|
|
||||||
marginBottom: theme.spacing(0.5),
|
|
||||||
color: theme.colors.text.primary,
|
|
||||||
maxWidth: '480px',
|
|
||||||
}),
|
|
||||||
labelContent: css({
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
}),
|
|
||||||
description: css({
|
|
||||||
label: 'Label-description',
|
|
||||||
color: theme.colors.text.secondary,
|
|
||||||
fontSize: theme.typography.size.sm,
|
|
||||||
fontWeight: theme.typography.fontWeightRegular,
|
|
||||||
marginTop: theme.spacing(0.25),
|
|
||||||
display: 'block',
|
|
||||||
}),
|
|
||||||
categories: css({
|
|
||||||
label: 'Label-categories',
|
|
||||||
display: 'inline-flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
}),
|
|
||||||
chevron: css({
|
|
||||||
margin: theme.spacing(0, 0.25),
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const Label = ({ children, description, className, category, ...labelProps }: LabelProps) => {
|
export const Label = ({ children, description, className, category, ...labelProps }: LabelProps) => {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getLabelStyles);
|
||||||
const styles = getLabelStyles(theme);
|
|
||||||
const categories = category?.map((c, i) => {
|
const categories = category?.map((c, i) => {
|
||||||
return (
|
return (
|
||||||
<span className={styles.categories} key={`${c}/${i}`}>
|
<span className={styles.categories} key={`${c}/${i}`}>
|
||||||
@@ -70,3 +35,35 @@ export const Label = ({ children, description, className, category, ...labelProp
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getLabelStyles = (theme: GrafanaTheme2) => ({
|
||||||
|
label: css({
|
||||||
|
label: 'Label',
|
||||||
|
fontSize: theme.typography.size.sm,
|
||||||
|
fontWeight: theme.typography.fontWeightMedium,
|
||||||
|
lineHeight: 1.25,
|
||||||
|
marginBottom: theme.spacing(0.5),
|
||||||
|
color: theme.colors.text.primary,
|
||||||
|
maxWidth: '480px',
|
||||||
|
}),
|
||||||
|
labelContent: css({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
}),
|
||||||
|
description: css({
|
||||||
|
label: 'Label-description',
|
||||||
|
color: theme.colors.text.secondary,
|
||||||
|
fontSize: theme.typography.size.sm,
|
||||||
|
fontWeight: theme.typography.fontWeightRegular,
|
||||||
|
marginTop: theme.spacing(0.25),
|
||||||
|
display: 'block',
|
||||||
|
}),
|
||||||
|
categories: css({
|
||||||
|
label: 'Label-categories',
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
}),
|
||||||
|
chevron: css({
|
||||||
|
margin: theme.spacing(0, 0.25),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import React from 'react';
|
|||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { StringSelector } from '@grafana/e2e-selectors';
|
import { StringSelector } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
import { useTheme2, stylesFactory } from '../../../themes';
|
import { useStyles2 } from '../../../themes';
|
||||||
import { getFocusStyles, getMouseFocusStyles } from '../../../themes/mixins';
|
import { getFocusStyles, getMouseFocusStyles } from '../../../themes/mixins';
|
||||||
import { getPropertiesForButtonSize } from '../commonStyles';
|
import { getPropertiesForButtonSize } from '../commonStyles';
|
||||||
|
|
||||||
@@ -41,8 +41,7 @@ export const RadioButton = React.forwardRef<HTMLInputElement, RadioButtonProps>(
|
|||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getRadioButtonStyles, size, fullWidth);
|
||||||
const styles = getRadioButtonStyles(theme, size, fullWidth);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.radioOption}>
|
<div className={styles.radioOption}>
|
||||||
@@ -68,7 +67,7 @@ export const RadioButton = React.forwardRef<HTMLInputElement, RadioButtonProps>(
|
|||||||
|
|
||||||
RadioButton.displayName = 'RadioButton';
|
RadioButton.displayName = 'RadioButton';
|
||||||
|
|
||||||
const getRadioButtonStyles = stylesFactory((theme: GrafanaTheme2, size: RadioButtonSize, fullWidth?: boolean) => {
|
const getRadioButtonStyles = (theme: GrafanaTheme2, size: RadioButtonSize, fullWidth?: boolean) => {
|
||||||
const { fontSize, height, padding } = getPropertiesForButtonSize(size, theme);
|
const { fontSize, height, padding } = getPropertiesForButtonSize(size, theme);
|
||||||
|
|
||||||
const textColor = theme.colors.text.secondary;
|
const textColor = theme.colors.text.secondary;
|
||||||
@@ -130,4 +129,4 @@ const getRadioButtonStyles = stylesFactory((theme: GrafanaTheme2, size: RadioBut
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2, colorManipulator, deprecationWarning } from '@grafana/data';
|
import { GrafanaTheme2, colorManipulator, deprecationWarning } from '@grafana/data';
|
||||||
|
|
||||||
import { useTheme2, stylesFactory } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
|
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
|
||||||
import { ComponentSize } from '../../types';
|
import { ComponentSize } from '../../types';
|
||||||
import { IconName, IconSize, IconType } from '../../types/icon';
|
import { IconName, IconSize, IconType } from '../../types/icon';
|
||||||
@@ -44,8 +44,6 @@ export type Props = BasePropsWithTooltip | BasePropsWithAriaLabel;
|
|||||||
|
|
||||||
export const IconButton = React.forwardRef<HTMLButtonElement, Props>((props, ref) => {
|
export const IconButton = React.forwardRef<HTMLButtonElement, Props>((props, ref) => {
|
||||||
const { size = 'md', variant = 'secondary' } = props;
|
const { size = 'md', variant = 'secondary' } = props;
|
||||||
|
|
||||||
const theme = useTheme2();
|
|
||||||
let limitedIconSize: LimitedIconSize;
|
let limitedIconSize: LimitedIconSize;
|
||||||
|
|
||||||
// very large icons (xl to xxxl) are unified to size xl
|
// very large icons (xl to xxxl) are unified to size xl
|
||||||
@@ -56,7 +54,7 @@ export const IconButton = React.forwardRef<HTMLButtonElement, Props>((props, ref
|
|||||||
limitedIconSize = size;
|
limitedIconSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = getStyles(theme, limitedIconSize, variant);
|
const styles = useStyles2(getStyles, limitedIconSize, variant);
|
||||||
|
|
||||||
let ariaLabel: string | undefined;
|
let ariaLabel: string | undefined;
|
||||||
let buttonRef: typeof ref | undefined;
|
let buttonRef: typeof ref | undefined;
|
||||||
@@ -104,7 +102,7 @@ export const IconButton = React.forwardRef<HTMLButtonElement, Props>((props, ref
|
|||||||
|
|
||||||
IconButton.displayName = 'IconButton';
|
IconButton.displayName = 'IconButton';
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2, size, variant: IconButtonVariant) => {
|
const getStyles = (theme: GrafanaTheme2, size: IconSize, variant: IconButtonVariant) => {
|
||||||
// overall size of the IconButton on hover
|
// overall size of the IconButton on hover
|
||||||
// theme.spacing.gridSize originates from 2*4px for padding and letting the IconSize generally decide on the hoverSize
|
// theme.spacing.gridSize originates from 2*4px for padding and letting the IconSize generally decide on the hoverSize
|
||||||
const hoverSize = getSvgSize(size) + theme.spacing.gridSize;
|
const hoverSize = getSvgSize(size) + theme.spacing.gridSize;
|
||||||
@@ -166,4 +164,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, size, variant: IconButton
|
|||||||
verticalAlign: 'baseline',
|
verticalAlign: 'baseline',
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory, useStyles2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { Alert, AlertVariant } from '../Alert/Alert';
|
import { Alert, AlertVariant } from '../Alert/Alert';
|
||||||
import { Icon } from '../Icon/Icon';
|
import { Icon } from '../Icon/Icon';
|
||||||
|
|
||||||
@@ -45,11 +45,9 @@ export const InfoBox = React.memo(
|
|||||||
|
|
||||||
InfoBox.displayName = 'InfoBox';
|
InfoBox.displayName = 'InfoBox';
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
return {
|
docsLink: css({
|
||||||
docsLink: css({
|
display: 'inline-block',
|
||||||
display: 'inline-block',
|
marginTop: theme.spacing(2),
|
||||||
marginTop: theme.spacing(2),
|
}),
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { FocusScope } from '@react-aria/focus';
|
|||||||
import { OverlayContainer, useOverlay } from '@react-aria/overlays';
|
import { OverlayContainer, useOverlay } from '@react-aria/overlays';
|
||||||
import React, { PropsWithChildren, useRef } from 'react';
|
import React, { PropsWithChildren, useRef } from 'react';
|
||||||
|
|
||||||
import { useTheme2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { IconName } from '../../types';
|
import { IconName } from '../../types';
|
||||||
import { t } from '../../utils/i18n';
|
import { t } from '../../utils/i18n';
|
||||||
import { IconButton } from '../IconButton/IconButton';
|
import { IconButton } from '../IconButton/IconButton';
|
||||||
@@ -46,8 +46,7 @@ export function Modal(props: PropsWithChildren<Props>) {
|
|||||||
onClickBackdrop,
|
onClickBackdrop,
|
||||||
trapFocus = true,
|
trapFocus = true,
|
||||||
} = props;
|
} = props;
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getModalStyles);
|
||||||
const styles = getModalStyles(theme);
|
|
||||||
|
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
@@ -101,8 +100,7 @@ export function Modal(props: PropsWithChildren<Props>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ModalButtonRow({ leftItems, children }: { leftItems?: React.ReactNode; children: React.ReactNode }) {
|
function ModalButtonRow({ leftItems, children }: { leftItems?: React.ReactNode; children: React.ReactNode }) {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getModalStyles);
|
||||||
const styles = getModalStyles(theme);
|
|
||||||
|
|
||||||
if (leftItems) {
|
if (leftItems) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ import { css } from '@emotion/css';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory } from '../../themes';
|
export const getModalStyles = (theme: GrafanaTheme2) => {
|
||||||
|
|
||||||
export const getModalStyles = stylesFactory((theme: GrafanaTheme2) => {
|
|
||||||
const borderRadius = theme.shape.radius.default;
|
const borderRadius = theme.shape.radius.default;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -80,4 +78,4 @@ export const getModalStyles = stylesFactory((theme: GrafanaTheme2) => {
|
|||||||
paddingTop: theme.spacing(3),
|
paddingTop: theme.spacing(3),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory } from '../../themes';
|
import { useStyles2 } from '../../themes/ThemeContext';
|
||||||
import { useTheme2 } from '../../themes/ThemeContext';
|
|
||||||
import { inputPadding } from '../Forms/commonStyles';
|
import { inputPadding } from '../Forms/commonStyles';
|
||||||
import { getInputStyles } from '../Input/Input';
|
import { getInputStyles } from '../Input/Input';
|
||||||
|
|
||||||
@@ -17,7 +16,20 @@ interface InputControlProps {
|
|||||||
innerProps: JSX.IntrinsicElements['div'];
|
innerProps: JSX.IntrinsicElements['div'];
|
||||||
}
|
}
|
||||||
|
|
||||||
const getInputControlStyles = stylesFactory((theme: GrafanaTheme2, invalid: boolean, withPrefix: boolean) => {
|
export const InputControl = React.forwardRef<HTMLDivElement, React.PropsWithChildren<InputControlProps>>(
|
||||||
|
function InputControl({ focused, invalid, disabled, children, innerProps, prefix, ...otherProps }, ref) {
|
||||||
|
const styles = useStyles2(getInputControlStyles, invalid, !!prefix);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.input} {...innerProps} ref={ref}>
|
||||||
|
{prefix && <div className={cx(styles.prefix)}>{prefix}</div>}
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const getInputControlStyles = (theme: GrafanaTheme2, invalid: boolean, withPrefix: boolean) => {
|
||||||
const styles = getInputStyles({ theme, invalid });
|
const styles = getInputStyles({ theme, invalid });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -47,17 +59,4 @@ const getInputControlStyles = stylesFactory((theme: GrafanaTheme2, invalid: bool
|
|||||||
})
|
})
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
|
|
||||||
export const InputControl = React.forwardRef<HTMLDivElement, React.PropsWithChildren<InputControlProps>>(
|
|
||||||
function InputControl({ focused, invalid, disabled, children, innerProps, prefix, ...otherProps }, ref) {
|
|
||||||
const theme = useTheme2();
|
|
||||||
const styles = getInputControlStyles(theme, invalid, !!prefix);
|
|
||||||
return (
|
|
||||||
<div className={styles.input} {...innerProps} ref={ref}>
|
|
||||||
{prefix && <div className={cx(styles.prefix)}>{prefix}</div>}
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import { components, ContainerProps as BaseContainerProps, GroupBase } from 'rea
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory } from '../../themes';
|
import { useStyles2 } from '../../themes/ThemeContext';
|
||||||
import { useTheme2 } from '../../themes/ThemeContext';
|
|
||||||
import { getFocusStyles } from '../../themes/mixins';
|
import { getFocusStyles } from '../../themes/mixins';
|
||||||
import { sharedInputStyle } from '../Forms/commonStyles';
|
import { sharedInputStyle } from '../Forms/commonStyles';
|
||||||
import { getInputStyles } from '../Input/Input';
|
import { getInputStyles } from '../Input/Input';
|
||||||
@@ -26,8 +25,7 @@ export const SelectContainer = <Option, isMulti extends boolean, Group extends G
|
|||||||
selectProps: { invalid = false },
|
selectProps: { invalid = false },
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getSelectContainerStyles, isFocused, isDisabled, invalid);
|
||||||
const styles = getSelectContainerStyles(theme, isFocused, isDisabled, invalid);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<components.SelectContainer {...props} className={cx(styles.wrapper, props.className)}>
|
<components.SelectContainer {...props} className={cx(styles.wrapper, props.className)}>
|
||||||
@@ -36,33 +34,31 @@ export const SelectContainer = <Option, isMulti extends boolean, Group extends G
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSelectContainerStyles = stylesFactory(
|
const getSelectContainerStyles = (theme: GrafanaTheme2, focused: boolean, disabled: boolean, invalid: boolean) => {
|
||||||
(theme: GrafanaTheme2, focused: boolean, disabled: boolean, invalid: boolean) => {
|
const styles = getInputStyles({ theme, invalid });
|
||||||
const styles = getInputStyles({ theme, invalid });
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
wrapper: cx(
|
wrapper: cx(
|
||||||
styles.wrapper,
|
styles.wrapper,
|
||||||
sharedInputStyle(theme, invalid),
|
sharedInputStyle(theme, invalid),
|
||||||
focused && css(getFocusStyles(theme)),
|
focused && css(getFocusStyles(theme)),
|
||||||
disabled && styles.inputDisabled,
|
disabled && styles.inputDisabled,
|
||||||
css({
|
css({
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
/* The display property is set by the styles prop in SelectBase because it's dependant on the width prop */
|
/* The display property is set by the styles prop in SelectBase because it's dependant on the width prop */
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
alignItems: 'stretch',
|
alignItems: 'stretch',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
minHeight: '32px',
|
minHeight: '32px',
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
|
|
||||||
/* Input padding is applied to the InputControl so the menu is aligned correctly */
|
/* Input padding is applied to the InputControl so the menu is aligned correctly */
|
||||||
padding: 0,
|
padding: 0,
|
||||||
cursor: disabled ? 'not-allowed' : 'pointer',
|
cursor: disabled ? 'not-allowed' : 'pointer',
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
);
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Global } from '@emotion/react';
|
|||||||
import Slider, { SliderProps } from 'rc-slider';
|
import Slider, { SliderProps } from 'rc-slider';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
import { useTheme2 } from '../../themes/ThemeContext';
|
import { useStyles2 } from '../../themes/ThemeContext';
|
||||||
|
|
||||||
import HandleTooltip from './HandleTooltip';
|
import HandleTooltip from './HandleTooltip';
|
||||||
import { getStyles } from './styles';
|
import { getStyles } from './styles';
|
||||||
@@ -43,8 +43,7 @@ export const RangeSlider = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const isHorizontal = orientation === 'horizontal';
|
const isHorizontal = orientation === 'horizontal';
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles, isHorizontal);
|
||||||
const styles = getStyles(theme, isHorizontal);
|
|
||||||
|
|
||||||
const tipHandleRender: SliderProps['handleRender'] = (node, handleProps) => {
|
const tipHandleRender: SliderProps['handleRender'] = (node, handleProps) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Global } from '@emotion/react';
|
|||||||
import SliderComponent from 'rc-slider';
|
import SliderComponent from 'rc-slider';
|
||||||
import React, { useState, useCallback, ChangeEvent, FocusEvent } from 'react';
|
import React, { useState, useCallback, ChangeEvent, FocusEvent } from 'react';
|
||||||
|
|
||||||
import { useTheme2 } from '../../themes/ThemeContext';
|
import { useStyles2 } from '../../themes/ThemeContext';
|
||||||
import { Input } from '../Input/Input';
|
import { Input } from '../Input/Input';
|
||||||
|
|
||||||
import { getStyles } from './styles';
|
import { getStyles } from './styles';
|
||||||
@@ -26,8 +26,7 @@ export const Slider = ({
|
|||||||
included,
|
included,
|
||||||
}: SliderProps) => {
|
}: SliderProps) => {
|
||||||
const isHorizontal = orientation === 'horizontal';
|
const isHorizontal = orientation === 'horizontal';
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles, isHorizontal, Boolean(marks));
|
||||||
const styles = getStyles(theme, isHorizontal, Boolean(marks));
|
|
||||||
const SliderWithTooltip = SliderComponent;
|
const SliderWithTooltip = SliderComponent;
|
||||||
const [sliderValue, setSliderValue] = useState<number>(value ?? min);
|
const [sliderValue, setSliderValue] = useState<number>(value ?? min);
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,7 @@ import { css as cssCore } from '@emotion/react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory } from '../../themes';
|
export const getStyles = (theme: GrafanaTheme2, isHorizontal: boolean, hasMarks = false) => {
|
||||||
|
|
||||||
export const getStyles = stylesFactory((theme: GrafanaTheme2, isHorizontal: boolean, hasMarks = false) => {
|
|
||||||
const { spacing } = theme;
|
const { spacing } = theme;
|
||||||
const railColor = theme.colors.border.strong;
|
const railColor = theme.colors.border.strong;
|
||||||
const trackColor = theme.colors.primary.main;
|
const trackColor = theme.colors.primary.main;
|
||||||
@@ -127,4 +125,4 @@ export const getStyles = stylesFactory((theme: GrafanaTheme2, isHorizontal: bool
|
|||||||
order: 1,
|
order: 1,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
});
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import React, { HTMLProps, useRef } from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2, deprecationWarning } from '@grafana/data';
|
import { GrafanaTheme2, deprecationWarning } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory, useTheme2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
|
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
|
||||||
|
|
||||||
export interface Props extends Omit<HTMLProps<HTMLInputElement>, 'value'> {
|
export interface Props extends Omit<HTMLProps<HTMLInputElement>, 'value'> {
|
||||||
@@ -21,8 +21,7 @@ export const Switch = React.forwardRef<HTMLInputElement, Props>(
|
|||||||
deprecationWarning('Switch', 'checked prop', 'value');
|
deprecationWarning('Switch', 'checked prop', 'value');
|
||||||
}
|
}
|
||||||
|
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getSwitchStyles);
|
||||||
const styles = getSwitchStyles(theme);
|
|
||||||
const switchIdRef = useRef(id ? id : uniqueId('switch-'));
|
const switchIdRef = useRef(id ? id : uniqueId('switch-'));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -52,8 +51,7 @@ export interface InlineSwitchProps extends Props {
|
|||||||
|
|
||||||
export const InlineSwitch = React.forwardRef<HTMLInputElement, InlineSwitchProps>(
|
export const InlineSwitch = React.forwardRef<HTMLInputElement, InlineSwitchProps>(
|
||||||
({ transparent, className, showLabel, label, value, id, invalid, ...props }, ref) => {
|
({ transparent, className, showLabel, label, value, id, invalid, ...props }, ref) => {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getSwitchStyles, transparent);
|
||||||
const styles = getSwitchStyles(theme, transparent);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -75,110 +73,108 @@ export const InlineSwitch = React.forwardRef<HTMLInputElement, InlineSwitchProps
|
|||||||
|
|
||||||
InlineSwitch.displayName = 'Switch';
|
InlineSwitch.displayName = 'Switch';
|
||||||
|
|
||||||
const getSwitchStyles = stylesFactory((theme: GrafanaTheme2, transparent?: boolean) => {
|
const getSwitchStyles = (theme: GrafanaTheme2, transparent?: boolean) => ({
|
||||||
return {
|
switch: css({
|
||||||
switch: css({
|
width: '32px',
|
||||||
width: '32px',
|
height: '16px',
|
||||||
height: '16px',
|
position: 'relative',
|
||||||
position: 'relative',
|
|
||||||
|
|
||||||
input: {
|
input: {
|
||||||
opacity: 0,
|
opacity: 0,
|
||||||
left: '-100vw',
|
left: '-100vw',
|
||||||
zIndex: -1000,
|
zIndex: -1000,
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
|
||||||
'&:disabled + label': {
|
'&:disabled + label': {
|
||||||
background: theme.colors.action.disabledBackground,
|
background: theme.colors.action.disabledBackground,
|
||||||
cursor: 'not-allowed',
|
cursor: 'not-allowed',
|
||||||
},
|
|
||||||
|
|
||||||
'&:checked + label': {
|
|
||||||
background: theme.colors.primary.main,
|
|
||||||
borderColor: theme.colors.primary.main,
|
|
||||||
|
|
||||||
'&:hover': {
|
|
||||||
background: theme.colors.primary.shade,
|
|
||||||
},
|
|
||||||
|
|
||||||
'&::after': {
|
|
||||||
transform: 'translate3d(18px, -50%, 0)',
|
|
||||||
background: theme.colors.primary.contrastText,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
'&:focus + label, &:focus-visible + label': getFocusStyles(theme),
|
|
||||||
|
|
||||||
'&:focus:not(:focus-visible) + label': getMouseFocusStyles(theme),
|
|
||||||
},
|
},
|
||||||
|
|
||||||
label: {
|
'&:checked + label': {
|
||||||
width: '100%',
|
background: theme.colors.primary.main,
|
||||||
height: '100%',
|
borderColor: theme.colors.primary.main,
|
||||||
cursor: 'pointer',
|
|
||||||
borderRadius: theme.shape.radius.pill,
|
|
||||||
background: theme.components.input.background,
|
|
||||||
border: `1px solid ${theme.components.input.borderColor}`,
|
|
||||||
transition: 'all 0.3s ease',
|
|
||||||
|
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
borderColor: theme.components.input.borderHover,
|
background: theme.colors.primary.shade,
|
||||||
},
|
},
|
||||||
|
|
||||||
'&::after': {
|
'&::after': {
|
||||||
position: 'absolute',
|
transform: 'translate3d(18px, -50%, 0)',
|
||||||
display: 'block',
|
background: theme.colors.primary.contrastText,
|
||||||
content: '""',
|
|
||||||
width: '12px',
|
|
||||||
height: '12px',
|
|
||||||
borderRadius: theme.shape.radius.circle,
|
|
||||||
background: theme.colors.text.secondary,
|
|
||||||
boxShadow: theme.shadows.z1,
|
|
||||||
top: '50%',
|
|
||||||
transform: 'translate3d(2px, -50%, 0)',
|
|
||||||
transition: 'transform 0.2s cubic-bezier(0.19, 1, 0.22, 1)',
|
|
||||||
|
|
||||||
'@media (forced-colors: active)': {
|
|
||||||
border: '1px solid transparent',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
|
||||||
inlineContainer: css({
|
'&:focus + label, &:focus-visible + label': getFocusStyles(theme),
|
||||||
padding: theme.spacing(0, 1),
|
|
||||||
height: theme.spacing(theme.components.height.md),
|
'&:focus:not(:focus-visible) + label': getMouseFocusStyles(theme),
|
||||||
display: 'inline-flex',
|
},
|
||||||
alignItems: 'center',
|
|
||||||
background: transparent ? 'transparent' : theme.components.input.background,
|
label: {
|
||||||
border: `1px solid ${transparent ? 'transparent' : theme.components.input.borderColor}`,
|
width: '100%',
|
||||||
borderRadius: theme.shape.radius.default,
|
height: '100%',
|
||||||
|
cursor: 'pointer',
|
||||||
|
borderRadius: theme.shape.radius.pill,
|
||||||
|
background: theme.components.input.background,
|
||||||
|
border: `1px solid ${theme.components.input.borderColor}`,
|
||||||
|
transition: 'all 0.3s ease',
|
||||||
|
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
border: `1px solid ${transparent ? 'transparent' : theme.components.input.borderHover}`,
|
borderColor: theme.components.input.borderHover,
|
||||||
|
},
|
||||||
|
|
||||||
'.inline-switch-label': {
|
'&::after': {
|
||||||
color: theme.colors.text.primary,
|
position: 'absolute',
|
||||||
|
display: 'block',
|
||||||
|
content: '""',
|
||||||
|
width: '12px',
|
||||||
|
height: '12px',
|
||||||
|
borderRadius: theme.shape.radius.circle,
|
||||||
|
background: theme.colors.text.secondary,
|
||||||
|
boxShadow: theme.shadows.z1,
|
||||||
|
top: '50%',
|
||||||
|
transform: 'translate3d(2px, -50%, 0)',
|
||||||
|
transition: 'transform 0.2s cubic-bezier(0.19, 1, 0.22, 1)',
|
||||||
|
|
||||||
|
'@media (forced-colors: active)': {
|
||||||
|
border: '1px solid transparent',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
disabled: css({
|
}),
|
||||||
backgroundColor: 'rgba(204, 204, 220, 0.04)',
|
inlineContainer: css({
|
||||||
color: 'rgba(204, 204, 220, 0.6)',
|
padding: theme.spacing(0, 1),
|
||||||
border: '1px solid rgba(204, 204, 220, 0.04)',
|
height: theme.spacing(theme.components.height.md),
|
||||||
}),
|
display: 'inline-flex',
|
||||||
inlineLabel: css({
|
alignItems: 'center',
|
||||||
cursor: 'pointer',
|
background: transparent ? 'transparent' : theme.components.input.background,
|
||||||
paddingRight: theme.spacing(1),
|
border: `1px solid ${transparent ? 'transparent' : theme.components.input.borderColor}`,
|
||||||
color: theme.colors.text.secondary,
|
borderRadius: theme.shape.radius.default,
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
}),
|
'&:hover': {
|
||||||
inlineLabelEnabled: css({
|
border: `1px solid ${transparent ? 'transparent' : theme.components.input.borderHover}`,
|
||||||
color: theme.colors.text.primary,
|
|
||||||
}),
|
'.inline-switch-label': {
|
||||||
invalid: css({
|
color: theme.colors.text.primary,
|
||||||
'input + label, input:checked + label, input:hover + label': {
|
|
||||||
border: `1px solid ${theme.colors.error.border}`,
|
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
};
|
}),
|
||||||
|
disabled: css({
|
||||||
|
backgroundColor: 'rgba(204, 204, 220, 0.04)',
|
||||||
|
color: 'rgba(204, 204, 220, 0.6)',
|
||||||
|
border: '1px solid rgba(204, 204, 220, 0.04)',
|
||||||
|
}),
|
||||||
|
inlineLabel: css({
|
||||||
|
cursor: 'pointer',
|
||||||
|
paddingRight: theme.spacing(1),
|
||||||
|
color: theme.colors.text.secondary,
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
}),
|
||||||
|
inlineLabelEnabled: css({
|
||||||
|
color: theme.colors.text.primary,
|
||||||
|
}),
|
||||||
|
invalid: css({
|
||||||
|
'input + label, input:checked + label, input:hover + label': {
|
||||||
|
border: `1px solid ${theme.colors.error.border}`,
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { SelectableValue, GrafanaTheme2 } from '@grafana/data';
|
|||||||
|
|
||||||
import { IconButton } from '../../components/IconButton/IconButton';
|
import { IconButton } from '../../components/IconButton/IconButton';
|
||||||
import { TabsBar, Tab, TabContent } from '../../components/Tabs';
|
import { TabsBar, Tab, TabContent } from '../../components/Tabs';
|
||||||
import { stylesFactory, useTheme2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { IconName } from '../../types/icon';
|
import { IconName } from '../../types/icon';
|
||||||
import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
|
import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
|
||||||
|
|
||||||
@@ -23,45 +23,14 @@ export interface TabbedContainerProps {
|
|||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
export function TabbedContainer({ tabs, defaultTab, closeIconTooltip, onClose }: TabbedContainerProps) {
|
||||||
return {
|
const [activeTab, setActiveTab] = useState(tabs.some((tab) => tab.value === defaultTab) ? defaultTab : tabs[0].value);
|
||||||
container: css({
|
|
||||||
height: '100%',
|
|
||||||
}),
|
|
||||||
tabContent: css({
|
|
||||||
padding: theme.spacing(2),
|
|
||||||
backgroundColor: theme.colors.background.primary,
|
|
||||||
height: `calc(100% - ${theme.components.menuTabs.height}px)`,
|
|
||||||
}),
|
|
||||||
close: css({
|
|
||||||
position: 'absolute',
|
|
||||||
right: '16px',
|
|
||||||
top: '5px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
fontSize: theme.typography.size.lg,
|
|
||||||
}),
|
|
||||||
tabs: css({
|
|
||||||
paddingTop: theme.spacing(1),
|
|
||||||
borderColor: theme.colors.border.weak,
|
|
||||||
ul: {
|
|
||||||
marginLeft: theme.spacing(2),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export function TabbedContainer(props: TabbedContainerProps) {
|
|
||||||
const [activeTab, setActiveTab] = useState(
|
|
||||||
props.tabs.some((tab) => tab.value === props.defaultTab) ? props.defaultTab : props.tabs?.[0].value
|
|
||||||
);
|
|
||||||
|
|
||||||
const onSelectTab = (item: SelectableValue<string>) => {
|
const onSelectTab = (item: SelectableValue<string>) => {
|
||||||
setActiveTab(item.value!);
|
setActiveTab(item.value!);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { tabs, onClose, closeIconTooltip } = props;
|
const styles = useStyles2(getStyles);
|
||||||
const theme = useTheme2();
|
|
||||||
const styles = getStyles(theme);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
@@ -83,3 +52,28 @@ export function TabbedContainer(props: TabbedContainerProps) {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
|
container: css({
|
||||||
|
height: '100%',
|
||||||
|
}),
|
||||||
|
tabContent: css({
|
||||||
|
padding: theme.spacing(2),
|
||||||
|
backgroundColor: theme.colors.background.primary,
|
||||||
|
height: `calc(100% - ${theme.components.menuTabs.height}px)`,
|
||||||
|
}),
|
||||||
|
close: css({
|
||||||
|
position: 'absolute',
|
||||||
|
right: '16px',
|
||||||
|
top: '5px',
|
||||||
|
cursor: 'pointer',
|
||||||
|
fontSize: theme.typography.size.lg,
|
||||||
|
}),
|
||||||
|
tabs: css({
|
||||||
|
paddingTop: theme.spacing(1),
|
||||||
|
borderColor: theme.colors.border.weak,
|
||||||
|
ul: {
|
||||||
|
marginLeft: theme.spacing(2),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { FixedSizeList as List } from 'react-window';
|
|||||||
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
|
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
|
||||||
|
|
||||||
import { Checkbox, FilterInput, Label, VerticalGroup } from '..';
|
import { Checkbox, FilterInput, Label, VerticalGroup } from '..';
|
||||||
import { stylesFactory, useTheme2 } from '../../themes';
|
import { useStyles2, useTheme2 } from '../../themes';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
values: SelectableValue[];
|
values: SelectableValue[];
|
||||||
@@ -18,8 +18,6 @@ const ITEM_HEIGHT = 28;
|
|||||||
const MIN_HEIGHT = ITEM_HEIGHT * 5;
|
const MIN_HEIGHT = ITEM_HEIGHT * 5;
|
||||||
|
|
||||||
export const FilterList = ({ options, values, caseSensitive, onChange }: Props) => {
|
export const FilterList = ({ options, values, caseSensitive, onChange }: Props) => {
|
||||||
const theme = useTheme2();
|
|
||||||
const styles = getStyles(theme);
|
|
||||||
const [searchFilter, setSearchFilter] = useState('');
|
const [searchFilter, setSearchFilter] = useState('');
|
||||||
const regex = useMemo(() => new RegExp(searchFilter, caseSensitive ? undefined : 'i'), [searchFilter, caseSensitive]);
|
const regex = useMemo(() => new RegExp(searchFilter, caseSensitive ? undefined : 'i'), [searchFilter, caseSensitive]);
|
||||||
const items = useMemo(
|
const items = useMemo(
|
||||||
@@ -32,16 +30,12 @@ export const FilterList = ({ options, values, caseSensitive, onChange }: Props)
|
|||||||
}),
|
}),
|
||||||
[options, regex]
|
[options, regex]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const styles = useStyles2(getStyles);
|
||||||
|
const theme = useTheme2();
|
||||||
const gutter = theme.spacing.gridSize;
|
const gutter = theme.spacing.gridSize;
|
||||||
const height = useMemo(() => Math.min(items.length * ITEM_HEIGHT, MIN_HEIGHT) + gutter, [gutter, items.length]);
|
const height = useMemo(() => Math.min(items.length * ITEM_HEIGHT, MIN_HEIGHT) + gutter, [gutter, items.length]);
|
||||||
|
|
||||||
const onInputChange = useCallback(
|
|
||||||
(v: string) => {
|
|
||||||
setSearchFilter(v);
|
|
||||||
},
|
|
||||||
[setSearchFilter]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onCheckedChanged = useCallback(
|
const onCheckedChanged = useCallback(
|
||||||
(option: SelectableValue) => (event: React.FormEvent<HTMLInputElement>) => {
|
(option: SelectableValue) => (event: React.FormEvent<HTMLInputElement>) => {
|
||||||
const newValues = event.currentTarget.checked
|
const newValues = event.currentTarget.checked
|
||||||
@@ -55,7 +49,7 @@ export const FilterList = ({ options, values, caseSensitive, onChange }: Props)
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<VerticalGroup spacing="md">
|
<VerticalGroup spacing="md">
|
||||||
<FilterInput placeholder="Filter values" onChange={onInputChange} value={searchFilter} />
|
<FilterInput placeholder="Filter values" onChange={setSearchFilter} value={searchFilter} />
|
||||||
{!items.length && <Label>No values</Label>}
|
{!items.length && <Label>No values</Label>}
|
||||||
{items.length && (
|
{items.length && (
|
||||||
<List
|
<List
|
||||||
@@ -82,7 +76,7 @@ export const FilterList = ({ options, values, caseSensitive, onChange }: Props)
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => ({
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
filterList: css({
|
filterList: css({
|
||||||
label: 'filterList',
|
label: 'filterList',
|
||||||
}),
|
}),
|
||||||
@@ -98,4 +92,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => ({
|
|||||||
backgroundColor: theme.colors.action.hover,
|
backgroundColor: theme.colors.action.hover,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
}));
|
});
|
||||||
|
|||||||
@@ -3,22 +3,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2, locale } from '@grafana/data';
|
import { GrafanaTheme2, locale } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory, useStyles2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
|
||||||
return {
|
|
||||||
counter: css({
|
|
||||||
label: 'counter',
|
|
||||||
marginLeft: theme.spacing(1),
|
|
||||||
borderRadius: theme.spacing(3),
|
|
||||||
backgroundColor: theme.colors.action.hover,
|
|
||||||
padding: theme.spacing(0.25, 1),
|
|
||||||
color: theme.colors.text.secondary,
|
|
||||||
fontWeight: theme.typography.fontWeightMedium,
|
|
||||||
fontSize: theme.typography.size.sm,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export interface CounterProps {
|
export interface CounterProps {
|
||||||
value: number;
|
value: number;
|
||||||
@@ -29,3 +14,16 @@ export const Counter = ({ value }: CounterProps) => {
|
|||||||
|
|
||||||
return <span className={styles.counter}>{locale(value, 0).text}</span>;
|
return <span className={styles.counter}>{locale(value, 0).text}</span>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
|
counter: css({
|
||||||
|
label: 'counter',
|
||||||
|
marginLeft: theme.spacing(1),
|
||||||
|
borderRadius: theme.spacing(3),
|
||||||
|
backgroundColor: theme.colors.action.hover,
|
||||||
|
padding: theme.spacing(0.25, 1),
|
||||||
|
color: theme.colors.text.secondary,
|
||||||
|
fontWeight: theme.typography.fontWeightMedium,
|
||||||
|
fontSize: theme.typography.size.sm,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@@ -3,23 +3,14 @@ import React, { HTMLAttributes, ReactNode } from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory, useTheme2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
|
|
||||||
interface Props extends HTMLAttributes<HTMLDivElement> {
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTabContentStyle = stylesFactory((theme: GrafanaTheme2) => {
|
|
||||||
return {
|
|
||||||
tabContent: css({
|
|
||||||
background: theme.colors.background.primary,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export const TabContent = ({ children, className, ...restProps }: Props) => {
|
export const TabContent = ({ children, className, ...restProps }: Props) => {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getTabContentStyle);
|
||||||
const styles = getTabContentStyle(theme);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...restProps} className={cx(styles.tabContent, className)}>
|
<div {...restProps} className={cx(styles.tabContent, className)}>
|
||||||
@@ -27,3 +18,9 @@ export const TabContent = ({ children, className, ...restProps }: Props) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getTabContentStyle = (theme: GrafanaTheme2) => ({
|
||||||
|
tabContent: css({
|
||||||
|
background: theme.colors.background.primary,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { HTMLProps } from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
import { stylesFactory, useTheme2 } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
import { getFocusStyle, sharedInputStyle } from '../Forms/commonStyles';
|
import { getFocusStyle, sharedInputStyle } from '../Forms/commonStyles';
|
||||||
|
|
||||||
export interface Props extends Omit<HTMLProps<HTMLTextAreaElement>, 'size'> {
|
export interface Props extends Omit<HTMLProps<HTMLTextAreaElement>, 'size'> {
|
||||||
@@ -12,26 +12,23 @@ export interface Props extends Omit<HTMLProps<HTMLTextAreaElement>, 'size'> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const TextArea = React.forwardRef<HTMLTextAreaElement, Props>(({ invalid, className, ...props }, ref) => {
|
export const TextArea = React.forwardRef<HTMLTextAreaElement, Props>(({ invalid, className, ...props }, ref) => {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getTextAreaStyle, invalid);
|
||||||
const styles = getTextAreaStyle(theme, invalid);
|
|
||||||
|
|
||||||
return <textarea {...props} className={cx(styles.textarea, className)} ref={ref} />;
|
return <textarea {...props} className={cx(styles.textarea, className)} ref={ref} />;
|
||||||
});
|
});
|
||||||
|
|
||||||
const getTextAreaStyle = stylesFactory((theme: GrafanaTheme2, invalid = false) => {
|
const getTextAreaStyle = (theme: GrafanaTheme2, invalid = false) => ({
|
||||||
return {
|
textarea: cx(
|
||||||
textarea: cx(
|
sharedInputStyle(theme),
|
||||||
sharedInputStyle(theme),
|
getFocusStyle(theme),
|
||||||
getFocusStyle(theme),
|
css({
|
||||||
css({
|
display: 'block',
|
||||||
display: 'block',
|
borderRadius: theme.shape.radius.default,
|
||||||
borderRadius: theme.shape.radius.default,
|
padding: `${theme.spacing.gridSize / 4}px ${theme.spacing.gridSize}px`,
|
||||||
padding: `${theme.spacing.gridSize / 4}px ${theme.spacing.gridSize}px`,
|
width: '100%',
|
||||||
width: '100%',
|
borderColor: invalid ? theme.colors.error.border : theme.components.input.borderColor,
|
||||||
borderColor: invalid ? theme.colors.error.border : theme.components.input.borderColor,
|
})
|
||||||
})
|
),
|
||||||
),
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
TextArea.displayName = 'TextArea';
|
TextArea.displayName = 'TextArea';
|
||||||
|
|||||||
@@ -2,30 +2,9 @@ import { css } from '@emotion/css';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { CSSTransition } from 'react-transition-group';
|
import { CSSTransition } from 'react-transition-group';
|
||||||
|
|
||||||
import { stylesFactory } from '../../themes';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
const getStyles = stylesFactory((duration: number) => {
|
import { useStyles2 } from '../../themes';
|
||||||
return {
|
|
||||||
enter: css({
|
|
||||||
label: 'enter',
|
|
||||||
opacity: 0,
|
|
||||||
}),
|
|
||||||
enterActive: css({
|
|
||||||
label: 'enterActive',
|
|
||||||
opacity: 1,
|
|
||||||
transition: `opacity ${duration}ms ease-out`,
|
|
||||||
}),
|
|
||||||
exit: css({
|
|
||||||
label: 'exit',
|
|
||||||
opacity: 1,
|
|
||||||
}),
|
|
||||||
exitActive: css({
|
|
||||||
label: 'exitActive',
|
|
||||||
opacity: 0,
|
|
||||||
transition: `opacity ${duration}ms ease-out`,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@@ -35,10 +14,32 @@ type Props = {
|
|||||||
|
|
||||||
export function FadeTransition(props: Props) {
|
export function FadeTransition(props: Props) {
|
||||||
const { visible, children, duration = 250 } = props;
|
const { visible, children, duration = 250 } = props;
|
||||||
const styles = getStyles(duration);
|
const styles = useStyles2(getStyles, duration);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CSSTransition in={visible} mountOnEnter={true} unmountOnExit={true} timeout={duration} classNames={styles}>
|
<CSSTransition in={visible} mountOnEnter={true} unmountOnExit={true} timeout={duration} classNames={styles}>
|
||||||
{children}
|
{children}
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getStyles = (_theme: GrafanaTheme2, duration: number) => ({
|
||||||
|
enter: css({
|
||||||
|
label: 'enter',
|
||||||
|
opacity: 0,
|
||||||
|
}),
|
||||||
|
enterActive: css({
|
||||||
|
label: 'enterActive',
|
||||||
|
opacity: 1,
|
||||||
|
transition: `opacity ${duration}ms ease-out`,
|
||||||
|
}),
|
||||||
|
exit: css({
|
||||||
|
label: 'exit',
|
||||||
|
opacity: 1,
|
||||||
|
}),
|
||||||
|
exitActive: css({
|
||||||
|
label: 'exitActive',
|
||||||
|
opacity: 0,
|
||||||
|
transition: `opacity ${duration}ms ease-out`,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@@ -2,34 +2,9 @@ import { css } from '@emotion/css';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { CSSTransition } from 'react-transition-group';
|
import { CSSTransition } from 'react-transition-group';
|
||||||
|
|
||||||
import { stylesFactory } from '../../themes';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
|
||||||
const getStyles = stylesFactory((duration: number, measurement: 'width' | 'height', size: number) => {
|
import { useStyles2 } from '../../themes';
|
||||||
return {
|
|
||||||
enter: css({
|
|
||||||
label: 'enter',
|
|
||||||
[`${measurement}`]: 0,
|
|
||||||
opacity: 0,
|
|
||||||
}),
|
|
||||||
enterActive: css({
|
|
||||||
label: 'enterActive',
|
|
||||||
[`${measurement}`]: `${size}px`,
|
|
||||||
opacity: 1,
|
|
||||||
transition: `opacity ${duration}ms ease-out, ${measurement} ${duration}ms ease-out`,
|
|
||||||
}),
|
|
||||||
exit: css({
|
|
||||||
label: 'exit',
|
|
||||||
[`${measurement}`]: `${size}px`,
|
|
||||||
opacity: 1,
|
|
||||||
}),
|
|
||||||
exitActive: css({
|
|
||||||
label: 'exitActive',
|
|
||||||
opacity: 0,
|
|
||||||
[`${measurement}`]: 0,
|
|
||||||
transition: `opacity ${duration}ms ease-out, ${measurement} ${duration}ms ease-out`,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
@@ -42,10 +17,36 @@ type Props = {
|
|||||||
|
|
||||||
export function SlideOutTransition(props: Props) {
|
export function SlideOutTransition(props: Props) {
|
||||||
const { visible, children, duration = 250, horizontal, size } = props;
|
const { visible, children, duration = 250, horizontal, size } = props;
|
||||||
const styles = getStyles(duration, horizontal ? 'width' : 'height', size);
|
const styles = useStyles2(getStyles, duration, horizontal ? 'width' : 'height', size);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CSSTransition in={visible} mountOnEnter={true} unmountOnExit={true} timeout={duration} classNames={styles}>
|
<CSSTransition in={visible} mountOnEnter={true} unmountOnExit={true} timeout={duration} classNames={styles}>
|
||||||
{children}
|
{children}
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getStyles = (_theme: GrafanaTheme2, duration: number, measurement: 'width' | 'height', size: number) => ({
|
||||||
|
enter: css({
|
||||||
|
label: 'enter',
|
||||||
|
[`${measurement}`]: 0,
|
||||||
|
opacity: 0,
|
||||||
|
}),
|
||||||
|
enterActive: css({
|
||||||
|
label: 'enterActive',
|
||||||
|
[`${measurement}`]: `${size}px`,
|
||||||
|
opacity: 1,
|
||||||
|
transition: `opacity ${duration}ms ease-out, ${measurement} ${duration}ms ease-out`,
|
||||||
|
}),
|
||||||
|
exit: css({
|
||||||
|
label: 'exit',
|
||||||
|
[`${measurement}`]: `${size}px`,
|
||||||
|
opacity: 1,
|
||||||
|
}),
|
||||||
|
exitActive: css({
|
||||||
|
label: 'exitActive',
|
||||||
|
opacity: 0,
|
||||||
|
[`${measurement}`]: 0,
|
||||||
|
transition: `opacity ${duration}ms ease-out, ${measurement} ${duration}ms ease-out`,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { GraphSeriesValue } from '@grafana/data';
|
import { GrafanaTheme2, GraphSeriesValue } from '@grafana/data';
|
||||||
import { LegendDisplayMode, LegendPlacement } from '@grafana/schema';
|
import { LegendDisplayMode, LegendPlacement } from '@grafana/schema';
|
||||||
|
|
||||||
import { CustomScrollbar } from '../../components/CustomScrollbar/CustomScrollbar';
|
import { CustomScrollbar } from '../../components/CustomScrollbar/CustomScrollbar';
|
||||||
import { VizLegend } from '../../components/VizLegend/VizLegend';
|
import { VizLegend } from '../../components/VizLegend/VizLegend';
|
||||||
import { VizLegendItem } from '../../components/VizLegend/types';
|
import { VizLegendItem } from '../../components/VizLegend/types';
|
||||||
import { stylesFactory } from '../../themes';
|
import { useStyles2 } from '../../themes';
|
||||||
|
|
||||||
import { Graph, GraphProps } from './Graph';
|
import { Graph, GraphProps } from './Graph';
|
||||||
|
|
||||||
@@ -25,21 +25,6 @@ export interface GraphWithLegendProps extends GraphProps {
|
|||||||
onToggleSort: (sortBy: string) => void;
|
onToggleSort: (sortBy: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getGraphWithLegendStyles = stylesFactory(({ placement }: GraphWithLegendProps) => ({
|
|
||||||
wrapper: css({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: placement === 'bottom' ? 'column' : 'row',
|
|
||||||
}),
|
|
||||||
graphContainer: css({
|
|
||||||
minHeight: '65%',
|
|
||||||
flexGrow: 1,
|
|
||||||
}),
|
|
||||||
legendContainer: css({
|
|
||||||
padding: '10px 0',
|
|
||||||
maxHeight: placement === 'bottom' ? '35%' : 'none',
|
|
||||||
}),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const shouldHideLegendItem = (data: GraphSeriesValue[][], hideEmpty = false, hideZero = false) => {
|
const shouldHideLegendItem = (data: GraphSeriesValue[][], hideEmpty = false, hideZero = false) => {
|
||||||
const isZeroOnlySeries = data.reduce((acc, current) => acc + (current[1] || 0), 0) === 0;
|
const isZeroOnlySeries = data.reduce((acc, current) => acc + (current[1] || 0), 0) === 0;
|
||||||
const isNullOnlySeries = !data.reduce((acc, current) => acc && current[1] !== null, true);
|
const isNullOnlySeries = !data.reduce((acc, current) => acc && current[1] !== null, true);
|
||||||
@@ -72,7 +57,7 @@ export const GraphWithLegend = (props: GraphWithLegendProps) => {
|
|||||||
children,
|
children,
|
||||||
ariaLabel,
|
ariaLabel,
|
||||||
} = props;
|
} = props;
|
||||||
const { graphContainer, wrapper, legendContainer } = getGraphWithLegendStyles(props);
|
const { graphContainer, wrapper, legendContainer } = useStyles2(getGraphWithLegendStyles, props.placement);
|
||||||
|
|
||||||
const legendItems = series.reduce<VizLegendItem[]>((acc, s) => {
|
const legendItems = series.reduce<VizLegendItem[]>((acc, s) => {
|
||||||
return shouldHideLegendItem(s.data, hideEmpty, hideZero)
|
return shouldHideLegendItem(s.data, hideEmpty, hideZero)
|
||||||
@@ -130,3 +115,18 @@ export const GraphWithLegend = (props: GraphWithLegendProps) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getGraphWithLegendStyles = (_theme: GrafanaTheme2, placement: LegendPlacement) => ({
|
||||||
|
wrapper: css({
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: placement === 'bottom' ? 'column' : 'row',
|
||||||
|
}),
|
||||||
|
graphContainer: css({
|
||||||
|
minHeight: '65%',
|
||||||
|
flexGrow: 1,
|
||||||
|
}),
|
||||||
|
legendContainer: css({
|
||||||
|
padding: '10px 0',
|
||||||
|
maxHeight: placement === 'bottom' ? '35%' : 'none',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { ErrorInfo, useEffect } from 'react';
|
|||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
import { locationUtil, PageLayoutType } from '@grafana/data';
|
import { locationUtil, PageLayoutType } from '@grafana/data';
|
||||||
import { Button, ErrorWithStack, stylesFactory } from '@grafana/ui';
|
import { Button, ErrorWithStack, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { Page } from '../components/Page/Page';
|
import { Page } from '../components/Page/Page';
|
||||||
|
|
||||||
@@ -15,6 +15,7 @@ interface Props {
|
|||||||
export function GrafanaRouteError({ error, errorInfo }: Props) {
|
export function GrafanaRouteError({ error, errorInfo }: Props) {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const isChunkLoadingError = error?.name === 'ChunkLoadError';
|
const isChunkLoadingError = error?.name === 'ChunkLoadError';
|
||||||
|
const style = useStyles2(getStyles);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Auto reload page 1 time if we have a chunk load error
|
// Auto reload page 1 time if we have a chunk load error
|
||||||
@@ -27,7 +28,7 @@ export function GrafanaRouteError({ error, errorInfo }: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Page navId="error" layout={PageLayoutType.Canvas}>
|
<Page navId="error" layout={PageLayoutType.Canvas}>
|
||||||
<div className={getStyles()}>
|
<div className={style}>
|
||||||
{isChunkLoadingError && (
|
{isChunkLoadingError && (
|
||||||
<div>
|
<div>
|
||||||
<h2>Unable to find application file</h2>
|
<h2>Unable to find application file</h2>
|
||||||
@@ -50,9 +51,7 @@ export function GrafanaRouteError({ error, errorInfo }: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStyles = stylesFactory(() => {
|
const getStyles = () => css`
|
||||||
return css`
|
width: 500px;
|
||||||
width: 500px;
|
margin: 64px auto;
|
||||||
margin: 64px auto;
|
`;
|
||||||
`;
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Modal, stylesFactory } from '@grafana/ui';
|
import { Modal, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { OnRowOptionsUpdate, RowOptionsForm } from './RowOptionsForm';
|
import { OnRowOptionsUpdate, RowOptionsForm } from './RowOptionsForm';
|
||||||
|
|
||||||
@@ -14,7 +14,8 @@ export interface RowOptionsModalProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const RowOptionsModal = ({ repeat, title, onDismiss, onUpdate, warning }: RowOptionsModalProps) => {
|
export const RowOptionsModal = ({ repeat, title, onDismiss, onUpdate, warning }: RowOptionsModalProps) => {
|
||||||
const styles = getStyles();
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={true} title="Row options" icon="copy" onDismiss={onDismiss} className={styles.modal}>
|
<Modal isOpen={true} title="Row options" icon="copy" onDismiss={onDismiss} className={styles.modal}>
|
||||||
<RowOptionsForm repeat={repeat} title={title} onCancel={onDismiss} onUpdate={onUpdate} warning={warning} />
|
<RowOptionsForm repeat={repeat} title={title} onCancel={onDismiss} onUpdate={onUpdate} warning={warning} />
|
||||||
@@ -22,11 +23,9 @@ export const RowOptionsModal = ({ repeat, title, onDismiss, onUpdate, warning }:
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory(() => {
|
const getStyles = () => ({
|
||||||
return {
|
modal: css`
|
||||||
modal: css`
|
label: RowOptionsModal;
|
||||||
label: RowOptionsModal;
|
width: 500px;
|
||||||
width: 500px;
|
`,
|
||||||
`,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import AutoSizer from 'react-virtualized-auto-sizer';
|
|||||||
import { areEqual, FixedSizeGrid as Grid } from 'react-window';
|
import { areEqual, FixedSizeGrid as Grid } from 'react-window';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { useTheme2, stylesFactory } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
import { SanitizedSVG } from 'app/core/components/SVG/SanitizedSVG';
|
import { SanitizedSVG } from 'app/core/components/SVG/SanitizedSVG';
|
||||||
|
|
||||||
import { ResourceItem } from './FolderPickerTab';
|
import { ResourceItem } from './FolderPickerTab';
|
||||||
@@ -26,8 +26,7 @@ const MemoizedCell = memo(function Cell(props: CellProps) {
|
|||||||
const { cards, columnCount, onChange, selected } = data;
|
const { cards, columnCount, onChange, selected } = data;
|
||||||
const singleColumnIndex = columnIndex + rowIndex * columnCount;
|
const singleColumnIndex = columnIndex + rowIndex * columnCount;
|
||||||
const card = cards[singleColumnIndex];
|
const card = cards[singleColumnIndex];
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles);
|
||||||
const styles = getStyles(theme);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={style}>
|
<div style={style}>
|
||||||
@@ -56,53 +55,6 @@ const MemoizedCell = memo(function Cell(props: CellProps) {
|
|||||||
);
|
);
|
||||||
}, areEqual);
|
}, areEqual);
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
|
||||||
return {
|
|
||||||
card: css`
|
|
||||||
display: inline-block;
|
|
||||||
width: 90px;
|
|
||||||
height: 90px;
|
|
||||||
margin: 0.75rem;
|
|
||||||
margin-left: 15px;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
background-color: transparent;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding-top: 6px;
|
|
||||||
:hover {
|
|
||||||
border-color: ${theme.colors.action.hover};
|
|
||||||
box-shadow: ${theme.shadows.z2};
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
selected: css`
|
|
||||||
border: 2px solid ${theme.colors.primary.main};
|
|
||||||
:hover {
|
|
||||||
border-color: ${theme.colors.primary.main};
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
img: css`
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
object-fit: cover;
|
|
||||||
vertical-align: middle;
|
|
||||||
fill: ${theme.colors.text.primary};
|
|
||||||
`,
|
|
||||||
text: css`
|
|
||||||
color: ${theme.colors.text.primary};
|
|
||||||
white-space: nowrap;
|
|
||||||
font-size: 12px;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
display: block;
|
|
||||||
overflow: hidden;
|
|
||||||
`,
|
|
||||||
grid: css`
|
|
||||||
border: 1px solid ${theme.colors.border.medium};
|
|
||||||
`,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
interface CardProps {
|
interface CardProps {
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
cards: ResourceItem[];
|
cards: ResourceItem[];
|
||||||
@@ -111,8 +63,7 @@ interface CardProps {
|
|||||||
|
|
||||||
export const ResourceCards = (props: CardProps) => {
|
export const ResourceCards = (props: CardProps) => {
|
||||||
const { onChange, cards, value } = props;
|
const { onChange, cards, value } = props;
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles);
|
||||||
const styles = getStyles(theme);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AutoSizer defaultWidth={680}>
|
<AutoSizer defaultWidth={680}>
|
||||||
@@ -139,3 +90,48 @@ export const ResourceCards = (props: CardProps) => {
|
|||||||
</AutoSizer>
|
</AutoSizer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
|
card: css`
|
||||||
|
display: inline-block;
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
margin: 0.75rem;
|
||||||
|
margin-left: 15px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding-top: 6px;
|
||||||
|
:hover {
|
||||||
|
border-color: ${theme.colors.action.hover};
|
||||||
|
box-shadow: ${theme.shadows.z2};
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
selected: css`
|
||||||
|
border: 2px solid ${theme.colors.primary.main};
|
||||||
|
:hover {
|
||||||
|
border-color: ${theme.colors.primary.main};
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
img: css`
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
object-fit: cover;
|
||||||
|
vertical-align: middle;
|
||||||
|
fill: ${theme.colors.text.primary};
|
||||||
|
`,
|
||||||
|
text: css`
|
||||||
|
color: ${theme.colors.text.primary};
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 12px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
`,
|
||||||
|
grid: css`
|
||||||
|
border: 1px solid ${theme.colors.border.medium};
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
|||||||
@@ -5,51 +5,7 @@ import React from 'react';
|
|||||||
|
|
||||||
// Services & Utils
|
// Services & Utils
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { stylesFactory, useTheme2 } from '@grafana/ui';
|
import { useStyles2, useTheme2 } from '@grafana/ui';
|
||||||
|
|
||||||
// Types
|
|
||||||
|
|
||||||
const drawerSlide = (theme: GrafanaTheme2) => keyframes`
|
|
||||||
0% {
|
|
||||||
transform: translateY(${theme.components.horizontalDrawer.defaultHeight}px);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
transform: translateY(0px);
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
|
||||||
return {
|
|
||||||
container: css`
|
|
||||||
position: fixed !important;
|
|
||||||
bottom: 0;
|
|
||||||
background: ${theme.colors.background.primary};
|
|
||||||
border-top: 1px solid ${theme.colors.border.weak};
|
|
||||||
margin: ${theme.spacing(0, -2, 0, -2)};
|
|
||||||
box-shadow: ${theme.shadows.z3};
|
|
||||||
z-index: ${theme.zIndex.navbarFixed};
|
|
||||||
`,
|
|
||||||
drawerActive: css`
|
|
||||||
opacity: 1;
|
|
||||||
animation: 0.5s ease-out ${drawerSlide(theme)};
|
|
||||||
`,
|
|
||||||
rzHandle: css`
|
|
||||||
background: ${theme.colors.secondary.main};
|
|
||||||
transition: 0.3s background ease-in-out;
|
|
||||||
position: relative;
|
|
||||||
width: 200px !important;
|
|
||||||
height: 7px !important;
|
|
||||||
left: calc(50% - 100px) !important;
|
|
||||||
top: -4px !important;
|
|
||||||
cursor: grab;
|
|
||||||
border-radius: ${theme.shape.radius.pill};
|
|
||||||
&:hover {
|
|
||||||
background: ${theme.colors.secondary.shade};
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
width: number;
|
width: number;
|
||||||
@@ -60,7 +16,7 @@ export interface Props {
|
|||||||
export function ExploreDrawer(props: Props) {
|
export function ExploreDrawer(props: Props) {
|
||||||
const { width, children, onResize } = props;
|
const { width, children, onResize } = props;
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
const styles = getStyles(theme);
|
const styles = useStyles2(getStyles);
|
||||||
const drawerWidth = `${width + 31.5}px`;
|
const drawerWidth = `${width + 31.5}px`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -87,3 +43,43 @@ export function ExploreDrawer(props: Props) {
|
|||||||
</Resizable>
|
</Resizable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const drawerSlide = (theme: GrafanaTheme2) => keyframes`
|
||||||
|
0% {
|
||||||
|
transform: translateY(${theme.components.horizontalDrawer.defaultHeight}px);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateY(0px);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
|
container: css`
|
||||||
|
position: fixed !important;
|
||||||
|
bottom: 0;
|
||||||
|
background: ${theme.colors.background.primary};
|
||||||
|
border-top: 1px solid ${theme.colors.border.weak};
|
||||||
|
margin: ${theme.spacing(0, -2, 0, -2)};
|
||||||
|
box-shadow: ${theme.shadows.z3};
|
||||||
|
z-index: ${theme.zIndex.navbarFixed};
|
||||||
|
`,
|
||||||
|
drawerActive: css`
|
||||||
|
opacity: 1;
|
||||||
|
animation: 0.5s ease-out ${drawerSlide(theme)};
|
||||||
|
`,
|
||||||
|
rzHandle: css`
|
||||||
|
background: ${theme.colors.secondary.main};
|
||||||
|
transition: 0.3s background ease-in-out;
|
||||||
|
position: relative;
|
||||||
|
width: 200px !important;
|
||||||
|
height: 7px !important;
|
||||||
|
left: calc(50% - 100px) !important;
|
||||||
|
top: -4px !important;
|
||||||
|
cursor: grab;
|
||||||
|
border-radius: ${theme.shape.radius.pill};
|
||||||
|
&:hover {
|
||||||
|
background: ${theme.colors.secondary.shade};
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import React, { useMemo, useState, useEffect } from 'react';
|
import React, { useMemo, useState, useEffect } from 'react';
|
||||||
|
|
||||||
import { StandardEditorProps, SelectableValue, GrafanaTheme2 } from '@grafana/data';
|
import { StandardEditorProps, SelectableValue } from '@grafana/data';
|
||||||
import { Alert, Select, stylesFactory, useTheme2 } from '@grafana/ui';
|
import { Alert, Select, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { COUNTRIES_GAZETTEER_PATH, Gazetteer, getGazetteer } from '../gazetteer/gazetteer';
|
import { COUNTRIES_GAZETTEER_PATH, Gazetteer, getGazetteer } from '../gazetteer/gazetteer';
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ export const GazetteerPathEditor = ({
|
|||||||
context,
|
context,
|
||||||
item,
|
item,
|
||||||
}: StandardEditorProps<string, GazetteerPathEditorConfigSettings>) => {
|
}: StandardEditorProps<string, GazetteerPathEditorConfigSettings>) => {
|
||||||
const styles = getStyles(useTheme2());
|
const styles = useStyles2(getStyles);
|
||||||
const [gaz, setGaz] = useState<Gazetteer>();
|
const [gaz, setGaz] = useState<Gazetteer>();
|
||||||
const settings = item.settings;
|
const settings = item.settings;
|
||||||
|
|
||||||
@@ -86,17 +86,15 @@ export const GazetteerPathEditor = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getStyles = () => ({
|
||||||
return {
|
keys: css`
|
||||||
keys: css`
|
margin-top: 4px;
|
||||||
margin-top: 4px;
|
text-overflow: ellipsis;
|
||||||
text-overflow: ellipsis;
|
overflow: hidden;
|
||||||
overflow: hidden;
|
white-space: nowrap;
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
> span {
|
> span {
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
QueryResultMetaStat,
|
QueryResultMetaStat,
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { stylesFactory, useTheme2 } from '@grafana/ui';
|
import { useStyles2, useTheme2 } from '@grafana/ui';
|
||||||
|
|
||||||
interface InspectStatsTableProps {
|
interface InspectStatsTableProps {
|
||||||
timeZone: TimeZone;
|
timeZone: TimeZone;
|
||||||
@@ -19,7 +19,7 @@ interface InspectStatsTableProps {
|
|||||||
|
|
||||||
export const InspectStatsTable = ({ timeZone, name, stats }: InspectStatsTableProps) => {
|
export const InspectStatsTable = ({ timeZone, name, stats }: InspectStatsTableProps) => {
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
const styles = getStyles(theme);
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
if (!stats || !stats.length) {
|
if (!stats || !stats.length) {
|
||||||
return null;
|
return null;
|
||||||
@@ -56,13 +56,11 @@ function formatStat(stat: QueryResultMetaStat, timeZone: TimeZone, theme: Grafan
|
|||||||
return formattedValueToString(display(stat.value));
|
return formattedValueToString(display(stat.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
return {
|
wrapper: css`
|
||||||
wrapper: css`
|
padding-bottom: ${theme.spacing(2)};
|
||||||
padding-bottom: ${theme.spacing(2)};
|
`,
|
||||||
`,
|
cell: css`
|
||||||
cell: css`
|
text-align: right;
|
||||||
text-align: right;
|
`,
|
||||||
`,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,16 +2,15 @@ import { css } from '@emotion/css';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { stylesFactory, useTheme2 } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
type Props = {
|
interface Props {
|
||||||
name: string;
|
name: string;
|
||||||
traceIds: string[];
|
traceIds: string[];
|
||||||
};
|
}
|
||||||
|
|
||||||
export const InspectStatsTraceIdsTable = ({ name, traceIds }: Props) => {
|
export const InspectStatsTraceIdsTable = ({ name, traceIds }: Props) => {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles);
|
||||||
const styles = getStyles(theme);
|
|
||||||
|
|
||||||
if (traceIds.length === 0) {
|
if (traceIds.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -35,13 +34,11 @@ export const InspectStatsTraceIdsTable = ({ name, traceIds }: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
return {
|
wrapper: css`
|
||||||
wrapper: css`
|
padding-bottom: ${theme.spacing(2)};
|
||||||
padding-bottom: ${theme.spacing(2)};
|
`,
|
||||||
`,
|
cell: css`
|
||||||
cell: css`
|
text-align: right;
|
||||||
text-align: right;
|
`,
|
||||||
`,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { locationService } from '@grafana/runtime';
|
import { locationService } from '@grafana/runtime';
|
||||||
import { Button, Modal, stylesFactory, useStyles2 } from '@grafana/ui';
|
import { Button, Modal, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { dashboardWatcher } from './dashboardWatcher';
|
import { dashboardWatcher } from './dashboardWatcher';
|
||||||
import { DashboardEvent, DashboardEventAction } from './types';
|
import { DashboardEvent, DashboardEventAction } from './types';
|
||||||
@@ -50,12 +50,10 @@ export function DashboardChangedModal({ onDismiss, event }: Props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
return {
|
modal: css({ width: '600px' }),
|
||||||
modal: css({ width: '600px' }),
|
description: css({
|
||||||
description: css({
|
color: theme.colors.text.secondary,
|
||||||
color: theme.colors.text.secondary,
|
paddingBottom: theme.spacing(1),
|
||||||
paddingBottom: theme.spacing(1),
|
}),
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { Button, InfoBox, Portal, stylesFactory, useTheme2 } from '@grafana/ui';
|
import { Button, InfoBox, Portal, useStyles2, useTheme2 } from '@grafana/ui';
|
||||||
import { getModalStyles } from '@grafana/ui/src/components/Modal/getModalStyles';
|
import { getModalStyles } from '@grafana/ui/src/components/Modal/getModalStyles';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -10,9 +10,8 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const TokenRevokedModal = (props: Props) => {
|
export const TokenRevokedModal = (props: Props) => {
|
||||||
|
const styles = useStyles2(getStyles);
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
|
|
||||||
const styles = getStyles(theme);
|
|
||||||
const modalStyles = getModalStyles(theme);
|
const modalStyles = getModalStyles(theme);
|
||||||
|
|
||||||
const showMaxConcurrentSessions = Boolean(props.maxConcurrentSessions);
|
const showMaxConcurrentSessions = Boolean(props.maxConcurrentSessions);
|
||||||
@@ -51,17 +50,15 @@ export const TokenRevokedModal = (props: Props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
return {
|
infobox: css`
|
||||||
infobox: css`
|
margin-bottom: 0;
|
||||||
margin-bottom: 0;
|
`,
|
||||||
`,
|
text: css`
|
||||||
text: css`
|
margin: ${theme.spacing(1, 0, 2)};
|
||||||
margin: ${theme.spacing(1, 0, 2)};
|
`,
|
||||||
`,
|
backdrop: css`
|
||||||
backdrop: css`
|
background-color: ${theme.colors.background.canvas};
|
||||||
background-color: ${theme.colors.background.canvas};
|
opacity: 0.8;
|
||||||
opacity: 0.8;
|
`,
|
||||||
`,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { stylesFactory, useTheme2 } from '@grafana/ui';
|
import { useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
export interface SpaceProps {
|
export interface SpaceProps {
|
||||||
v?: number;
|
v?: number;
|
||||||
@@ -11,8 +11,7 @@ export interface SpaceProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const Space = (props: SpaceProps) => {
|
export const Space = (props: SpaceProps) => {
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles, props);
|
||||||
const styles = getStyles(theme, props);
|
|
||||||
|
|
||||||
return <span className={cx(styles.wrapper)} />;
|
return <span className={cx(styles.wrapper)} />;
|
||||||
};
|
};
|
||||||
@@ -23,7 +22,7 @@ Space.defaultProps = {
|
|||||||
layout: 'block',
|
layout: 'block',
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2, props: SpaceProps) => ({
|
const getStyles = (theme: GrafanaTheme2, props: SpaceProps) => ({
|
||||||
wrapper: css([
|
wrapper: css([
|
||||||
{
|
{
|
||||||
paddingRight: theme.spacing(props.h ?? 0),
|
paddingRight: theme.spacing(props.h ?? 0),
|
||||||
@@ -36,4 +35,4 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, props: SpaceProps) => ({
|
|||||||
display: 'block',
|
display: 'block',
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
}));
|
});
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { useState } from 'react';
|
|||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { AccessoryButton, InputGroup } from '@grafana/experimental';
|
import { AccessoryButton, InputGroup } from '@grafana/experimental';
|
||||||
import { Input, stylesFactory, useTheme2 } from '@grafana/ui';
|
import { Input, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { MultiFilterCondition } from './MultiFilter';
|
import { MultiFilterCondition } from './MultiFilter';
|
||||||
|
|
||||||
@@ -17,8 +17,7 @@ export interface Props {
|
|||||||
export const MultiFilterItem = ({ filter, onChange, onDelete, keyPlaceholder }: Props) => {
|
export const MultiFilterItem = ({ filter, onChange, onDelete, keyPlaceholder }: Props) => {
|
||||||
const [localKey, setLocalKey] = useState(filter.key || '');
|
const [localKey, setLocalKey] = useState(filter.key || '');
|
||||||
const [localValue, setLocalValue] = useState(filter.value?.join(', ') || '');
|
const [localValue, setLocalValue] = useState(filter.value?.join(', ') || '');
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getOperatorStyles);
|
||||||
const styles = getOperatorStyles(theme);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-testid="cloudwatch-multifilter-item">
|
<div data-testid="cloudwatch-multifilter-item">
|
||||||
@@ -59,9 +58,9 @@ export const MultiFilterItem = ({ filter, onChange, onDelete, keyPlaceholder }:
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOperatorStyles = stylesFactory((theme: GrafanaTheme2) => ({
|
const getOperatorStyles = (theme: GrafanaTheme2) => ({
|
||||||
root: css({
|
root: css({
|
||||||
padding: theme.spacing(0, 1),
|
padding: theme.spacing(0, 1),
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
}),
|
}),
|
||||||
}));
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useAsyncFn } from 'react-use';
|
|||||||
|
|
||||||
import { GrafanaTheme2, SelectableValue, toOption } from '@grafana/data';
|
import { GrafanaTheme2, SelectableValue, toOption } from '@grafana/data';
|
||||||
import { AccessoryButton, InputGroup } from '@grafana/experimental';
|
import { AccessoryButton, InputGroup } from '@grafana/experimental';
|
||||||
import { Select, stylesFactory, useTheme2 } from '@grafana/ui';
|
import { Select, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { CloudWatchDatasource } from '../../../datasource';
|
import { CloudWatchDatasource } from '../../../datasource';
|
||||||
import { Dimensions, MetricStat } from '../../../types';
|
import { Dimensions, MetricStat } from '../../../types';
|
||||||
@@ -76,8 +76,7 @@ export const FilterItem = ({
|
|||||||
metricName,
|
metricName,
|
||||||
accountId,
|
accountId,
|
||||||
]);
|
]);
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getOperatorStyles);
|
||||||
const styles = getOperatorStyles(theme);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-testid="cloudwatch-dimensions-filter-item">
|
<div data-testid="cloudwatch-dimensions-filter-item">
|
||||||
@@ -119,9 +118,9 @@ export const FilterItem = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOperatorStyles = stylesFactory((theme: GrafanaTheme2) => ({
|
const getOperatorStyles = (theme: GrafanaTheme2) => ({
|
||||||
root: css({
|
root: css({
|
||||||
padding: theme.spacing(0, 1),
|
padding: theme.spacing(0, 1),
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
}),
|
}),
|
||||||
}));
|
});
|
||||||
|
|||||||
@@ -6,50 +6,28 @@ import { DataSourceInstanceSettings, VariableSuggestion } from '@grafana/data';
|
|||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
DataLinkInput,
|
DataLinkInput,
|
||||||
stylesFactory,
|
|
||||||
InlineField,
|
InlineField,
|
||||||
InlineSwitch,
|
InlineSwitch,
|
||||||
InlineFieldRow,
|
InlineFieldRow,
|
||||||
InlineLabel,
|
InlineLabel,
|
||||||
Input,
|
Input,
|
||||||
|
useStyles2,
|
||||||
} from '@grafana/ui';
|
} from '@grafana/ui';
|
||||||
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
|
import { DataSourcePicker } from 'app/features/datasources/components/picker/DataSourcePicker';
|
||||||
|
|
||||||
import { DataLinkConfig } from '../types';
|
import { DataLinkConfig } from '../types';
|
||||||
|
|
||||||
const getStyles = stylesFactory(() => ({
|
interface Props {
|
||||||
firstRow: css`
|
|
||||||
display: flex;
|
|
||||||
`,
|
|
||||||
nameField: css`
|
|
||||||
flex: 2;
|
|
||||||
`,
|
|
||||||
regexField: css`
|
|
||||||
flex: 3;
|
|
||||||
`,
|
|
||||||
row: css`
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
`,
|
|
||||||
urlField: css`
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
`,
|
|
||||||
urlDisplayLabelField: css`
|
|
||||||
flex: 1;
|
|
||||||
`,
|
|
||||||
}));
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
value: DataLinkConfig;
|
value: DataLinkConfig;
|
||||||
onChange: (value: DataLinkConfig) => void;
|
onChange: (value: DataLinkConfig) => void;
|
||||||
onDelete: () => void;
|
onDelete: () => void;
|
||||||
suggestions: VariableSuggestion[];
|
suggestions: VariableSuggestion[];
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export const DataLink = (props: Props) => {
|
export const DataLink = (props: Props) => {
|
||||||
const { value, onChange, onDelete, suggestions, className } = props;
|
const { value, onChange, onDelete, suggestions, className } = props;
|
||||||
const styles = getStyles();
|
const styles = useStyles2(getStyles);
|
||||||
const [showInternalLink, setShowInternalLink] = useInternalLink(value.datasourceUid);
|
const [showInternalLink, setShowInternalLink] = useInternalLink(value.datasourceUid);
|
||||||
|
|
||||||
const handleChange = (field: keyof typeof value) => (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleChange = (field: keyof typeof value) => (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
@@ -173,3 +151,26 @@ function useInternalLink(datasourceUid?: string): [boolean, Dispatch<SetStateAct
|
|||||||
|
|
||||||
return [showInternalLink, setShowInternalLink];
|
return [showInternalLink, setShowInternalLink];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getStyles = () => ({
|
||||||
|
firstRow: css`
|
||||||
|
display: flex;
|
||||||
|
`,
|
||||||
|
nameField: css`
|
||||||
|
flex: 2;
|
||||||
|
`,
|
||||||
|
regexField: css`
|
||||||
|
flex: 3;
|
||||||
|
`,
|
||||||
|
row: css`
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
`,
|
||||||
|
urlField: css`
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
`,
|
||||||
|
urlDisplayLabelField: css`
|
||||||
|
flex: 1;
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { css } from '@emotion/css';
|
|||||||
import React, { ComponentProps } from 'react';
|
import React, { ComponentProps } from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { Field, Icon, PopoverContent, ReactUtils, stylesFactory, Tooltip, useTheme2 } from '@grafana/ui';
|
import { Field, Icon, PopoverContent, ReactUtils, Tooltip, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
interface EditorFieldProps extends ComponentProps<typeof Field> {
|
interface EditorFieldProps extends ComponentProps<typeof Field> {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -15,8 +15,7 @@ interface EditorFieldProps extends ComponentProps<typeof Field> {
|
|||||||
export const EditorField = (props: EditorFieldProps) => {
|
export const EditorField = (props: EditorFieldProps) => {
|
||||||
const { label, optional, tooltip, children, width, ...fieldProps } = props;
|
const { label, optional, tooltip, children, width, ...fieldProps } = props;
|
||||||
|
|
||||||
const theme = useTheme2();
|
const styles = useStyles2(getStyles, width);
|
||||||
const styles = getStyles(theme, width);
|
|
||||||
|
|
||||||
// Null check for backward compatibility
|
// Null check for backward compatibility
|
||||||
const childInputId = fieldProps?.htmlFor || ReactUtils?.getChildId(children);
|
const childInputId = fieldProps?.htmlFor || ReactUtils?.getChildId(children);
|
||||||
@@ -45,32 +44,30 @@ export const EditorField = (props: EditorFieldProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme2, width?: number | string) => {
|
const getStyles = (theme: GrafanaTheme2, width?: number | string) => ({
|
||||||
return {
|
space: css({
|
||||||
space: css({
|
paddingRight: theme.spacing(0),
|
||||||
paddingRight: theme.spacing(0),
|
paddingBottom: theme.spacing(0.5),
|
||||||
paddingBottom: theme.spacing(0.5),
|
}),
|
||||||
}),
|
root: css({
|
||||||
root: css({
|
minWidth: theme.spacing(width ?? 0),
|
||||||
minWidth: theme.spacing(width ?? 0),
|
}),
|
||||||
}),
|
label: css({
|
||||||
label: css({
|
fontSize: 12,
|
||||||
fontSize: 12,
|
fontWeight: theme.typography.fontWeightMedium,
|
||||||
fontWeight: theme.typography.fontWeightMedium,
|
}),
|
||||||
}),
|
optional: css({
|
||||||
optional: css({
|
fontStyle: 'italic',
|
||||||
fontStyle: 'italic',
|
color: theme.colors.text.secondary,
|
||||||
color: theme.colors.text.secondary,
|
}),
|
||||||
}),
|
field: css({
|
||||||
field: css({
|
marginBottom: 0, // GrafanaUI/Field has a bottom margin which we must remove
|
||||||
marginBottom: 0, // GrafanaUI/Field has a bottom margin which we must remove
|
}),
|
||||||
}),
|
icon: css({
|
||||||
icon: css({
|
color: theme.colors.text.secondary,
|
||||||
color: theme.colors.text.secondary,
|
marginLeft: theme.spacing(1),
|
||||||
marginLeft: theme.spacing(1),
|
':hover': {
|
||||||
':hover': {
|
color: theme.colors.text.primary,
|
||||||
color: theme.colors.text.primary,
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user