@grafana/ui
Version:
Grafana Components Library
124 lines (117 loc) • 4.12 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var jsxRuntime = require('react/jsx-runtime');
var css = require('@emotion/css');
var React = require('react');
var SVG = require('react-inlinesvg');
var data = require('@grafana/data');
var ThemeContext = require('../../themes/ThemeContext.cjs');
var keyframes = require('../../utils/keyframes.cjs');
var utils = require('./utils.cjs');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
var SVG__default = /*#__PURE__*/_interopDefaultCompat(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: `${keyframes.spin} 2s infinite linear`
}
})
};
};
function useIconWorkaround(name) {
const [, setForceUpdate] = React.useState(0);
const isLoadingRef = React.useRef(false);
const currentNameRef = React.useRef(name);
const bufferedNameRef = React.useRef(null);
let nameToUse = name;
if (isLoadingRef.current && name !== currentNameRef.current) {
nameToUse = currentNameRef.current;
bufferedNameRef.current = name;
} else if (!isLoadingRef.current && name !== currentNameRef.current) {
currentNameRef.current = name;
bufferedNameRef.current = null;
isLoadingRef.current = true;
}
const handleLoad = React.useCallback(() => {
isLoadingRef.current = false;
if (bufferedNameRef.current) {
currentNameRef.current = bufferedNameRef.current;
bufferedNameRef.current = null;
setForceUpdate((n) => n + 1);
}
}, []);
return { nameToUse, handleLoad };
}
const Icon = React.memo(
React.forwardRef(
({ size = "md", type = "default", name: nameProp, className, style, title = "", ...rest }, ref) => {
const styles = ThemeContext.useStyles2(getIconStyles);
const { nameToUse: name, handleLoad } = useIconWorkaround(nameProp);
if (!data.isIconName(name)) {
console.warn("Icon component passed an invalid icon name", name);
}
const iconName = name === "fa fa-spinner" ? "spinner" : name;
const svgSize = utils.getSvgSize(size);
const svgHgt = svgSize;
const svgWid = name.startsWith("gf-bar-align") ? 16 : name.startsWith("gf-interp") ? 30 : svgSize;
const svgPath = utils.getIconPath(iconName, type);
const composedClassName = css.cx(
styles.icon,
className,
type === "mono" ? { [styles.orange]: name === "favorite" } : "",
{
[styles.spin]: iconName === "spinner"
}
);
return (
// @ts-expect-error react-inlinesvg@4.3.0 return type includes bigint, which isn't in @types/react@18's ReactNode. Remove when we update @types/react.
/* @__PURE__ */ jsxRuntime.jsx(
SVG__default.default,
{
"data-testid": `icon-${iconName}`,
"aria-hidden": rest.tabIndex === void 0 && !title && !rest["aria-label"] && !rest["aria-labelledby"] && !rest["aria-describedby"],
onLoad: handleLoad,
onError: handleLoad,
innerRef: ref,
src: svgPath,
width: svgWid,
height: svgHgt,
title,
className: composedClassName,
style,
loader: /* @__PURE__ */ jsxRuntime.jsx(
"svg",
{
className: css.cx(
css.css({
width: svgWid,
height: svgHgt
}),
composedClassName
)
}
),
...rest
}
)
);
}
)
);
Icon.displayName = "Icon";
exports.Icon = Icon;
//# sourceMappingURL=Icon.cjs.map