import React, { forwardRef, useContext, InputHTMLAttributes, ForwardRefExoticComponent, ComponentProps, } from "react"; import classNames from "classnames"; import { FormGroupContext } from "../FormGroup/FormGroupContext"; import { bem } from "../../utilities/bem"; import { STATUS_VARIANT, THEME } from "../../types"; import { Box } from "../Box"; import { Icon, IconType } from "../Icon"; export enum INPUT_ICON_POSITION { LEFT = "left", RIGHT = "right", } const cn = "TextInput"; export interface InputBaseProps { ref?: any; as?: any; /** * Variant changes the border color of the input */ variant?: STATUS_VARIANT; /** * @deprecated * Choose with theme to use; product (light) or brand (dark) */ theme?: THEME; /** * Icon type enum to be placed inside of the input’s bounding box */ icon?: IconType; /** * Determine which side to put the icon */ iconPosition?: INPUT_ICON_POSITION; /** * Additional props for the icon */ iconProps?: ComponentProps; /** * When you use an icon along with the input, a wrapping div is added * around the input. If you need to apply specific styles on the wrapper, * then you will need to use `wrapperClassName`. */ wrapperClassName?: string; } export interface InputProps extends InputBaseProps, InputHTMLAttributes {} const Input: ForwardRefExoticComponent = forwardRef< HTMLInputElement, InputProps >( ( { as: Component = "input", className, wrapperClassName, icon, iconPosition = INPUT_ICON_POSITION.LEFT, iconProps = {}, id: idProp, type, variant: variantProp = STATUS_VARIANT.DEFAULT, theme: themeProp, disabled, ...rest }, ref, ) => { const isTextInput = type !== "radio" && type !== "checkbox"; const { id: idContext, variant: variantContext, theme: themeContext, } = useContext(FormGroupContext); const id = idContext || idProp; const variant = variantContext || variantProp; const theme = themeProp || themeContext; const inputClasses = classNames( isTextInput && bem(cn), bem(cn, { m: variant }), bem(cn, { m: theme }), disabled && bem(cn, { m: "disabled" }), icon && bem(cn, { m: `icon-${iconPosition}` }), className, ); const wrapperClasses = classNames( bem(cn, { e: "wrapper" }), wrapperClassName, ); const { className: iconClassName, color: iconColor = "gray-600", ...iconPropsRest } = iconProps; const iconClasses = classNames( bem(cn, { e: "icon" }), bem(cn, { e: "icon", m: iconPosition }), iconClassName, ); return isTextInput && icon ? ( ) : ( ); }, ); export { Input };