{"version":3,"file":"Icon.cjs","sources":["../../../../src/components/Icon/Icon.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { useCallback, useState, useRef, memo, forwardRef } from 'react';\nimport SVG from 'react-inlinesvg';\n\nimport { GrafanaTheme2, isIconName } from '@grafana/data';\n\nimport { useStyles2 } from '../../themes/ThemeContext';\nimport { IconName, IconType, IconSize } from '../../types/icon';\nimport { spin } from '../../utils/keyframes';\n\nimport { getIconPath, getSvgSize } from './utils';\n\nexport interface IconProps extends Omit<React.SVGProps<SVGElement>, 'onLoad' | 'onError' | 'ref'> {\n  name: IconName;\n  size?: IconSize;\n  type?: IconType;\n  /**\n   * Give your icon a semantic meaning. The icon will be hidden from screen readers, unless this prop or an aria-label is provided.\n   */\n  title?: string;\n}\n\nconst getIconStyles = (theme: GrafanaTheme2) => {\n  return {\n    icon: css({\n      display: 'inline-block',\n      fill: 'currentColor',\n      flexShrink: 0,\n      label: 'Icon',\n      // line-height: 0; is needed for correct icon alignment in Safari\n      lineHeight: 0,\n      verticalAlign: 'middle',\n    }),\n    orange: css({\n      fill: theme.v1.palette.orange,\n    }),\n    spin: css({\n      [theme.transitions.handleMotion('no-preference', 'reduce')]: {\n        animation: `${spin} 2s infinite linear`,\n      },\n    }),\n  };\n};\n\n// The SVG can become 'stuck' if it's changed quickly before the previous icon finished loading.\n// See https://github.com/gilbarbara/react-inlinesvg/issues/247\n// By using the svgPath as the key, we ensure that the component is re-mounted and the new icon is loaded correctly.\nfunction useIconWorkaround(name: IconName) {\n  // Buffer name changes while the icon is loading until it stops loading, then apply the most recent name change.\n  // We use refs for state and a forceUpdate state to avoid needing to use the buffered name in the happy path\n  // of when the icon changes when its not currently loading.\n  // We want to avoid needless state updates to keep track of the lifecycle.\n\n  const [, setForceUpdate] = useState(0);\n  const isLoadingRef = useRef(false);\n  const currentNameRef = useRef(name);\n  const bufferedNameRef = useRef<IconName | null>(null);\n\n  // Decide which name to render THIS render\n  let nameToUse = name;\n\n  if (isLoadingRef.current && name !== currentNameRef.current) {\n    // Currently loading and name changed - buffer it, keep using current\n    nameToUse = currentNameRef.current;\n    bufferedNameRef.current = name;\n  } else if (!isLoadingRef.current && name !== currentNameRef.current) {\n    // Not loading - use new name immediately (happy path)\n    currentNameRef.current = name;\n    bufferedNameRef.current = null;\n    isLoadingRef.current = true; // Mark as loading when we accept a new name\n  }\n\n  const handleLoad = useCallback(() => {\n    isLoadingRef.current = false;\n\n    // Apply buffered name if one exists\n    if (bufferedNameRef.current) {\n      currentNameRef.current = bufferedNameRef.current;\n      bufferedNameRef.current = null;\n      setForceUpdate((n) => n + 1); // Trigger re-render with buffered name\n    }\n  }, []);\n\n  return { nameToUse, handleLoad };\n}\n\n/**\n * Grafana's icon wrapper component.\n *\n * https://developers.grafana.com/ui/latest/index.html?path=/docs/iconography-icon--docs\n */\nexport const Icon = memo(\n  forwardRef<SVGElement, IconProps>(\n    ({ size = 'md', type = 'default', name: nameProp, className, style, title = '', ...rest }, ref) => {\n      const styles = useStyles2(getIconStyles);\n      const { nameToUse: name, handleLoad } = useIconWorkaround(nameProp);\n\n      if (!isIconName(name)) {\n        console.warn('Icon component passed an invalid icon name', name);\n      }\n\n      // handle the deprecated 'fa fa-spinner'\n      const iconName: IconName = name === 'fa fa-spinner' ? 'spinner' : name;\n\n      const svgSize = getSvgSize(size);\n      const svgHgt = svgSize;\n      const svgWid = name.startsWith('gf-bar-align') ? 16 : name.startsWith('gf-interp') ? 30 : svgSize;\n      const svgPath = getIconPath(iconName, type);\n\n      const composedClassName = cx(\n        styles.icon,\n        className,\n        type === 'mono' ? { [styles.orange]: name === 'favorite' } : '',\n        {\n          [styles.spin]: iconName === 'spinner',\n        }\n      );\n\n      return (\n        <SVG\n          data-testid={`icon-${iconName}`}\n          aria-hidden={\n            rest.tabIndex === undefined &&\n            !title &&\n            !rest['aria-label'] &&\n            !rest['aria-labelledby'] &&\n            !rest['aria-describedby']\n          }\n          onLoad={handleLoad}\n          onError={handleLoad}\n          innerRef={ref}\n          src={svgPath}\n          width={svgWid}\n          height={svgHgt}\n          title={title}\n          className={composedClassName}\n          style={style}\n          // render an empty element with the correct dimensions while loading\n          // this prevents content layout shift whilst the icon asynchronously loads\n          // which happens even if the icon is in the cache(!)\n          loader={\n            <svg\n              className={cx(\n                css({\n                  width: svgWid,\n                  height: svgHgt,\n                }),\n                composedClassName\n              )}\n            />\n          }\n          {...rest}\n        />\n      );\n    }\n  )\n);\n\nIcon.displayName = 'Icon';\n"],"names":["css","spin","useState","useRef","useCallback","memo","forwardRef","useStyles2","isIconName","getSvgSize","getIconPath","cx","jsx","SVG"],"mappings":"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"}