UNPKG

@grafana/ui

Version:
1,566 lines (1,532 loc) • 1.38 MB
'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