@grafana/ui
Version:
Grafana Components Library
1,566 lines (1,532 loc) • 1.38 MB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var jsxRuntime = require('react/jsx-runtime');
var css = require('@emotion/css');
var classNames = require('classnames');
var React = require('react');
var SVG = require('react-inlinesvg');
var data = require('@grafana/data');
var hoistNonReactStatics = require('hoist-non-react-statics');
var memoize = require('micro-memoize');
var react = require('@floating-ui/react');
var e2eSelectors = require('@grafana/e2e-selectors');
var ReactDOM = require('react-dom');
var ReactSelect = require('react-select');
var ReactAsyncSelect = require('react-select/async');
var Creatable = require('react-select/creatable');
var i18n = require('@grafana/i18n');
var reactTransitionGroup = require('react-transition-group');
var lodash = require('lodash');
var tinycolor = require('tinycolor2');
var schema = require('@grafana/schema');
var reactUse = require('react-use');
var AsyncCreatable = require('react-select/async-creatable');
var reactWindow = require('react-window');
var ReactDOMServer = require('react-dom/server');
var Scrollbars = require('react-custom-scrollbars-2');
var RCCascader = require('rc-cascader');
var dialog = require('@react-aria/dialog');
var focus = require('@react-aria/focus');
var overlays = require('@react-aria/overlays');
var reactColorful = require('react-colorful');
var dateFns = require('date-fns');
var reactVirtual = require('@tanstack/react-virtual');
var downshift = require('downshift');
var Calendar = require('react-calendar');
var uuid = require('uuid');
var RcPicker = require('rc-picker');
var generateConfig = require('rc-picker/lib/generate/moment');
var locale = require('rc-picker/lib/locale/en_US');
require('rc-picker/assets/index.css');
var reactTable = require('react-table');
var Skeleton = require('react-loading-skeleton');
var reactHookForm = require('react-hook-form');
var Plain = require('slate-plain-serializer');
var slateReact = require('slate-react');
var isHotkey = require('is-hotkey');
var slate = require('slate');
var calculateSize = require('calculate-size');
var Highlighter = require('react-highlight-words');
var reactRouterDomV5Compat = require('react-router-dom-v5-compat');
var rxjs = require('rxjs');
var operators = require('rxjs/operators');
var RcDrawer = require('rc-drawer');
require('rc-drawer/assets/index.css');
var WKT = require('ol/format/WKT');
var geom = require('ol/geom');
var uPlot = require('uplot');
require('uplot/dist/uPlot.min.css');
var $ = require('jquery');
var Prism = require('prismjs');
var immutable = require('immutable');
var dnd = require('@hello-pangea/dnd');
var faroWebSdk = require('@grafana/faro-web-sdk');
var react$1 = require('@emotion/react');
var SliderComponent = require('rc-slider');
require('rc-slider/assets/index.css');
var Tooltip$1 = require('rc-tooltip');
var reactDropzone = require('react-dropzone');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
function _interopNamespaceCompat(e) {
if (e && typeof e === 'object' && 'default' in e) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var classNames__default = /*#__PURE__*/_interopDefaultCompat(classNames);
var React__namespace = /*#__PURE__*/_interopNamespaceCompat(React);
var SVG__default = /*#__PURE__*/_interopDefaultCompat(SVG);
var hoistNonReactStatics__default = /*#__PURE__*/_interopDefaultCompat(hoistNonReactStatics);
var memoize__default = /*#__PURE__*/_interopDefaultCompat(memoize);
var ReactDOM__default = /*#__PURE__*/_interopDefaultCompat(ReactDOM);
var ReactSelect__default = /*#__PURE__*/_interopDefaultCompat(ReactSelect);
var ReactAsyncSelect__default = /*#__PURE__*/_interopDefaultCompat(ReactAsyncSelect);
var Creatable__default = /*#__PURE__*/_interopDefaultCompat(Creatable);
var tinycolor__default = /*#__PURE__*/_interopDefaultCompat(tinycolor);
var AsyncCreatable__default = /*#__PURE__*/_interopDefaultCompat(AsyncCreatable);
var ReactDOMServer__default = /*#__PURE__*/_interopDefaultCompat(ReactDOMServer);
var Scrollbars__default = /*#__PURE__*/_interopDefaultCompat(Scrollbars);
var RCCascader__default = /*#__PURE__*/_interopDefaultCompat(RCCascader);
var Calendar__default = /*#__PURE__*/_interopDefaultCompat(Calendar);
var RcPicker__default = /*#__PURE__*/_interopDefaultCompat(RcPicker);
var generateConfig__default = /*#__PURE__*/_interopDefaultCompat(generateConfig);
var locale__default = /*#__PURE__*/_interopDefaultCompat(locale);
var Skeleton__default = /*#__PURE__*/_interopDefaultCompat(Skeleton);
var Plain__default = /*#__PURE__*/_interopDefaultCompat(Plain);
var calculateSize__default = /*#__PURE__*/_interopDefaultCompat(calculateSize);
var Highlighter__default = /*#__PURE__*/_interopDefaultCompat(Highlighter);
var RcDrawer__default = /*#__PURE__*/_interopDefaultCompat(RcDrawer);
var WKT__default = /*#__PURE__*/_interopDefaultCompat(WKT);
var uPlot__default = /*#__PURE__*/_interopDefaultCompat(uPlot);
var $__default = /*#__PURE__*/_interopDefaultCompat($);
var Prism__default = /*#__PURE__*/_interopDefaultCompat(Prism);
var SliderComponent__default = /*#__PURE__*/_interopDefaultCompat(SliderComponent);
var Tooltip__default = /*#__PURE__*/_interopDefaultCompat(Tooltip$1);
function stylesFactory(stylesCreator) {
return memoize__default.default(stylesCreator);
}
let ThemeContextMock = null;
const memoizedStyleCreators = /* @__PURE__ */ new WeakMap();
const withTheme = (Component) => {
const WithTheme = (props) => {
const ContextComponent = ThemeContextMock || data.ThemeContext;
return (
// @ts-ignore
/* @__PURE__ */ jsxRuntime.jsx(ContextComponent.Consumer, { children: (theme) => /* @__PURE__ */ jsxRuntime.jsx(Component, { ...props, theme: theme.v1 }) })
);
};
WithTheme.displayName = `WithTheme(${Component.displayName})`;
hoistNonReactStatics__default.default(WithTheme, Component);
return WithTheme;
};
const withTheme2 = (Component) => {
const WithTheme = (props) => {
const ContextComponent = ThemeContextMock || data.ThemeContext;
return (
// @ts-ignore
/* @__PURE__ */ jsxRuntime.jsx(ContextComponent.Consumer, { children: (theme) => /* @__PURE__ */ jsxRuntime.jsx(Component, { ...props, theme }) })
);
};
WithTheme.displayName = `WithTheme(${Component.displayName})`;
hoistNonReactStatics__default.default(WithTheme, Component);
return WithTheme;
};
function useTheme() {
return React.useContext(ThemeContextMock || data.ThemeContext).v1;
}
function useTheme2() {
return React.useContext(ThemeContextMock || data.ThemeContext);
}
function useStyles(getStyles) {
const theme = useTheme();
let memoizedStyleCreator = memoizedStyleCreators.get(getStyles);
if (!memoizedStyleCreator) {
memoizedStyleCreator = stylesFactory(getStyles);
memoizedStyleCreators.set(getStyles, memoizedStyleCreator);
}
return memoizedStyleCreator(theme);
}
function useStyles2(getStyles, ...additionalArguments) {
const theme = useTheme2();
if (!theme.colors.background.elevated) {
theme.colors.background.elevated = theme.colors.mode === "light" ? theme.colors.background.primary : theme.colors.background.secondary;
}
let memoizedStyleCreator = memoizedStyleCreators.get(getStyles);
if (!memoizedStyleCreator) {
memoizedStyleCreator = memoize__default.default(getStyles, { maxSize: 10 });
memoizedStyleCreators.set(getStyles, memoizedStyleCreator);
}
return memoizedStyleCreator(theme, ...additionalArguments);
}
const mockThemeContext = (theme) => {
ThemeContextMock = React__namespace.createContext(theme);
return () => {
ThemeContextMock = null;
};
};
const spin$1 = css.keyframes({
"0%": {
transform: "rotate(0deg)"
},
"100%": {
transform: "rotate(359deg)"
}
});
const alwaysMonoIcons = [
"grafana",
"favorite",
"heart-break",
"heart",
"panel-add",
"library-panel",
"circle-mono"
];
function getIconSubDir(name, type) {
if (name == null ? void 0 : name.startsWith("gf-")) {
return "custom";
} else if (alwaysMonoIcons.includes(name)) {
return "mono";
} else if (type === "default") {
return "unicons";
} else if (type === "solid") {
return "solid";
} else {
return "mono";
}
}
function getSvgSize(size) {
switch (size) {
case "xs":
return 12;
case "sm":
return 14;
case "md":
return 16;
case "lg":
return 18;
case "xl":
return 24;
case "xxl":
return 36;
case "xxxl":
return 48;
}
}
let iconRoot;
function getIconRoot() {
if (iconRoot) {
return iconRoot;
}
const grafanaPublicPath = typeof window !== "undefined" && window.__grafana_public_path__;
if (grafanaPublicPath) {
iconRoot = grafanaPublicPath + "build/img/icons/";
} else {
iconRoot = "public/build/img/icons/";
}
return iconRoot;
}
function getIconPath(name, type = "default") {
const iconRoot2 = getIconRoot();
const subDir = getIconSubDir(name, type);
return `${iconRoot2}${subDir}/${name}.svg`;
}
const getIconStyles = (theme) => {
return {
icon: css.css({
display: "inline-block",
fill: "currentColor",
flexShrink: 0,
label: "Icon",
// line-height: 0; is needed for correct icon alignment in Safari
lineHeight: 0,
verticalAlign: "middle"
}),
orange: css.css({
fill: theme.v1.palette.orange
}),
spin: css.css({
[theme.transitions.handleMotion("no-preference", "reduce")]: {
animation: `${spin$1} 2s infinite linear`
}
})
};
};
const Icon = React__namespace.forwardRef(
({ size = "md", type = "default", name, className, style, title = "", ...rest }, ref) => {
const styles = useStyles2(getIconStyles);
if (!data.isIconName(name)) {
console.warn("Icon component passed an invalid icon name", name);
}
const iconName = name === "fa fa-spinner" ? "spinner" : name;
const svgSize = getSvgSize(size);
const svgHgt = svgSize;
const svgWid = name.startsWith("gf-bar-align") ? 16 : name.startsWith("gf-interp") ? 30 : svgSize;
const svgPath = getIconPath(iconName, type);
const composedClassName = css.cx(
styles.icon,
className,
type === "mono" ? { [styles.orange]: name === "favorite" } : "",
{
[styles.spin]: iconName === "spinner"
}
);
return /* @__PURE__ */ jsxRuntime.jsx(
SVG__default.default,
{
"aria-hidden": rest.tabIndex === void 0 && !title && !rest["aria-label"] && !rest["aria-labelledby"] && !rest["aria-describedby"],
innerRef: ref,
src: svgPath,
width: svgWid,
height: svgHgt,
title,
className: composedClassName,
style,
loader: /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
className: css.cx(
css.css({
width: svgWid,
height: svgHgt
}),
composedClassName
)
}
),
...rest
}
);
}
);
Icon.displayName = "Icon";
function getPlacement(placement) {
switch (placement) {
case "auto":
return "bottom";
case "auto-start":
return "bottom-start";
case "auto-end":
return "bottom-end";
default:
return placement != null ? placement : "bottom";
}
}
function buildTooltipTheme(theme, tooltipBg, toggletipBorder, tooltipText, tooltipPadding) {
return {
arrow: css.css({
fill: tooltipBg
}),
container: css.css({
backgroundColor: tooltipBg,
borderRadius: theme.shape.radius.default,
border: `1px solid ${toggletipBorder}`,
boxShadow: theme.shadows.z2,
color: tooltipText,
fontSize: theme.typography.bodySmall.fontSize,
padding: theme.spacing(tooltipPadding.topBottom, tooltipPadding.rightLeft),
[theme.transitions.handleMotion("no-preference", "reduce")]: {
transition: "opacity 0.3s"
},
zIndex: theme.zIndex.tooltip,
maxWidth: "400px",
overflowWrap: "break-word",
"&[data-popper-interactive='false']": {
pointerEvents: "none"
}
}),
headerClose: css.css({
color: theme.colors.text.secondary,
position: "absolute",
right: theme.spacing(1),
top: theme.spacing(1.5),
backgroundColor: "transparent",
border: 0
}),
header: css.css({
paddingTop: theme.spacing(1),
paddingBottom: theme.spacing(2)
}),
body: css.css({
paddingTop: theme.spacing(1),
paddingBottom: theme.spacing(1)
}),
footer: css.css({
paddingTop: theme.spacing(2),
paddingBottom: theme.spacing(1)
})
};
}
function Portal$1(props) {
const { children, className, root, forwardedRef } = props;
const theme = useTheme2();
const node = React.useRef(null);
const portalRoot = root != null ? root : getPortalContainer();
if (!node.current) {
node.current = document.createElement("div");
if (className) {
node.current.className = className;
}
node.current.style.position = "relative";
node.current.style.zIndex = `${theme.zIndex.portal}`;
}
React.useLayoutEffect(() => {
if (node.current) {
portalRoot.appendChild(node.current);
}
return () => {
if (node.current) {
portalRoot.removeChild(node.current);
}
};
}, [portalRoot]);
return ReactDOM__default.default.createPortal(/* @__PURE__ */ jsxRuntime.jsx("div", { ref: forwardedRef, children }), node.current);
}
function getPortalContainer() {
var _a;
return (_a = window.document.getElementById("grafana-portal-container")) != null ? _a : document.body;
}
function PortalContainer() {
const styles = useStyles2(getStyles$2i);
return /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
id: "grafana-portal-container",
"data-testid": e2eSelectors.selectors.components.Portal.container,
className: styles.grafanaPortalContainer
}
);
}
const getStyles$2i = (theme) => {
return {
grafanaPortalContainer: css.css({
position: "fixed",
top: 0,
width: "100%",
zIndex: theme.zIndex.portal
})
};
};
const RefForwardingPortal = React__namespace.forwardRef((props, ref) => {
return /* @__PURE__ */ jsxRuntime.jsx(Portal$1, { ...props, forwardedRef: ref });
});
RefForwardingPortal.displayName = "RefForwardingPortal";
const Tooltip = React.forwardRef(
({ children, theme, interactive, show, placement, content }, forwardedRef) => {
const arrowRef = React.useRef(null);
const [controlledVisible, setControlledVisible] = React.useState(show);
const isOpen = show != null ? show : controlledVisible;
const middleware = [
react.offset(8),
react.flip({
fallbackAxisSideDirection: "end",
// see https://floating-ui.com/docs/flip#combining-with-shift
crossAxis: false,
boundary: document.body
}),
react.shift(),
react.arrow({
element: arrowRef
})
];
const { context, refs, floatingStyles } = react.useFloating({
open: isOpen,
placement: getPlacement(placement),
onOpenChange: setControlledVisible,
middleware,
whileElementsMounted: react.autoUpdate
});
const tooltipId = React.useId();
const hover = react.useHover(context, {
handleClose: interactive ? react.safePolygon() : void 0,
move: false
});
const focus = react.useFocus(context);
const dismiss = react.useDismiss(context);
const { getReferenceProps, getFloatingProps } = react.useInteractions([dismiss, hover, focus]);
const contentIsFunction = typeof content === "function";
const styles = useStyles2(getStyles$2h);
const style = styles[theme != null ? theme : "info"];
const handleRef = React.useCallback(
(ref) => {
refs.setReference(ref);
if (typeof forwardedRef === "function") {
forwardedRef(ref);
} else if (forwardedRef) {
forwardedRef.current = ref;
}
},
[forwardedRef, refs]
);
const childHasMatchingAriaLabel = "aria-label" in children.props && children.props["aria-label"] === content;
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
React.cloneElement(children, {
ref: handleRef,
tabIndex: 0,
// tooltip trigger should be keyboard focusable
"aria-describedby": !childHasMatchingAriaLabel && isOpen ? tooltipId : void 0,
...getReferenceProps()
}),
isOpen && /* @__PURE__ */ jsxRuntime.jsx(Portal$1, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: refs.setFloating, style: floatingStyles, ...getFloatingProps(), children: [
/* @__PURE__ */ jsxRuntime.jsx(react.FloatingArrow, { className: style.arrow, ref: arrowRef, context }),
/* @__PURE__ */ jsxRuntime.jsxs(
"div",
{
"data-testid": e2eSelectors.selectors.components.Tooltip.container,
id: tooltipId,
role: "tooltip",
className: style.container,
children: [
typeof content === "string" && content,
React.isValidElement(content) && React.cloneElement(content),
contentIsFunction && content({})
]
}
)
] }) })
] });
}
);
Tooltip.displayName = "Tooltip";
const getStyles$2h = (theme) => {
const info = buildTooltipTheme(
theme,
theme.components.tooltip.background,
theme.components.tooltip.background,
theme.components.tooltip.text,
{ topBottom: 0.5, rightLeft: 1 }
);
const error = buildTooltipTheme(
theme,
theme.colors.error.main,
theme.colors.error.main,
theme.colors.error.contrastText,
{ topBottom: 0.5, rightLeft: 1 }
);
return {
info,
["info-alt"]: info,
error
};
};
const FormLabel = ({
children,
isFocused,
isInvalid,
className,
htmlFor,
tooltip,
width,
interactive,
...rest
}) => {
const classes = classNames__default.default(className, `gf-form-label width-${width ? width : "10"}`, {
"gf-form-label--is-focused": isFocused,
"gf-form-label--is-invalid": isInvalid
});
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: classes, ...rest, htmlFor, children: [
children,
tooltip && /* @__PURE__ */ jsxRuntime.jsx(Tooltip, { placement: "top", content: tooltip, theme: "info", interactive, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "info-circle", size: "sm", style: { marginLeft: "10px" } }) })
] });
};
const InlineFormLabel = FormLabel;
const FormField = ({
label,
tooltip,
labelWidth = 6,
inputWidth = 12,
inputEl,
className,
interactive,
...inputProps
}) => {
const styles = getStyles$2g();
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: css.cx(styles.formField, className), children: [
/* @__PURE__ */ jsxRuntime.jsx(InlineFormLabel, { width: labelWidth, tooltip, interactive, children: label }),
inputEl || /* @__PURE__ */ jsxRuntime.jsx(
"input",
{
type: "text",
className: `gf-form-input ${inputWidth ? `width-${inputWidth}` : ""}`,
...inputProps,
disabled: inputProps.disabled
}
)
] });
};
FormField.displayName = "FormField";
const getStyles$2g = () => {
return {
formField: css.css({
display: "flex",
flexDirection: "row",
alignItems: "flex-start",
textAlign: "left",
position: "relative"
})
};
};
var EventsWithValidation = /* @__PURE__ */ ((EventsWithValidation2) => {
EventsWithValidation2["onBlur"] = "onBlur";
EventsWithValidation2["onFocus"] = "onFocus";
EventsWithValidation2["onChange"] = "onChange";
return EventsWithValidation2;
})(EventsWithValidation || {});
const validate = (value, validationRules) => {
const errors = validationRules.reduce((acc, currRule) => {
if (!currRule.rule(value)) {
return acc.concat(currRule.errorMessage);
}
return acc;
}, []);
return errors.length > 0 ? errors : null;
};
const hasValidationEvent = (event, validationEvents) => {
return validationEvents && validationEvents[event];
};
const regexValidation = (pattern, errorMessage) => {
return {
rule: (valueToValidate) => {
return !!valueToValidate.match(pattern);
},
errorMessage: errorMessage || "Value is not valid"
};
};
var LegacyInputStatus = /* @__PURE__ */ ((LegacyInputStatus2) => {
LegacyInputStatus2["Invalid"] = "invalid";
LegacyInputStatus2["Valid"] = "valid";
return LegacyInputStatus2;
})(LegacyInputStatus || {});
let Input$1 = class Input extends React.PureComponent {
constructor() {
super(...arguments);
this.state = {
error: null
};
this.validatorAsync = (validationRules) => {
return (evt) => {
const errors = validate(evt.target.value, validationRules);
this.setState((prevState) => {
return { ...prevState, error: errors ? errors[0] : null };
});
};
};
this.populateEventPropsWithStatus = (restProps, validationEvents) => {
const inputElementProps = { ...restProps };
if (!validationEvents) {
return inputElementProps;
}
Object.keys(EventsWithValidation).forEach((eventName) => {
if (hasValidationEvent(eventName, validationEvents) || restProps[eventName]) {
inputElementProps[eventName] = async (evt) => {
evt.persist();
if (hasValidationEvent(eventName, validationEvents)) {
await this.validatorAsync(validationEvents[eventName]).apply(this, [evt]);
}
if (restProps[eventName]) {
restProps[eventName].apply(null, [evt, this.status]);
}
};
}
});
return inputElementProps;
};
}
get status() {
return this.state.error ? "invalid" /* Invalid */ : "valid" /* Valid */;
}
get isInvalid() {
return this.status === "invalid" /* Invalid */;
}
render() {
const { validationEvents, className, hideErrorMessage, inputRef, ...restProps } = this.props;
const { error } = this.state;
const inputClassName = classNames__default.default("gf-form-input", { invalid: this.isInvalid }, className);
const inputElementProps = this.populateEventPropsWithStatus(restProps, validationEvents);
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flexGrow: 1 }, children: [
/* @__PURE__ */ jsxRuntime.jsx("input", { ...inputElementProps, ref: inputRef, className: inputClassName }),
error && !hideErrorMessage && /* @__PURE__ */ jsxRuntime.jsx("span", { children: error })
] });
}
};
Input$1.defaultProps = {
className: ""
};
const IndicatorsContainer$1 = (props) => {
const isOpen = props.selectProps.menuIsOpen;
return /* @__PURE__ */ jsxRuntime.jsx(ReactSelect.components.IndicatorsContainer, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: isOpen ? "angle-up" : "angle-down", style: { marginTop: "7px" } }) });
};
const NoOptionsMessage = (props) => {
const { children } = props;
return /* @__PURE__ */ jsxRuntime.jsx(ReactSelect.components.NoOptionsMessage, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gf-form-select-box__desc-option", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gf-form-select-box__desc-option__body", children }) }) });
};
function breakpointCSS(theme, prop, getCSS, key) {
const value = prop[key];
if (value !== void 0 && value !== null) {
return {
[theme.breakpoints.up(key)]: getCSS(value)
};
}
return;
}
function getResponsiveStyle(theme, prop, getCSS) {
if (prop === void 0 || prop === null) {
return null;
}
if (typeof prop !== "object" || !("xs" in prop)) {
return getCSS(prop);
}
return [
breakpointCSS(theme, prop, getCSS, "xs"),
breakpointCSS(theme, prop, getCSS, "sm"),
breakpointCSS(theme, prop, getCSS, "md"),
breakpointCSS(theme, prop, getCSS, "lg"),
breakpointCSS(theme, prop, getCSS, "xl"),
breakpointCSS(theme, prop, getCSS, "xxl")
];
}
const getSizeStyles = (theme, width, minWidth, maxWidth, height, minHeight, maxHeight) => {
return css.css([
getResponsiveStyle(theme, width, (val) => ({
width: theme.spacing(val)
})),
getResponsiveStyle(theme, minWidth, (val) => ({
minWidth: theme.spacing(val)
})),
getResponsiveStyle(theme, maxWidth, (val) => ({
maxWidth: theme.spacing(val)
})),
getResponsiveStyle(theme, height, (val) => ({
height: theme.spacing(val)
})),
getResponsiveStyle(theme, minHeight, (val) => ({
minHeight: theme.spacing(val)
})),
getResponsiveStyle(theme, maxHeight, (val) => ({
maxHeight: theme.spacing(val)
}))
]);
};
const Box = React.forwardRef((props, ref) => {
const {
children,
margin,
marginX,
marginY,
marginTop,
marginBottom,
marginLeft,
marginRight,
padding,
paddingX,
paddingY,
paddingTop,
paddingBottom,
paddingLeft,
paddingRight,
display,
backgroundColor,
grow,
shrink,
basis,
flex,
borderColor,
borderStyle,
borderRadius,
direction,
justifyContent,
alignItems,
boxShadow,
element,
gap,
width,
minWidth,
maxWidth,
height,
minHeight,
maxHeight,
position,
...rest
} = props;
const styles = useStyles2(
getStyles$2f,
margin,
marginX,
marginY,
marginTop,
marginBottom,
marginLeft,
marginRight,
padding,
paddingX,
paddingY,
paddingTop,
paddingBottom,
paddingLeft,
paddingRight,
display,
backgroundColor,
grow,
shrink,
basis,
flex,
borderColor,
borderStyle,
borderRadius,
direction,
justifyContent,
alignItems,
boxShadow,
gap,
position
);
const sizeStyles = useStyles2(getSizeStyles, width, minWidth, maxWidth, height, minHeight, maxHeight);
const Element = element != null ? element : "div";
return /* @__PURE__ */ jsxRuntime.jsx(Element, { ref, className: css.cx(styles.root, sizeStyles), ...rest, children });
});
Box.displayName = "Box";
const customBorderColor = (color, theme) => {
switch (color) {
case "error":
case "success":
case "info":
case "warning":
return theme.colors[color].borderTransparent;
default:
return color ? theme.colors.border[color] : void 0;
}
};
const customBackgroundColor = (color, theme) => {
switch (color) {
case "error":
case "success":
case "info":
case "warning":
return theme.colors[color].transparent;
default:
return color ? theme.colors.background[color] : void 0;
}
};
const getStyles$2f = (theme, margin, marginX, marginY, marginTop, marginBottom, marginLeft, marginRight, padding, paddingX, paddingY, paddingTop, paddingBottom, paddingLeft, paddingRight, display, backgroundColor, grow, shrink, basis, flex, borderColor, borderStyle, borderRadius, direction, justifyContent, alignItems, boxShadow, gap, position) => {
return {
root: css.css([
getResponsiveStyle(theme, margin, (val) => ({
margin: theme.spacing(val)
})),
getResponsiveStyle(theme, marginX, (val) => ({
marginLeft: theme.spacing(val),
marginRight: theme.spacing(val)
})),
getResponsiveStyle(theme, marginY, (val) => ({
marginTop: theme.spacing(val),
marginBottom: theme.spacing(val)
})),
getResponsiveStyle(theme, marginTop, (val) => ({
marginTop: theme.spacing(val)
})),
getResponsiveStyle(theme, marginBottom, (val) => ({
marginBottom: theme.spacing(val)
})),
getResponsiveStyle(theme, marginLeft, (val) => ({
marginLeft: theme.spacing(val)
})),
getResponsiveStyle(theme, marginRight, (val) => ({
marginRight: theme.spacing(val)
})),
getResponsiveStyle(theme, padding, (val) => ({
padding: theme.spacing(val)
})),
getResponsiveStyle(theme, paddingX, (val) => ({
paddingLeft: theme.spacing(val),
paddingRight: theme.spacing(val)
})),
getResponsiveStyle(theme, paddingY, (val) => ({
paddingTop: theme.spacing(val),
paddingBottom: theme.spacing(val)
})),
getResponsiveStyle(theme, paddingTop, (val) => ({
paddingTop: theme.spacing(val)
})),
getResponsiveStyle(theme, paddingBottom, (val) => ({
paddingBottom: theme.spacing(val)
})),
getResponsiveStyle(theme, paddingLeft, (val) => ({
paddingLeft: theme.spacing(val)
})),
getResponsiveStyle(theme, paddingRight, (val) => ({
paddingRight: theme.spacing(val)
})),
getResponsiveStyle(theme, display, (val) => ({
display: val
})),
getResponsiveStyle(theme, backgroundColor, (val) => ({
backgroundColor: customBackgroundColor(val, theme)
})),
getResponsiveStyle(theme, direction, (val) => ({
flexDirection: val
})),
getResponsiveStyle(theme, grow, (val) => ({
flexGrow: val
})),
getResponsiveStyle(theme, shrink, (val) => ({
flexShrink: val
})),
getResponsiveStyle(theme, basis, (val) => ({
flexBasis: val
})),
getResponsiveStyle(theme, flex, (val) => ({
flex: val
})),
getResponsiveStyle(theme, borderStyle, (val) => ({
borderStyle: val
})),
getResponsiveStyle(theme, borderColor, (val) => ({
borderColor: customBorderColor(val, theme)
})),
(borderStyle || borderColor) && {
borderWidth: "1px"
},
getResponsiveStyle(theme, justifyContent, (val) => ({
justifyContent: val
})),
getResponsiveStyle(theme, alignItems, (val) => ({
alignItems: val
})),
getResponsiveStyle(theme, borderRadius, (val) => ({
borderRadius: theme.shape.radius[val]
})),
getResponsiveStyle(theme, boxShadow, (val) => ({
boxShadow: theme.shadows[val]
})),
getResponsiveStyle(theme, gap, (val) => ({
gap: theme.spacing(val)
})),
getResponsiveStyle(theme, position, (val) => ({
position: val
}))
])
};
};
const ScrollIndicators$1 = ({ children }) => {
const [showScrollTopIndicator, setShowTopScrollIndicator] = React.useState(false);
const [showScrollBottomIndicator, setShowBottomScrollIndicator] = React.useState(false);
const scrollTopMarker = React.useRef(null);
const scrollBottomMarker = React.useRef(null);
const styles = useStyles2(getStyles$2e);
React.useEffect(() => {
const intersectionObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.target === scrollTopMarker.current) {
setShowTopScrollIndicator(!entry.isIntersecting);
} else if (entry.target === scrollBottomMarker.current) {
setShowBottomScrollIndicator(!entry.isIntersecting);
}
});
});
[scrollTopMarker, scrollBottomMarker].forEach((ref) => {
if (ref.current) {
intersectionObserver.observe(ref.current);
}
});
return () => intersectionObserver.disconnect();
}, []);
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
/* @__PURE__ */ jsxRuntime.jsx(
"div",
{
className: css.cx(styles.scrollIndicator, styles.scrollTopIndicator, {
[styles.scrollIndicatorVisible]: showScrollTopIndicator
}),
role: "presentation"
}
),
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.scrollContent, children: [
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: scrollTopMarker, className: css.cx(styles.scrollMarker, styles.scrollTopMarker) }),
children,
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: scrollBottomMarker, className: css.cx(styles.scrollMarker, styles.scrollBottomMarker) })
] }),
/* @__PURE__ */ jsxRuntime.jsx(
"div",
{
className: css.cx(styles.scrollIndicator, styles.scrollBottomIndicator, {
[styles.scrollIndicatorVisible]: showScrollBottomIndicator
}),
role: "presentation"
}
)
] });
};
const getStyles$2e = (theme) => {
const scrollGradientColor = `rgba(0, 0, 0, ${theme.isDark ? 0.25 : 0.08})`;
return {
scrollContent: css.css({
display: "flex",
flexDirection: "column",
flexGrow: 1,
position: "relative"
}),
scrollIndicator: css.css({
height: `max(5%, ${theme.spacing(3)})`,
left: 0,
opacity: 0,
pointerEvents: "none",
position: "absolute",
right: 0,
[theme.transitions.handleMotion("no-preference", "reduce")]: {
transition: theme.transitions.create("opacity")
},
zIndex: 1
}),
scrollTopIndicator: css.css({
background: `linear-gradient(0deg, transparent, ${scrollGradientColor})`,
top: 0
}),
scrollBottomIndicator: css.css({
background: `linear-gradient(180deg, transparent, ${scrollGradientColor})`,
bottom: 0
}),
scrollIndicatorVisible: css.css({
opacity: 1
}),
scrollMarker: css.css({
height: "1px",
left: 0,
pointerEvents: "none",
position: "absolute",
right: 0
}),
scrollTopMarker: css.css({
top: 0
}),
scrollBottomMarker: css.css({
bottom: 0
})
};
};
const ScrollContainer = React.forwardRef(
({
children,
showScrollIndicators = false,
onScroll,
overflowX = "auto",
overflowY = "auto",
scrollbarWidth = "thin",
...rest
}, ref) => {
const styles = useStyles2(getStyles$2d, scrollbarWidth, overflowY, overflowX);
const defaults = {
maxHeight: "100%",
minHeight: 0,
minWidth: 0
};
const boxProps = { ...defaults, ...rest };
return /* @__PURE__ */ jsxRuntime.jsx(Box, { ...boxProps, display: "flex", direction: "column", flex: 1, position: "relative", children: /* @__PURE__ */ jsxRuntime.jsx("div", { onScroll, className: styles.scroller, ref, children: showScrollIndicators ? /* @__PURE__ */ jsxRuntime.jsx(ScrollIndicators$1, { children }) : children }) });
}
);
ScrollContainer.displayName = "ScrollContainer";
const getStyles$2d = (theme, scrollbarWidth, overflowY, overflowX) => ({
scroller: css.css({
display: "flex",
flex: 1,
flexDirection: "column",
overflowX,
overflowY,
scrollbarWidth
})
});
function useDelayedSwitch(value, options = {}) {
const { duration = 250, delay = 250 } = options;
const [delayedValue, setDelayedValue] = React.useState(value);
const onStartTime = React.useRef();
React.useEffect(() => {
let timeout;
if (value) {
timeout = setTimeout(() => {
onStartTime.current = /* @__PURE__ */ new Date();
setDelayedValue(value);
}, delay);
} else {
const timeSpent = onStartTime.current ? Date.now() - onStartTime.current.valueOf() : 0;
const turnOff = () => {
onStartTime.current = void 0;
setDelayedValue(value);
};
if (timeSpent >= duration) {
turnOff();
} else {
timeout = setTimeout(turnOff, duration - timeSpent);
}
}
return () => {
if (timeout) {
clearTimeout(timeout);
timeout = void 0;
}
};
}, [value, duration, delay]);
return delayedValue;
}
const isIconSize = (value) => {
return ["xs", "sm", "md", "lg", "xl", "xxl", "xxxl"].includes(value);
};
const getAvailableIcons = () => Object.keys(data.availableIconsIndex);
function getFieldTypeIcon(field) {
return getFieldTypeIconName(field == null ? void 0 : field.type);
}
function getFieldTypeIconName(type) {
if (type) {
switch (type) {
case data.FieldType.time:
return "clock-nine";
case data.FieldType.string:
return "font";
case data.FieldType.number:
return "calculator-alt";
case data.FieldType.boolean:
return "toggle-on";
case data.FieldType.trace:
return "info-circle";
case data.FieldType.enum:
return "list-ol";
case data.FieldType.geo:
return "map-marker";
case data.FieldType.other:
return "brackets-curly";
}
}
return "question-circle";
}
const Spinner = ({
className,
inline = false,
iconClassName,
style,
size = "md"
}) => {
const styles = useStyles2(getStyles$2c);
const deprecatedStyles = useStyles2(getDeprecatedStyles, size);
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
const iconName = prefersReducedMotion ? "hourglass" : "spinner";
if (typeof size !== "string" || !isIconSize(size)) {
const iconRoot = getIconRoot();
const subDir = getIconSubDir(iconName, "default");
const svgPath = `${iconRoot}${subDir}/${iconName}.svg`;
return /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
"data-testid": "Spinner",
style,
className: css.cx(
{
[styles.inline]: inline
},
deprecatedStyles.wrapper,
className
),
children: /* @__PURE__ */ jsxRuntime.jsx(
SVG__default.default,
{
src: svgPath,
width: size,
height: size,
className: css.cx(styles.spin, deprecatedStyles.icon, className),
style
}
)
}
);
}
return /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
"data-testid": "Spinner",
style,
className: css.cx(
{
[styles.inline]: inline
},
className
),
children: /* @__PURE__ */ jsxRuntime.jsx(
Icon,
{
className: css.cx(styles.spin, iconClassName),
name: iconName,
size,
"aria-label": i18n.t("grafana-ui.spinner.aria-label", "Loading")
}
)
}
);
};
const getStyles$2c = (theme) => ({
inline: css.css({
display: "inline-block",
lineHeight: 0
}),
spin: css.css({
[theme.transitions.handleMotion("no-preference")]: {
animation: `${spin$1} 2s infinite linear`
}
})
});
const getDeprecatedStyles = (theme, size) => ({
wrapper: css.css({
fontSize: typeof size === "string" ? size : `${size}px`
}),
icon: css.css({
display: "inline-block",
fill: "currentColor",
flexShrink: 0,
label: "Icon",
// line-height: 0; is needed for correct icon alignment in Safari
lineHeight: 0,
verticalAlign: "middle"
})
});
function FadeTransition(props) {
const { visible, children, duration = 250 } = props;
const styles = useStyles2(getStyles$2b, duration);
const transitionRef = React.useRef(null);
return /* @__PURE__ */ jsxRuntime.jsx(
reactTransitionGroup.CSSTransition,
{
in: visible,
mountOnEnter: true,
unmountOnExit: true,
timeout: duration,
classNames: styles,
nodeRef: transitionRef,
children: React__namespace.cloneElement(children, { ref: transitionRef })
}
);
}
const getStyles$2b = (theme, duration) => ({
enter: css.css({
label: "enter",
opacity: 0
}),
enterActive: css.css({
label: "enterActive",
opacity: 1,
[theme.transitions.handleMotion("no-preference", "reduce")]: {
transition: `opacity ${duration}ms ease-out`
}
}),
exit: css.css({
label: "exit",
opacity: 1
}),
exitActive: css.css({
label: "exitActive",
opacity: 0,
[theme.transitions.handleMotion("no-preference", "reduce")]: {
transition: `opacity ${duration}ms ease-out`
}
})
});
function SlideOutTransition(props) {
const { visible, children, duration = 250, horizontal, size } = props;
const styles = useStyles2(getStyles$2a, duration, horizontal ? "width" : "height", size);
const transitionRef = React.useRef(null);
return /* @__PURE__ */ jsxRuntime.jsx(
reactTransitionGroup.CSSTransition,
{
in: visible,
mountOnEnter: true,
unmountOnExit: true,
timeout: duration,
classNames: styles,
nodeRef: transitionRef,
children: React__namespace.cloneElement(children, { ref: transitionRef })
}
);
}
const getStyles$2a = (theme, duration, measurement, size) => ({
enter: css.css({
label: "enter",
[`${measurement}`]: 0,
opacity: 0
}),
enterActive: css.css({
label: "enterActive",
[`${measurement}`]: `${size}px`,
opacity: 1,
[theme.transitions.handleMotion("no-preference")]: {
transition: `opacity ${duration}ms ease-out, ${measurement} ${duration}ms ease-out`
},
[theme.transitions.handleMotion("reduce")]: {
transition: `opacity ${duration}ms ease-out`
}
}),
exit: css.css({
label: "exit",
[`${measurement}`]: `${size}px`,
opacity: 1
}),
exitActive: css.css({
label: "exitActive",
opacity: 0,
[`${measurement}`]: 0,
[theme.transitions.handleMotion("no-preference")]: {
transition: `opacity ${duration}ms ease-out, ${measurement} ${duration}ms ease-out`
},
[theme.transitions.handleMotion("reduce")]: {
transition: `opacity ${duration}ms ease-out`
}
})
});
const getStyles$29 = (theme) => {
return {
singleValue: css.css({
label: "singleValue",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
boxSizing: "border-box",
maxWidth: "100%",
gridArea: "1 / 1 / 2 / 3"
}),
spinnerWrapper: css.css({
width: "16px",
height: "16px",
display: "inline-block",
marginRight: "10px",
position: "relative",
verticalAlign: "middle",
overflow: "hidden"
}),
spinnerIcon: css.css({
width: "100%",
height: "100%",
position: "absolute"
}),
optionIcon: css.css({
marginRight: theme.spacing(1),
color: theme.colors.text.secondary
}),
disabled: css.css({
color: theme.colors.text.disabled
}),
isOpen: css.css({
color: theme.colors.text.disabled
})
};
};
const SingleValue = (props) => {
var _a;
const { children, data: data$1, isDisabled } = props;
const styles = useStyles2(getStyles$29);
const loading = useDelayedSwitch(data$1.loading || false, { delay: 250, duration: 750 });
const icon = data$1.icon ? data.toIconName(data$1.icon) : void 0;
return /* @__PURE__ */ jsxRuntime.jsxs(
ReactSelect.components.SingleValue,
{
...props,
className: css.cx(styles.singleValue, isDisabled && styles.disabled, props.selectProps.menuIsOpen && styles.isOpen),
children: [
data$1.imgUrl ? /* @__PURE__ */ jsxRuntime.jsx(FadeWithImage, { loading, imgUrl: data$1.imgUrl, styles, alt: String((_a = data$1.label) != null ? _a : data$1.value) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
/* @__PURE__ */ jsxRuntime.jsx(SlideOutTransition, { horizontal: true, size: 16, visible: loading, duration: 150, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.spinnerWrapper, children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { className: styles.spinnerIcon, inline: true }) }) }),
icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, role: "img", className: styles.optionIcon })
] }),
!data$1.hideText && children
]
}
);
};
const FadeWithImage = (props) => {
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: props.styles.spinnerWrapper, children: [
/* @__PURE__ */ jsxRuntime.jsx(FadeTransition, { duration: 150, visible: props.loading, children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { className: props.styles.spinnerIcon, inline: true }) }),
/* @__PURE__ */ jsxRuntime.jsx(FadeTransition, { duration: 150, visible: !props.loading, children: /* @__PURE__ */ jsxRuntime.jsx("img", { className: props.styles.spinnerIcon, src: props.imgUrl, alt: props.alt }) })
] });
};
function resetSelectStyles(theme) {
return {
clearIndicator: () => ({}),
container: () => ({}),
control: () => ({}),
dropdownIndicator: () => ({}),
group: () => ({}),
groupHeading: () => ({}),
indicatorsContainer: () => ({}),
indicatorSeparator: () => ({}),
input: function(originalStyles) {
return {
...originalStyles,
color: "inherit",
margin: 0,
padding: 0,
// Set an explicit z-index here to ensure this element always overlays the singleValue
zIndex: 1,
overflow: "hidden"
};
},
loadingIndicator: () => ({}),
loadingMessage: () => ({}),
menu: () => ({}),
menuList: ({ maxHeight }) => ({
maxHeight
}),
multiValue: () => ({}),
multiValueLabel: () => ({
overflow: "hidden",
textOverflow: "ellipsis"
}),
multiValueRemove: () => ({}),
noOptionsMessage: () => ({}),
option: () => ({}),
placeholder: (originalStyles) => ({
...originalStyles,
color: theme.colors.text.secondary
}),
singleValue: () => ({}),
valueContainer: () => ({})
};
}
function useCustomSelectStyles(theme, width) {
return React.useMemo(() => {
return {
...resetSelectStyles(theme),
menuPortal: (base) => {
return {
...base,
zIndex: theme.zIndex.portal
};
},
//These are required for the menu positioning to function
menu: ({ top, bottom, position }) => {
return {
top,
bottom,
position,
minWidth: "100%",
zIndex: theme.zIndex.dropdown
};
},
container: () => ({
width: width ? theme.spacing(width) : "100%",
display: width === "auto" ? "inline-flex" : "flex"
}),
option: (provided, state) => ({
...provided,
opacity: state.isDisabled ? 0.5 : 1
})
};
}, [theme, width]);
}
const SelectOption = (props) => {
const { children, isSelected, data } = props;
return /* @__PURE__ */ jsxRuntime.jsx(ReactSelect.components.Option, { ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gf-form-select-box__desc-option", children: [
data.imgUrl && /* @__PURE__ */ jsxRuntime.jsx("img", { className: "gf-form-select-box__desc-option__img", src: data.imgUrl, alt: "" }),
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gf-form-select-box__desc-option__body", children: [
/* @__PURE__ */ jsxRuntime.jsx("div", { children }),
data.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gf-form-select-box__desc-option__desc", children: data.description })
] }),
isSelected && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "check", "aria-hidden": "true" })
] }) });
};
const getSelectOptionGroupStyles = stylesFactory((theme) => {
return {
header: css.css({
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
justifyItems: "center",
cursor: "pointer",
padding: "7px 10px",
width: "100%",
borderBottom: `1px solid ${theme.colors.background.secondary}`,
"&:hover": {
color: theme.colors.text.maxContrast
}
}),
label: css.css({
flexGrow: 1
}),
icon: css.css({
paddingRight: "2px"
})
};
});
class UnthemedSelectOptionGroup extends React.PureComponent {
constructor() {
super(...arguments);
this.state = {
expanded: false
};
this.onToggleChildren = () => {
this.setState((prevState) => ({
expanded: !prevState.expanded
}));
};
}
componentDidMount() {
if (this.props.data.expanded) {
this.setState({ expanded: true });
} else if (this.props.selectProps && this.props.selectProps.value) {
const { value } = this.props.selectProps.value;
if (value && this.props.options.some((option) => option.value === value)) {
this.setState({ expanded: true });
}
}
}
componentDidUpdate(nextProps) {
if (nextProps.selectProps.inputValue !== "") {
this.setState({ expanded: true });
}
}
render() {
const { children, label, theme } = this.props;
const { expanded } = this.state;
const styles = getSelectOptionGroupStyles(theme);
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.header, onClick: this.onToggleChildren, role: "presentation", children: [
/* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.label, children: label }),
/* @__PURE__ */ jsxRuntime.jsx(Icon, { className: styles.icon, name: expanded ? "angle-up" : "angle-down" })
] }),
expanded && children
] });
}
}
const SelectOptionGroup$1 = withTheme2(UnthemedSelectOptionGroup);
const MenuList = (props) => {
return /* @__PURE__ */ jsxRuntime.jsx(ReactSelect.components.MenuList, { ...props, children: /* @__PURE__ */ jsxRuntime.jsx(ScrollContainer, { showScrollIndicators: true, overflowX: "hidden", maxHeight: "inherit", children: props.children }) });
};
const _Select = class _Select extends React.PureComponent {
render() {
const {
defaultValue,
getOptionLabel,
getOptionValue,
onChange,
options,
placeholder,
width,
value,
className,
isDisabled,
isLoading,
isSearchable,
isClearable,
backspaceRemovesValue,
isMulti,
autoFocus,
openMenuOnFocus,
onBlur,
maxMenuHeight,
noOptionsMessage,
isOpen,
components: components2,
tooltipContent,
tabSelectsValue,
o