{"version":3,"file":"Input.mjs","sources":["../../../../src/components/Input/Input.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { forwardRef, HTMLProps, ReactNode, useContext } from 'react';\nimport { useMeasure } from 'react-use';\n\nimport { GrafanaTheme2 } from '@grafana/data';\n\nimport { useTheme2 } from '../../themes/ThemeContext';\nimport { stylesFactory } from '../../themes/stylesFactory';\nimport { getFocusStyle, sharedInputStyle } from '../Forms/commonStyles';\nimport { Spinner } from '../Spinner/Spinner';\n\nimport { AutoSizeInputContext } from './AutoSizeInputContext';\n\nexport interface Props extends Omit<HTMLProps<HTMLInputElement>, 'prefix' | 'size'> {\n  /** Sets the width to a multiple of 8px. Should only be used with inline forms. Setting width of the container is preferred in other cases.*/\n  width?: number;\n  /** Show an invalid state around the input */\n  invalid?: boolean;\n  /** Show an icon as a prefix in the input */\n  prefix?: ReactNode;\n  /** Show an icon as a suffix in the input */\n  suffix?: ReactNode;\n  /** Show a loading indicator as a suffix in the input */\n  loading?: boolean;\n  /** Add a component as an addon before the input  */\n  addonBefore?: ReactNode;\n  /** Add a component as an addon after the input */\n  addonAfter?: ReactNode;\n}\n\ninterface StyleDeps {\n  theme: GrafanaTheme2;\n  invalid?: boolean;\n  width?: number;\n}\n\n/**\n * Used for regular text input. For an array of data or tree-structured data, consider using `Combobox` or `Cascader` respectively.\n *\n * https://developers.grafana.com/ui/latest/index.html?path=/docs/inputs-input--docs\n */\nexport const Input = forwardRef<HTMLInputElement, Props>((props, ref) => {\n  const {\n    className,\n    addonAfter,\n    addonBefore,\n    prefix,\n    suffix: suffixProp,\n    invalid,\n    loading,\n    width = 0,\n    ...restProps\n  } = props;\n  /**\n   * Prefix & suffix are positioned absolutely within inputWrapper. We use client rects below to apply correct padding to the input\n   * when prefix/suffix is larger than default (28px = 16px(icon) + 12px(left/right paddings)).\n   * Thanks to that prefix/suffix do not overflow the input element itself.\n   */\n  const [prefixRef, prefixRect] = useMeasure<HTMLDivElement>();\n  const [suffixRef, suffixRect] = useMeasure<HTMLDivElement>();\n\n  // Yes, this is gross - When Input is being wrapped by AutoSizeInput, add the suffix/prefix width to the overall width\n  // so the text content is not clipped. The intention is to make all the input's text appear without overflow/clipping,\n  // which isn't normally how width is used in this component.\n  // This behaviour is not controlled via a prop so we can limit API surface, and remove this as a 'breaking change' later\n  // if a better solution is found.\n  const isInAutoSizeInput = useContext(AutoSizeInputContext);\n  const accessoriesWidth = (prefixRect.width || 0) + (suffixRect.width || 0);\n  const autoSizeWidth = isInAutoSizeInput && width ? width + accessoriesWidth / 8 : undefined;\n\n  const theme = useTheme2();\n\n  // Don't pass the width prop, as this causes an unnecessary amount of Emotion calls when auto sizing\n  const styles = getInputStyles({ theme, invalid: !!invalid, width: autoSizeWidth ? undefined : width });\n\n  const suffix = suffixProp || (loading && <Spinner inline={true} />);\n\n  return (\n    <div\n      className={cx(styles.wrapper, className)}\n      // If the component is in an AutoSizeInput, set the width here to prevent emotion doing stuff\n      // on every keypress\n      style={autoSizeWidth ? { width: theme.spacing(autoSizeWidth) } : undefined}\n      data-testid=\"input-wrapper\"\n    >\n      {!!addonBefore && <div className={styles.addon}>{addonBefore}</div>}\n      <div className={styles.inputWrapper}>\n        {prefix && (\n          <div className={styles.prefix} ref={prefixRef}>\n            {prefix}\n          </div>\n        )}\n\n        <input\n          ref={ref}\n          className={styles.input}\n          {...restProps}\n          onWheel={\n            restProps.type === 'number'\n              ? (e) => {\n                  e.currentTarget.blur();\n                  restProps.onWheel?.(e);\n                }\n              : restProps.onWheel\n          }\n          style={{\n            paddingLeft: prefix ? prefixRect.width + 12 : undefined,\n            paddingRight: suffix || loading ? suffixRect.width + 12 : undefined,\n          }}\n        />\n\n        {suffix && (\n          <div className={styles.suffix} ref={suffixRef}>\n            {suffix}\n          </div>\n        )}\n      </div>\n      {!!addonAfter && <div className={styles.addon}>{addonAfter}</div>}\n    </div>\n  );\n});\n\nInput.displayName = 'Input';\n\nexport const getInputStyles = stylesFactory(({ theme, invalid = false, width }: StyleDeps) => {\n  const prefixSuffixStaticWidth = '28px';\n  const prefixSuffix = css({\n    position: 'absolute',\n    top: 0,\n    zIndex: 1,\n    display: 'flex',\n    alignItems: 'center',\n    justifyContent: 'center',\n    flexGrow: 0,\n    flexShrink: 0,\n    fontSize: theme.typography.size.md,\n    height: '100%',\n    /* Min width specified for prefix/suffix classes used outside React component*/\n    minWidth: prefixSuffixStaticWidth,\n    color: theme.colors.text.secondary,\n  });\n\n  return {\n    // Wraps inputWrapper and addons\n    wrapper: cx(\n      css({\n        label: 'input-wrapper',\n        display: 'flex',\n        width: width ? theme.spacing(width) : '100%',\n        height: theme.spacing(theme.components.height.md),\n        borderRadius: theme.shape.radius.default,\n        '&:hover': {\n          '> .prefix, .suffix, .input': {\n            borderColor: invalid ? theme.colors.error.border : theme.colors.primary.border,\n          },\n\n          // only show number buttons on hover\n          \"input[type='number']\": {\n            appearance: 'textfield',\n          },\n\n          \"input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button\": {\n            // Need type assertion here due to the use of !important\n            // see https://github.com/frenic/csstype/issues/114#issuecomment-697201978\n            // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n            WebkitAppearance: 'inner-spin-button !important' as 'inner-spin-button',\n            opacity: 1,\n          },\n        },\n      })\n    ),\n    // Wraps input and prefix/suffix\n    inputWrapper: css({\n      label: 'input-inputWrapper',\n      position: 'relative',\n      flexGrow: 1,\n      /* we want input to be above addons, especially for focused state */\n      zIndex: 1,\n\n      /* when input rendered with addon before only*/\n      '&:not(:first-child):last-child': {\n        '> input': {\n          borderLeft: 'none',\n          borderTopLeftRadius: 'unset',\n          borderBottomLeftRadius: 'unset',\n        },\n      },\n\n      /* when input rendered with addon after only*/\n      '&:first-child:not(:last-child)': {\n        '> input': {\n          borderRight: 'none',\n          borderTopRightRadius: 'unset',\n          borderBottomRightRadius: 'unset',\n        },\n      },\n\n      /* when rendered with addon before and after */\n      '&:not(:first-child):not(:last-child)': {\n        '> input': {\n          borderRight: 'none',\n          borderTopRightRadius: 'unset',\n          borderBottomRightRadius: 'unset',\n          borderTopLeftRadius: 'unset',\n          borderBottomLeftRadius: 'unset',\n        },\n      },\n\n      input: {\n        /* paddings specified for classes used outside React component */\n        '&:not(:first-child)': {\n          paddingLeft: prefixSuffixStaticWidth,\n        },\n        '&:not(:last-child)': {\n          paddingRight: prefixSuffixStaticWidth,\n        },\n        '&[readonly]': {\n          cursor: 'default',\n        },\n      },\n    }),\n\n    input: cx(\n      getFocusStyle(theme),\n      sharedInputStyle(theme, invalid),\n      css({\n        label: 'input-input',\n        position: 'relative',\n        zIndex: 0,\n        flexGrow: 1,\n        borderRadius: theme.shape.radius.default,\n        height: '100%',\n        width: '100%',\n      })\n    ),\n    inputDisabled: css({\n      backgroundColor: theme.colors.action.disabledBackground,\n      color: theme.colors.action.disabledText,\n      border: `1px solid ${theme.colors.action.disabledBackground}`,\n      '&:focus': {\n        boxShadow: 'none',\n      },\n    }),\n    addon: css({\n      label: 'input-addon',\n      display: 'flex',\n      justifyContent: 'center',\n      alignItems: 'center',\n      flexGrow: 0,\n      flexShrink: 0,\n      position: 'relative',\n\n      '&:first-child': {\n        borderTopRightRadius: 'unset',\n        borderBottomRightRadius: 'unset',\n        '> :last-child': {\n          borderTopRightRadius: 'unset',\n          borderBottomRightRadius: 'unset',\n        },\n      },\n\n      '&:last-child': {\n        borderTopLeftRadius: 'unset',\n        borderBottomLeftRadius: 'unset',\n        '> :first-child': {\n          borderTopLeftRadius: 'unset',\n          borderBottomLeftRadius: 'unset',\n        },\n      },\n      '> *:focus': {\n        /* we want anything that has focus and is an addon to be above input */\n        zIndex: 2,\n      },\n    }),\n    prefix: cx(\n      prefixSuffix,\n      css({\n        label: 'input-prefix',\n        paddingLeft: theme.spacing(1),\n        paddingRight: theme.spacing(0.5),\n        borderRight: 'none',\n        borderTopRightRadius: 'unset',\n        borderBottomRightRadius: 'unset',\n      })\n    ),\n    suffix: cx(\n      prefixSuffix,\n      css({\n        label: 'input-suffix',\n        paddingLeft: theme.spacing(1),\n        paddingRight: theme.spacing(1),\n        borderLeft: 'none',\n        borderTopLeftRadius: 'unset',\n        borderBottomLeftRadius: 'unset',\n        right: 0,\n      })\n    ),\n    loadingIndicator: css({\n      '& + *': {\n        marginLeft: theme.spacing(0.5),\n      },\n    }),\n  };\n});\n"],"names":[],"mappings":"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"}